首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在Delphi程序中使用CUDA调用运行C函数

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

Stack Overflow用户
提问于 2018-04-10 10:02:41
回答 2查看 748关注 0票数 3

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

C/Cuda文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* 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;
}

pascal主文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// this is the "progpas.pas" file
program progpas;
{$mode objfpc}{$H+}
uses unitpas;

var
    ...


begin
    ...
    func(a, b, c, len);
    ...
end.

pascal单元文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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.

我找到了这篇文章Programming CUDA using Delphi or FreePascal ,但它展示了在德尔菲中编写CUDA程序的更多方法。

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

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

我正在使用Linuxubuntu16.04LTS,但如果必要的话,我还在windows中使用了CUDA和VS。

注意:如果你们能详细解释一下怎么做的话,会有帮助的( pascal和链接文件)

我已经尝试过生成.o对象文件,并将其链接到免费pascal中

$ nvcc progcuda.cu -c -o progcuda.o然后$fpc progpas.pas

但它在连接方面失败了。

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

注意:新帐户在堆栈溢出,我还不能回复答案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-10 11:23:57

我对德尔福和FreePascal一无所知,但我确实了解数据自动化系统、C和C++,所以也许我的解决方案也适用于你。

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

f.cu含量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int f() { return 42; }

main.c含量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
extern int f();

int main() {
    return f();
}

以下工作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ gcc -c -xc f.cu # need -xc to tell gcc it's a C file
$ gcc main.c f.o
(no errors emitted)

现在,当我们尝试用gcc替换nvcc

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ 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

这看起来更好,没有奇怪的错误,但它仍然没有找到函数f。这是因为nvccf.cu视为一个C++文件,因此它在创建对象文件时确实会命名故障,我们必须指定f具有C,而不是C++链接(请参阅更多信息:linkage)。要做到这一点,我们必须像这样修改f.cu

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
extern "C" int f() { return 42; }

现在,当我们这样做:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ nvcc -c f.cu
$ gcc main.c f.o -L/opt/cuda/lib64 -lcudart
(no errors emitted)

我希望你能设法修改这个来使用你的语言。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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;
}

在编译时,我得到了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ nvcc -c f.cu
$ gcc main.c f.o -L/opt/cuda/lib64 -lcudart -lstdc++
$ ./a.out
Running kernel
票数 5
EN

Stack Overflow用户

发布于 2018-04-11 08:33:51

我将文件修改为@Goran解释:将extern "C" int func(...);添加到.cu文件中。然后尝试编译/链接.cu代码,但是没有设备调用(使用设备代码),而且都运行良好。

但是,当我添加设备调用( foo<<<Nb,Nt>>>(...) )并使用以下方法编译时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$nvcc progcuda.cu -c
$fpc progpas.pas -ofinal.exe -Fl/usr/local/cuda/lib64

我得到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Free Pascal Compiler version 3.0.4 [2017/12/13] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling prog1.pas
Linking sum.exe
/usr/bin/ld: aviso: link.res contém seções de saída; você se esqueceu -T?
/usr/bin/ld: sum.o: undefined reference to symbol '_Unwind_Resume@@GCC_3.0'
//lib/x86_64-linux-gnu/libgcc_s.so.1: error adding symbols: DSO missing from command line
prog1.pas(16,1) Error: Error while linking
prog1.pas(16,1) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode

所以还是有漏掉的唇语。

解决方案:

发现将stdc++和gcc_s库链接到pascal解决了编译问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
unit unitpas;
// file "unitpas.pas"
{$LINK progcuda.o}
{$LINKLIB c}
{$LINKLIB cudart}
{$linklib stdc++}
{$linklib gcc_s}

interface

uses ctypes;
function func(x,y: cint32): cint32; cdecl; external;

implementation

end.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$nvcc progcuda.cu -c
$fpc progpas.pas -ofinal.exe -Fl/usr/local/cuda/lib64

一切都正常。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49760265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文