c-动态链接支持PGI OpenACC的库与gcc

c-动态链接支持PGI OpenACC的库与gcc,gcc,linker,openacc,pgi,pgi-accelerator,Gcc,Linker,Openacc,Pgi,Pgi Accelerator,之前,我问了一个关于使用PGI创建静态库并将其链接到使用gcc构建的程序的问题: 现在,我有同样的问题,但是动态地。当我的库是使用PGI动态构建的时,如何使用gcc构建程序 同时,考虑到以下事实: 我希望它们都能识别相同的OpenMP pragma和例程。例如,当我在库中使用OpenMP关键区域时,整个程序应该在该部分序列化 OpenACC pragmas用于使用PGI构建的库中 在我的应用程序中完全动态加载库。我的意思是使用dlopen打开lib和dlsym查找函数 我还希望我的线程能够同时

之前,我问了一个关于使用PGI创建静态库并将其链接到使用gcc构建的程序的问题:

现在,我有同样的问题,但是动态地。当我的库是使用PGI动态构建的时,如何使用gcc构建程序

同时,考虑到以下事实:

  • 我希望它们都能识别相同的OpenMP pragma和例程。例如,当我在库中使用OpenMP关键区域时,整个程序应该在该部分序列化

  • OpenACC pragmas用于使用PGI构建的库中

  • 在我的应用程序中完全动态加载库。我的意思是使用
    dlopen
    打开lib和
    dlsym
    查找函数

  • 我还希望我的线程能够同时访问GPU进行数据传输和/或计算。有关更多详细信息,请参阅以下代码段

例如,生成以下库和主代码时会发出以下错误:
调用cuMemcpyHtoDAsync返回错误1:无效值


注意:在构建以下代码时,我有意使用LibGOMP(
-lgomp
)而不是PGI的OpenMP库(
-lpgmp
),用于lib和main两种情况


库代码:

#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;
}
并使用gcc使用以下命令构建了我的主代码,如Mat在上一个问题中所述:

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



我做错什么了吗?以上步骤正确吗?

您的代码对我来说工作正常。我尝试使用您列出的内容,但需要删除“libctest.so”,更改dlopen获取so的位置,并在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

谢谢@mat colgrove。关于libctest.so的事很抱歉。那是个打字错误。在我这边,我把它改成了
libmyacc。所以
复制后,我把它粘贴到这里并开始工作。但是,我在传递给
gcc
的选项上犯了一个错误。当我使用gcc上的
-fopenmp
启用OpenMP(答案第3行)并删除库中的
omp critical
行时,有时它会调用cuMemFreeHost返回错误1:无效值错误。请尝试将“-nomp”添加到PGI选项中。PGI和GNU的OpenMP运行时不兼容,这可能会导致您的问题。请注意,虽然这对我有效,但二进制文件确实周期性地出现seg故障。不过,当我在OpenACC代码周围设置宏保护并仅使用GNU构建时,也出现了这种情况,因此我认为这与此无关,也没有进一步调查。感谢Mat在这个问题上的帮助。我添加了
-nomp
来编译库。但是,当我在循环中调用库中的函数时,会得到
分段错误
错误。我只需调用
calculate\u sum
1000次,但在第一次第7次或第8次迭代时,它会错误地停止。这是GDB向我展示的:。有什么想法吗?这是我的主要文件和库:
% 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