現在、CUDA-Fortran でコーディングされたプロジェクトに取り組んでいます。CUDA-Fortran をコンパイルできるコンパイラは、Portland グループの pgfortran コンパイラだけです。しかし、pgfortran コンパイラが常に OMP タスク ディレクティブをシリアル化するというバグが見つかりました。簡単に言えば、OMP TASK は、PGI のコンパイラでコンパイルすると並列化されませんが、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 の間違った方法にリンクすることを示唆しています。
ここに私のメイクファイルがあります:
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 )関数をより独立した状態に保ちながら、この2つのオブジェクトを正しくリンクするにはどうすればよいか知っている人はいますか?