使用Golang调用CUDA库

11

我正在尝试从我的Go代码中调用CUDA函数。 我有以下三个文件。

test.h:

int test_add(void);

test.cu:

__global__ void add(int *a, int *b, int *c){
       *c = *a + *b;
}

int test_add(void) {
       int a, b, c; // host copies of a, b, c
       int *d_a, *d_b, *d_c; // device copies of a, b, c
       int size = sizeof(int);
       // Allocate space for device copies of a, b, c
       cudaMalloc((void **)&d_a, size);
       cudaMalloc((void **)&d_b, size);
       cudaMalloc((void **)&d_c, size);
      // Setup input values
      a = 2;
      b = 7;

      // Copy inputs to device
      cudaMemcpy(d_a, &a, size, cudaMemcpyHostToDevice);
      cudaMemcpy(d_b, &b, size, cudaMemcpyHostToDevice);
      // Launch add() kernel on GPU
     add<<<1,1>>>(d_a, d_b, d_c);
     // Copy result back to host
     cudaMemcpy(&c, d_c, size, cudaMemcpyDeviceToHost);
     // Cleanup
     cudaFree(d_a); cudaFree(d_b); cudaFree(d_c);
    return 0;
}

test.go:

package main

import "fmt"

//#cgo CFLAGS: -I.
//#cgo LDFLAGS: -L. -ltest
//#cgo LDFLAGS: -lcudart
//#include <test.h>
import "C"


func main() {
     fmt.Printf("Invoking cuda library...\n")
     fmt.Println("Done ", C.test_add())
}

我正在使用以下工具编译CUDA代码:

nvcc -m64 -arch=sm_20 -o libtest.so --shared -Xcompiler -fPIC test.cu

所有三个文件 - test.h,test.cu和test.go都在同一个目录中。 当我尝试使用go构建时,出现的错误是“未定义对`test_add'的引用”。

我对C/C ++几乎没有经验,CUDA方面完全是新手。

我已经尝试解决这个问题两天了,非常感谢任何帮助。

谢谢。


3
我不熟悉 Go 语言,但可能是 C 和 C++ 链接的问题。尝试将你的 test_add() 原型用 extern "C" { ... } 包装起来。 - Robert Crovella
@RobertCrovella:你在哪里看到 C 代码了?CUDA 是基于 C++ 的。 - too honest for this site
1
@Olaf,我在哪里说“我看到了C代码”?我知道CUDA使用C++风格的链接。如果偶然间go导入C期望以C风格的链接提供函数,那么你就会遇到这个问题。这只是一个猜测。 - Robert Crovella
@RobertCrovella:谢谢,老兄。我尝试了你的建议,它起作用了。你真是我的救星 :) - Peter Veselinović
3
感谢您在第一次发布问题时提供了一个 MCVE,这样做非常棒。 - Robert Crovella
1个回答

5
在这种情况下,似乎C语言的go导入希望函数提供C风格链接
CUDA(即nvcc)主要遵循C ++模式,并默认提供C ++风格链接(包括函数名重载等)。
可以使用extern "C"{...代码...}强制使代码段使用C而不是C ++风格链接从外部提供。这是C ++语言的一项功能,与CUDA或nvcc无关。
因此,通过对test.cu进行以下修改,似乎可以解决问题:
extern "C" { int test_add(void) { ... code ... }; }

对我来说,如果我在test.cu文件中使用extern "C"{...code...},解决方案就可以工作。但是,如果我在头文件test.h中包含extern "C",我会收到一个错误./test.h:1:8: error: expected identifier or '(' before string constant。因此,我将使用在cuda文件(.cu)中的extern "C",这似乎对我有用。再次感谢您的帮助。 - Peter Veselinović
2
谢谢。我已经更新了答案以反映您的用法。虽然我不是这方面的专家,但我认为您的问题可能对未来的读者有用,作为一个规范的“如何将go连接到CUDA”的类型问题。 - Robert Crovella

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接