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 unddlsym
, 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?
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
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. –
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