我现在正在开发一个用 CUDA-Fortran 编码的项目。唯一可以编译 CUDA-Fortran 的编译器是 Portland group 的 pgfortran 编译器。但是我们发现了一个错误,即 pgfortran 编译器总是序列化 OMP 任务指令。简而言之:当使用 PGI 的编译器编译时,OMP TASK 不是并行的,而在使用 GNU 的编译器编译时是并行的。我们已将此情况报告给 PGI,但我们不确定修复该错误需要多长时间。所以现在我试图从 Fortran 程序(在 testF.cuf 中)调用一个 C 函数(更具体地说是一个 CUDA 函数)并将 OMP 任务指令放入 C 函数(在 cuda.cu 中),因为我们知道 gcc 的 omp任务工作正常。
testF.cuf:
external cfunction
...
cfunction( foo )
cuda.cu
extern "C" function_(Foo * foo){
#pragma omp parallel
{
...
#pragma omp single
{
...
#pragma omp task
{
...
}
}
}
}
结果是没有任何 OMP 指令的 Fortran 程序可以调用 C 函数并且 OMP 任务是并行的。但是一旦我们在 Fortran 代码中加入了任何 OMP 内容,或者在编译 Fortran 代码时只放置了一个 -mp 标志。C 文件中的 OMP 任务会以 PGI 的方式运行:序列化。如果我将 OMP 任务更改为 OMP 并行,结果将再次正确。这表明 pgfortran 会将 C 代码中的 OMP 链接到 pgfortran 的错误方式中。
这是我的Makefile:
myFtoCU: cuda.o testF.o
pgfortran cuda.o testF.o -o myFtoCU -Mcuda=5.0 -lstdc++ -lgomp
cuda.o: cuda.cu
nvcc -c cuda.cu -o cuda.o -Xcompiler -fopenmp -lgomp
testF.o: testF.cuf
pgfortran -c testF.cuf -Mcuda=5.0 -lstdc++ -lgomp -mp
clean: cuda.o testF.o myFtoCU
rm cuda.o testF.o ./myFtoCU
我想问题是当我将 cuda.o 和 testF.o 链接在一起时,链接器强制 cuda.o 中的 OMP 充当 pgfortran 的 OMP 任务,这是错误的。
那么有没有人知道如何正确链接这两个对象,同时保持 C( CUDA ) 函数更独立?