Ранее я задал вопрос о создании статической библиотеки с ОПИ и связывая его с программой, которая построена с GCC: c - Linking a PGI OpenACC-enabled library with gccс - Динамически связывая PGI OpenACC с поддержкой библиотеки с GCC
сейчас , У меня тот же вопрос, но динамически. Как я могу создать программу с gcc, тогда как моя библиотека динамически построена с помощью PGI?
А также, учитывая следующие факты:
Я хочу, чтобы оба признать тот же OpenMP прагму и процедуры тоже. Например, когда я использую критические области OpenMP в библиотеке, вся программа должна быть сериализована в этом разделе.
Прагмы OpenACC используются в библиотеке, которая была построена с помощью PGI.
Загрузить библиотеку, полностью динамичную в моем приложении. Я имею в виду использование
dlopen
, чтобы открыть lib иdlsym
, чтобы найти функции.Я также хочу, чтобы мои потоки могли одновременно обращаться к графическому процессору для передачи данных и/или вычислений. Подробнее см. В следующих фрагментах кода.
Например, строительство следующего Lib и основного кода выдает эту ошибку: call to cuMemcpyHtoDAsync returned error 1: Invalid value
Примечание: При создании следующих кодов, я намеренно использовал LibGOMP (-lgomp
) вместо библиотеки OpenMP PGI (в -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
Mai п Код:
#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, как описано в Мат мой предыдущий вопрос:
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
я делаю что-то не так? Правильны ли выше шаги?
Спасибо @ mat-colgrove. Извините за 'libctest.so'. Это была опечатка. В конце концов, я изменил его на libmyacc.so после копирования и вставки его здесь и работал. ** Однако **, я допустил ошибку в параметрах, переданных 'gcc'. Когда я включаю OpenMP с помощью '-fopenmp' на gcc (строка 3 в вашем ответе) и удаляю строку' omp critical' в библиотеке **, иногда ** она дает мне вызов 'call to cuMemFreeHost возвращенной ошибки 1: ошибка недопустимого значения'. – Millad
Попробуйте добавить «-nomp» в параметры PGI. Время работы PGI и GNU OpenMP несовместимо, что может вызвать проблемы. Обратите внимание, что, хотя это работает для меня, двоичный код периодически получает ошибку seg. Хотя это также произошло, когда я поставил макрографы вокруг кода OpenACC и построил с помощью только GNU, поэтому я не думаю, что это связано, и я еще не исследовал его. –
Спасибо Mat за помощь по этому вопросу. Я добавил '-nomp' для компиляции библиотеки. Однако, когда я вызываю свою функцию в библиотеке в цикле, я получаю ошибку «Ошибка сегментации». Я просто называю 'calculate_sum' как 1000 раз, но он останавливается с ошибкой на первой 7-й или 8-й итерации. Это то, что показывает мне GDB: [GDB Output] (https://paste.ee/p/fLfOw). Есть идеи? – Millad