在Delphi程序中使用CUDA调用运行C函数

joã*_*.f. 3 c cuda freepascal

我的目标是有一个Delphi(或freepascal)代码,它将像这样调用C函数func:

C/Cuda文件:

/* this is the "progcuda.cu" file */
#include <stdio.h>

__global__ void foo(int *a, int *b, int *c, int n){
    /*
    add all the vector's element
    */
}


void func(int *a, int *b, int *c,int n){
    int *da,*db,*dc;
    cudaMalloc(&da, n*sizeof(int));
    cudaMalloc(&db, n*sizeof(int));
    cudaMalloc(&dc, n*sizeof(int));

    cudaMemcpy(da,a,sizeof(int)*n,cudaMemcpyHostToDevice);
    cudaMemcpy(db,b,sizeof(int)*n,cudaMemcpyHostToDevice);
    cudaMemcpy(dc,c,sizeof(int)*n,cudaMemcpyHostToDevice);

    foo<<<1,256>>>(da,db,dc);
    cudaMemcpy(c,dc,sizeof(int),cudaMemcpyDeviceToHost);

    /* do other stuff and call another Host and Device functions*/

    return;
}
Run Code Online (Sandbox Code Playgroud)

pascal主文件:

// this is the "progpas.pas" file
program progpas;
{$mode objfpc}{$H+}
uses unitpas;

var
    ...


begin
    ...
    func(a, b, c, len);
    ...
end.
Run Code Online (Sandbox Code Playgroud)

pascal单元文件:

// this is the "unitpas.pas" file
unit unitpas;
{$link progcuda.o}
interface

uses ctypes;
procedure func(a, b, c : cpint32 , n:cint32); cdecl; external;
procedure foo(a, b, c : cpint32 , n:cint32);cdecl; external;

implementation

end.
Run Code Online (Sandbox Code Playgroud)

我发现这篇文章使用Delphi或FreePascal编程CUDA,但它显示了更多在delphi中编写CUDA 的方法.

我不想在Delphi中编写CUDA,我想用纯C/C++代码在CUDA中编程,只在delphi中调用那个C函数.

问题是什么?如何将.cu代码链接到delphi?

我正在使用linux ubuntu 16.04 LTS,但如果有必要,我还在Windows中使用CUDA和VS.

注意:如果你们可以详细解释如何做到这一点,会有所帮助(对pascal和链接文件不熟悉)


我已经尝试生成.o对象文件并将其链接到free pascal
$ nvcc progcuda.cu -c -o progcuda.o然后$fpc progpas.pas
但它在链接时失败了.

注意:我曾经尝试过将C代码生成的普通.o链接到pascal代码,使用gcc和freepascal编译器,并且它有效,但如果我使用nvcc而不是gcc并将扩展名重命名为.cu(仍然是相同的代码) ),链接失败.


注意:堆栈溢出的新帐户,我无法回复答案.

Gor*_*gar 5

我对Delphi和FreePascal一无所知,但我确实知道CUDA,C和C++,所以也许我的解决方案也适合你.

我将用一个简单的问题来演示它:

内容f.cu:

int f() { return 42; }
Run Code Online (Sandbox Code Playgroud)

内容main.c:

extern int f();

int main() {
    return f();
}
Run Code Online (Sandbox Code Playgroud)

以下作品:

$ gcc -c -xc f.cu # need -xc to tell gcc it's a C file
$ gcc main.c f.o
(no errors emitted)
Run Code Online (Sandbox Code Playgroud)

现在,当我们尝试替换gccnvcc:

$ nvcc -c f.cu
$ gcc main.c f.o
/tmp/ccI3tBM1.o: In function `main':
main.c:(.text+0xa): undefined reference to `f'
f.o: In function `__cudaUnregisterBinaryUtil()':
tmpxft_0000704e_00000000-5_f.cudafe1.cpp:(.text+0x52): undefined reference to `__cudaUnregisterFatBinary'
f.o: In function `__nv_init_managed_rt_with_module(void**)':
tmpxft_0000704e_00000000-5_f.cudafe1.cpp:(.text+0x6d): undefined reference to `__cudaInitModule'
f.o: In function `__sti____cudaRegisterAll()':
tmpxft_0000704e_00000000-5_f.cudafe1.cpp:(.text+0xa9): undefined reference to `__cudaRegisterFatBinary'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

这里的问题是nvcc在编译时添加对CUDA运行时API中某些符号的引用f.cu,并且这些符号必须链接到最终的可执行文件.我的CUDA安装在/opt/cuda,所以我将使用它,但您必须将其替换为系统上安装CUDA的任何地方.因此,如果我们libcudart.so在编译库时链接,我们得到:

$ nvcc -c f.cu
$ gcc main.c f.o -L/opt/cuda/lib64 -lcudart
/tmp/ccUeDZcb.o: In function `main':
main.c:(.text+0xa): undefined reference to `f'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

这看起来更好,没有奇怪的错误,但它仍然没有找到功能f.那是因为它nvccf.cu视为一个C++文件,因此它在创建目标文件时会命名为mangling,我们必须指定我们想要fC,而不是C++链接(详见http://en.cppreference.com)/w/cpp/language/language_linkage).要做到这一点,我们必须f.cu像这样修改:

extern "C" int f() { return 42; }
Run Code Online (Sandbox Code Playgroud)

现在我们这样做:

$ nvcc -c f.cu
$ gcc main.c f.o -L/opt/cuda/lib64 -lcudart
(no errors emitted)
Run Code Online (Sandbox Code Playgroud)

我希望你设法修改它以使用你的语言.

编辑:我尝试了一些更复杂的例子:

// f.cu
#include <stdio.h>

__global__ void kernel() {
    printf("Running kernel\n");
}

extern "C" void f() {
    kernel<<<1, 1>>>();
    // make sure the kernel completes before exiting
    cudaDeviceSynchronize();
}

// main.c
extern void f();

int main() {
    f();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译时我得到了:

    f.o:(.data.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

要修复它,您还需要将标准C++库添加到链接器标志:

$ nvcc -c f.cu
$ gcc main.c f.o -L/opt/cuda/lib64 -lcudart -lstdc++
$ ./a.out
Running kernel
Run Code Online (Sandbox Code Playgroud)