2016-07-07 6 views
1

とPGI OpenACC対応のライブラリをリンクし、gccで構築されているプログラムにリンク:今すぐc - Linking a PGI OpenACC-enabled library with gccCは - 動的に私はPGIと<strong>静的ライブラリ</strong>の作成に関する質問を、以前のgcc

、私は同じ質問がありますが、は動的にです。私のライブラリがで、動的にがPGIで構築されている間、gccでプログラムを構築するにはどうすればいいですか?

そしてまた、以下の事実を考慮:

  • 私はそれらの両方があまりにも同じOpenMPのプラグマおよびルーチンを認識します。たとえば、ライブラリでOpenMPクリティカルリージョンを使用する場合、そのセクションでプログラム全体をシリアル化する必要があります。

  • OpenACCプラグマは、PGIでビルドされたライブラリで使用されます。

  • アプリケーションでライブラリを完全に動的にロードします。私はlibを開くためにdlopenを使用し、機能を見つけるにはdlsymを使用することを意味します。

  • また、私のスレッドがデータ転送および/または計算のためにGPUに同時にアクセスできるようにします。詳細については、次のコードスニペットを参照してください。例えば

、libとメインコード次の建物は、このエラーを発する:call to cuMemcpyHtoDAsync returned error 1: Invalid value


注:以下のコードを構築するとき、私は意図的に(代わりに、PGIのOpenMPのライブラリーのLibGOMP(-lgomp)を使用し-lpgmp)(libとmainの両方)。


Libのコード:

#include <stdio.h> 
#include <stdlib.h> 
#include <openacc.h> 
#include <omp.h> 

double calculate_sum(int n, double *a) { 
    double sum = 0; 
    int i; 

    #pragma omp critical 
    { 
     printf("Num devices: %d\n", acc_get_num_devices(acc_device_nvidia)); 

     #pragma acc enter data copyin(a[0:n]) 

     #pragma acc parallel 
     #pragma acc loop 
     for(i=0;i<n;i++) { 
      sum += a[i]; 
     } 

     #pragma acc exit data delete(a[0:n]) 
    } 

    return sum; 
} 


int ret_num_dev(int index) { 
    int dev = acc_get_num_devices(acc_device_nvidia); 
    if(dev == acc_device_nvidia) 
     printf("Num devices: %d - Current device: %d\n", dev, acc_get_device()); 
    return dev; 
} 

次のコマンドで作成したライブラリ:

pgcc -acc -ta=nvidia:nordc -fPIC -c libmyacc.c

pgcc -shared -Wl,-soname,libctest.so.1 -o libmyacc.so -L/opt/pgi/linux86-64/16.5/lib -L/usr/lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -laccapi -laccg -laccn -laccg2 -ldl -lcudadevice -lgomp -lnuma -lpthread -lnspgc -lpgc -lm -lgcc -lc -lgcc libmyacc.o


舞Nコード:

#include <stdio.h> 
#include <stdlib.h> 
#include <omp.h> 
#include <dlfcn.h> 


#define N 1000 

// to make sure library is loaded just once for whole program 
static void *lib_handle = NULL; 
static int lib_loaded = 0; 
static double (*calculate_sum2)(int , double *); 

void call_lib_so() { 

    // load library just once and init the function pointer 
    // to function in the library. 
    if(lib_loaded == 0) { 
     lib_loaded = 1; 
     char *error; 

     lib_handle = dlopen("/home/millad/temp/gcc-pgi/libmyacc.so", RTLD_NOW); 
     if (!lib_handle) { 
      fprintf(stderr, "%s\n", dlerror()); 
      exit(1); 
     } 

     calculate_sum2 = (double (*)(int , double *)) dlsym(lib_handle, "calculate_sum"); 
     if ((error = dlerror()) != NULL) { 
      fprintf(stderr, "%s\n", error); 
      exit(1); 
     } 
    } 


    // execute the function per call 
    int n = N, i; 
    double *a = (double *) malloc(sizeof(double) * n); 
    for(i=0;i<n;i++) 
     a[i] = 1.0 * i; 
    double sum = (*calculate_sum2)(n, a); 
    free(a); 
    printf("-------- SUM: %.3f\n", sum); 



// dlclose(lib_handle); 
} 


extern double calculate_sum(int n, double *a); 

int main() { 

    // allocation and initialization of an array 
    double *a = (double*) malloc(sizeof(double) * N); 
    int i; 
    for(i=0;i<N;i++) { 
     a[i] = (i+1) * 1.0; 
    } 

    // access and run OpenACC region with all threads 
    #pragma omp parallel 
    call_lib_so(); 

    return 0; 
} 

そして、私の前の質問にマットによって記載されているようにはgccを使用して、次のコマンドを使用して、私の主なコードを構築しました:

​​


私が何か間違ったことをやっていますか?上記の手順は正しいですか?

答えて

1

コードは正しく動作します。私はリストしたものを使用しようとしましたが、 "libctest.so"を削除する必要がありました.dlopenがそうする場所を変更し、gccコンパイル行に "-DN = 1024"を追加します。その後、コンパイルして正常に動作しました。

% pgcc -acc -ta=nvidia:nordc -fPIC -c libmyacc.c -V16.5        
% pgcc -shared -o libmyacc.so -L/opt/pgi/linux86-64/16.5/lib -L/usr/lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -laccapi -laccg -laccn -laccg2 -ldl -lcudadevice -lgomp -lnuma -lpthread -lnspgc -lpgc -lm -lgcc -lc -lgcc libmyacc.o -V16.5 
% gcc f1.c -L/proj/pgi/linux86-64/16.5/lib -L/usr/lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L. -laccapi -laccg -laccn -laccg2 -ldl -lcudadevice -lgomp -lnuma -lpthread -lnspgc -lpgc -lm -lgcc -lc -lgcc -lmyacc -DN=1024 
% ./a.out 
Num devices: 8 
-------- SUM: 523776.000 
+0

Thanks @ mat-colgrove。 'libctest.so'については申し訳ありません。それはタイプミスでした。私の最終的には、ここでコピー&ペーストしてlibmyacc.so'に変更して働きました。 **しかし、**、私は 'gcc'に渡されたオプションについて間違いを犯しました。 gcc上の '-fopenmp'(3行目)をOpenMPで有効にし、ライブラリ内の' omp critical'行を削除すると**時には 'cuMemFreeHostがエラー1を返しました:無効な値'エラーが表示されます。 – Millad

+1

PGIオプションに "-nomp"を追加してみてください。 PGIとGNUのOpenMPランタイムは互換性がないため、問題の原因となっている可能性があります。これは私にとっては効果的ですが、バイナリは定期的にsegフォールトを取得することに注意してください。しかし、これはOpenACCコードの周りにマクロガードを置いて、ちょうどGNUだけで構築されているので、関連しているとは思っていません。 –

+0

ありがとうございました。ライブラリをコンパイルするために '-nomp'を追加しました。しかし、私が関数をライブラリ上でループで呼び出すと、 'Segmentation fault'というエラーが出ます。私は単純に 'calculate_sum'を1000回のように呼び出しますが、最初の7回目または8回目の反復でエラーで停止します。これはGDBが私に示すものです:[GDB Output](https://paste.ee/p/fLfOw)。何か案は? – Millad

関連する問題