You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用nvc++运行带OpenACC的C++程序报错libgomp: TODO求助

使用nvc运行带OpenACC的C程序时出现libgomp: TODO错误的解决思路

问题概述

使用nvc编译运行包含OpenACC的C程序时,出现libgomp: TODO运行错误,同时编译输出中出现Generating implicit copyin(duplicate.step.p[:1],srcImg.step.p[:1],srcImg,duplicate)[if not already present]的提示,已尝试显式为srcImg分配GPU内存,但问题仍存在。

测试代码

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <openacc.h>

using namespace std;
using namespace cv;

int main(){
  cv::Mat srcImg=cv::imread("/home/testSpace/images/blue-mountains.jpg");
  if(!srcImg.data){
   cout<<"The file is not loaded or does not exist"<<endl;
   return -1;
  }

    cout<<"Matrix"<<srcImg.rows<<" "<<srcImg.cols<<endl;
    Mat duplicate(srcImg.rows,srcImg.cols, CV_8UC1,Scalar::all(255) );

    #pragma acc enter data copyin(srcImg[:srcImg.rows][:srcImg.cols])
    #pragma acc enter data copyin(duplicate[:duplicate.rows][:duplicate.cols])

    #pragma acc parallel
    {
     #pragma acc loop
     for(int i=0;i<srcImg.rows;i++){
     #pragma acc loop
     for(int j=0;j<srcImg.cols;j++){
       duplicate.at<uchar>(i,j)=srcImg.at<uchar>(i,j);
    }
   }

   #pragma acc data copyout(duplicate[:duplicate.rows][:duplicate.cols])
   #pragma acc data copyout(srcImg[:srcImg.rows][:srcImg.cols])
 }

   cout<<"duplicate"<<": "<<(int)duplicate.at<uchar>(23,45)<<endl;
   return 0;
}

编译输出

main:
    2216, Loop unrolled 4 times (completely unrolled)

 36, Generating enter data copyin(duplicate,srcImg)

     Generating NVIDIA GPU code

     38, #pragma acc loop gang /* blockIdx.x */

     40, #pragma acc loop vector(128) /* threadIdx.x */

 36, Generating implicit copyin(duplicate.step.p[:1],srcImg.step.p[:1],srcImg,duplicate)[if not already present]

 40, Loop is parallelizable

     Loop not vectorized/parallelized: not countable

cv::Matx<double, (int)4, (int)1>::Matx():

运行结果

Matrix810 1440
libgomp: TODO

编译命令

nvc++ -g -O3 -acc -gpu=cc60,cc70 -Minfo `pkg-config opencv4 --cflags --libs` -nomp -o nvcpp.out  test.cpp

问题分析与解决建议

1. 隐式copyin提示的原因

cv::Mat是包含元数据(rows、cols、step等)和数据指针(data)的结构体。你使用srcImg[:srcImg.rows][:srcImg.cols]的写法,编译器会误解为复制结构体的切片,而非实际图像数据。当GPU代码需要访问step.p等结构体成员时,编译器会自动生成隐式copyin操作,将这些元数据复制到GPU。

2. libgomp: TODO错误的原因

尽管添加了-nomp参数,但代码中可能存在触发OpenMP运行时调用的逻辑,或者nvc++在特定场景下仍会链接libgomp库。另外,OpenACC数据区域的使用错误也可能间接导致该问题:

  • 嵌套使用#pragma acc data指令(parallel区域内又定义copyout),违反OpenACC数据区域的使用规则。
  • 使用Mat::at()成员函数在GPU区域内,该函数包含主机端的边界检查逻辑,无法在设备上正确执行。
  • 数据区域的范围指定错误,未正确复制图像的实际数据。

3. 具体修复步骤

  • 修正数据区域的写法:显式复制cv::Mat结构体和实际数据:

    // 先复制结构体元数据
    #pragma acc enter data copyin(srcImg, duplicate)
    // 再复制图像数据
    #pragma acc enter data copyin(srcImg.data[:srcImg.rows * srcImg.cols], duplicate.data[:duplicate.rows * duplicate.cols])
    
  • 替换Mat::at()为直接指针访问:在GPU区域内避免使用成员函数,直接通过数据指针计算偏移:

    uchar* src_data = srcImg.data;
    uchar* dup_data = duplicate.data;
    int src_step = srcImg.step;
    int dup_step = duplicate.step;
    
    #pragma acc parallel present(srcImg, duplicate, src_data, dup_data, src_step, dup_step)
    {
        #pragma acc loop gang vector(128) collapse(2)
        for(int i=0; i<srcImg.rows; i++){
            for(int j=0; j<srcImg.cols; j++){
                dup_data[i * dup_step + j] = src_data[i * src_step + j];
            }
        }
    }
    
  • 修正数据区域生命周期:将copyout操作移到parallel区域外,使用exit data指令:

    #pragma acc exit data copyout(duplicate.data[:duplicate.rows * duplicate.cols])
    // 不需要copyout srcImg,因为是只读输入
    #pragma acc exit data delete(srcImg, duplicate, src_data, dup_data, src_step, dup_step)
    
  • 确保禁用OpenMP运行时:改用-mp=noopenmp参数替代-nomp,强制不链接libgomp:

    nvc++ -g -O3 -acc -gpu=cc60,cc70 -Minfo `pkg-config opencv4 --cflags --libs` -mp=noopenmp -o nvcpp.out  test.cpp
    
  • 验证GPU架构匹配:确认编译时指定的cc60,cc70与实际使用的GPU架构一致,若架构不匹配,会导致运行时错误。

内容的提问来源于stack exchange,提问作者Lance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:01:22