2016-07-07 7 views
1

Zuvor ich eine Frage in Bezug auf die Schaffung eine statischen Bibliothek mit PGI gefragt und es zu einem Programm verknüpft, die mit gcc gebaut: c - Linking a PGI OpenACC-enabled library with gccc - Verknüpfung dynamisch eine PGI OpenACC-aktivierte Bibliothek mit gcc

Jetzt Ich habe die gleiche Frage, aber dynamisch. Wie kann ich ein Programm mit gcc erstellen, während meine Bibliothek dynamisch mit PGI gebaut ist?

Und auch, wenn man bedenkt folgende Fakten:

  • Ich möchte beide zu gleichen OpenMP Pragma und Routinen zu erkennen. Wenn ich beispielsweise kritische Bereiche von OpenMP in der Bibliothek verwende, sollte das gesamte Programm in diesem Bereich serialisiert werden.

  • OpenACC-Pragmas werden in der Bibliothek verwendet, die mit PGI erstellt wurde.

  • Laden Sie die Bibliothek vollständig dynamisch in meiner Anwendung. Ich meine mit dlopen zu öffnen lib und dlsym, um Funktionen zu finden.

  • Ich möchte auch meine Threads in der Lage sein, gleichzeitig GPU für Datentransfer und/oder Berechnungen zugreifen. Weitere Informationen finden Sie in den folgenden Codeschnipsel.

Zum Beispiel Gebäude folgende lib und Hauptcode aussendet, diesen Fehler: call to cuMemcpyHtoDAsync returned error 1: Invalid value


Hinweis: Wenn folgenden Codes erstellen, I LibGOMP (-lgomp) anstelle von PGI OpenMP Bibliothek absichtlich verwendet (-lpgmp) für beide Fälle, lib und main.


Lib Code:

#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; 
} 

Eingebaute Bibliothek mit folgenden Befehle:

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


Mai n Code:

#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; 
} 

Und baute mein Haupt-Code mit dem Befehl folgenden gcc wie von Mat in meiner vorherigen Frage beschrieben:

gcc f1.c -L/opt/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


Bin ich etwas falsch? Sind die obigen Schritte korrekt?

Antwort

1

Ihr Code funktioniert richtig für mich. Ich habe versucht, das zu verwenden, was Sie aufgelistet haben, aber ich musste das "libctest.so" entfernen, den Speicherort für dlopen ändern und "-DN = 1024" in der gcc-Kompilierungszeile hinzufügen. Danach kompilierte es und lief gut.

% 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

Dank @ Mat-Colgrove. Tut mir leid über 'libctest.so'. Es war ein Tippfehler. An meinem Ende habe ich es nach dem Kopieren in "libymacc.so" geändert und hier eingefügt. ** Allerdings **, habe ich einen Fehler bei Optionen gemacht, die an 'gcc' weitergegeben wurden. Wenn ich OpenMP mit '-fopenmp' auf gcc (Zeile 3 auf Ihrer Antwort) aktiviere und 'omp critical' Zeile in der Bibliothek entferne, ** manchmal ** gibt es mir' Aufruf an cuMemFreeHost Fehler 1: Ungültiger Wert' Fehler. – Millad

+1

Versuchen Sie "-nomp" zu den PGI-Optionen hinzuzufügen. Die OpenMP-Laufzeit von PGI und GNU ist nicht kompatibel, was möglicherweise zu Ihrem Problem führt. Beachten Sie, dass, während dies für mich funktioniert, die Binärdatei in regelmäßigen Abständen einen Seg-Fehler erhält. Dies geschah jedoch auch, als ich Makro-Wachen um den OpenACC-Code herumstellte und nur mit GNU baute, also glaube ich nicht, dass es verwandt ist, noch habe ich weiter nachforschen. –

+0

Danke Mat für Ihre Hilfe zu dieser Frage. Ich habe "-nomp" hinzugefügt, um die Bibliothek zu kompilieren. Wenn ich jedoch in einer Schleife meine Funktion in der Bibliothek anrufe, erhalte ich den Fehler "Segmentierungsfehler". Ich rufe einfach 'calculate_sum' wie 1000 Mal auf, aber es stoppt mit Fehler bei der ersten siebten oder achten Iteration. Das zeigt mir GDB: [GDB Ausgabe] (https://paste.ee/p/fLfOw). Irgendwelche Ideen? – Millad

Verwandte Themen