【问题标题】:c - Linking a PGI OpenACC-enabled library with gccc - 将启用 PGI OpenACC 的库与 gcc 链接
【发布时间】:2016-07-05 21:36:11
【问题描述】:

简而言之,我的问题依赖于使用两个不同的编译器编译/构建文件(使用库),同时利用源文件中的 OpenACC 结构。

我有一个具有 OpenACC 结构的 C 源文件。它只有一个简单的函数来计算数组的总和:

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

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

    printf("Num devices: %d\n", acc_get_num_devices(acc_device_nvidia));

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

    return sum;
}

我可以使用以下行轻松编译它:

pgcc -acc -ta=nvidia -c libmyacc.c

然后,通过以下行创建一个静态库:

ar -cvq libmyacc.a libmyacc.o

为了使用我的库,我写了一段代码如下:

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

#define N 1000

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

int main() {
    printf("Hello --- Start of the main.\n");
    double *a = (double*) malloc(sizeof(double) * N);
    int i;
    for(i=0;i<N;i++) {
        a[i] = (i+1) * 1.0;
    }

    double sum = 0.0;
    for(i=0;i<N;i++) {
        sum += a[i];
    }
    printf("Sum: %.3f\n", sum);


    double sum2 = -1;
    sum2 = calculate_sum(N, a);
    printf("Sum2: %.3f\n", sum2);

    return 0;
}

现在,我可以使用这个带有 PGI 编译器本身的静态库来编译上面的源代码 (f1.c):

pgcc -acc -ta=nvidia f1.c libmyacc.a

它会完美执行。但是,对于 gcc,它有所不同。我的问题就在这里。如何使用 gcc 正确构建它?

感谢 Jeff 对这个问题的评论: linking pgi compiled library with gcc linker,现在我可以毫无错误地构建我的源文件 (f1.c),但是可执行文件会发出一些致命错误。

这是我用 gcc (f1.c) 编译源文件时使用的:

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 -lpgmp -lnuma -lpthread -lnspgc -lpgc -lm -lgcc -lc -lgcc -lmyacc

这是错误:

Num devices: 2
Accelerator Fatal Error: No CUDA device code available

感谢-v 选项,在使用 PGI 编译器编译 f1.c 时,我看到编译器调用了 PGI 和 NVidia 的许多其他工具(如 pgacclnknvlink)。


我的问题:

  1. 我是不是走错了路?我可以从 GCC 调用 PGI 编译库中的函数并在这些函数中使用 OpenACC 吗?
  2. 如果上面的回答是肯定的,我可以使用没有 PGI 采取的步骤(调用 pgacclnknvlink)的静止链接吗?
  3. 如果上面的回答也是肯定的,我该怎么办?

【问题讨论】:

    标签: gcc linker openacc pgi pgi-accelerator


    【解决方案1】:

    将“-ta=tesla:nordc”添加到您的 pgcc 编译中。默认情况下,PGI 对 GPU 代码使用运行时动态编译 (RDC)。然而,RDC 需要一个 gcc 不支持的额外链接步骤(使用 nvlink)。 “nordc”子选项禁用 RDC,因此您将能够在库中使用 OpenACC 代码。但是,通过禁用 RDC,您将无法再从计算区域调用外部设备例程。

    % pgcc -acc -ta=tesla:nordc -c libmyacc.c
    % ar -cvq libmyacc.a libmyacc.o
    a - libmyacc.o
    % 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 -lpgmp -lnuma -lpthread -lnspgc -lpgc -lm -lgcc -lc -lgcc -lmyacc
    % a.out
    Hello --- Start of the main.
    Sum: 500500.000
    Num devices: 8
    Sum2: 500500.000
    

    希望这会有所帮助, 垫子

    【讨论】:

    • 谢谢垫。绝对是我想要的。
    • 请问最后一句中的“外部设备例程”是什么意思?您指的是 OpenACC 中的哪些功能?
    • 意味着从设备代码调用子程序,其中子程序位于不同的对象中。如果子程序在同一个源中,可以内联,但需要链接外部程序。
    • 亲爱的@MatColgrove,现在 NVHPC SDK 正在替换旧的 PGI 编译器,共享库似乎已经改变,我尝试了您在示例中使用的标志,但多个库报告找不到,你能再更新一次那行吗?我尝试自己做,但它导致托管内存功能丢失,并且我在运行时看到 700 错误
    • 是的,所有库名称都随着品牌重塑而改变。然而,一般来说,库会随着版本的不同而变化,因此最好查看编译器的详细“dryrun”输出以了解我们传递给链接器的内容。使用与行运行“nvc -dryrun x.o”相同的标志并查找链接(ld)命令。
    猜你喜欢
    • 2018-02-07
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多