我正在尝试使用 python 通过 ctypes 来控制 cuda。在这里,为了说明我的问题,我使用 python 将指针传递给分配 cuda 内存的 c 函数,将 numpy 数组复制到 cuda 内存,并将 cuda 内存复制回新的 numpy 数组。但它似乎不起作用,尽管我的基本 ctypes 设置工作正常。我认为问题在于从 cudaMalloc 函数返回到 python 的内容。
这是python代码
pycu_alloc = dll.alloc_gpu_mem
pycu_alloc.argtypes = [c_size_t]
pycu_alloc.restypes = [c_void_p]
host2gpu = dll.host2gpu
host2gpu.argtypes = [c_void_p, c_void_p, c_size_t]
gpu2host = dll.gpu2host
gpu2host.argtypes = [c_void_p, c_void_p, c_size_t]
a = np.random.randn(1024).astype('float32')
c = np.zeros(1024).astype('float32')
c_a = c_void_p(a.ctypes.data)
c_c = c_void_p(c.ctypes.data)
da = pycu_alloc(1024)
c_da = c_void_p(da)
host2gpu(c_a, c_da, 1024)
gpu2host(c_c, c_da, 1024)
print a
print c
和 C:
extern "C" {
float * alloc_gpu_mem( size_t N)
{
float *d;
int size = N *sizeof(float);
int err;
err = cudaMalloc(&d, size);
printf("cuda malloc: %d\n", err);
return d;
}}
extern "C" {
void host2gpu(float * a, void * da, size_t N)
{
int size = N * sizeof(float);
int err;
err = cudaMemcpy(da, a, size, cudaMemcpyHostToDevice);
printf("load mem: %d\n", err);
}}
extern "C"{
void gpu2host(float *c, void *d_c, size_t N)
{
int err;
int size = N*sizeof(float);
err = cudaMemcpy(c, d_c, size, cudaMemcpyDeviceToHost);
printf("cpy mem back %d\n", err);
}}
代码应该将一个随机 vector a
复制到cuda内存,然后将该cuda内存复制回一个空 vector c
。当我打印 c
时,我想,它只是 0
s。
我曾尝试过 float*
和 void*
的不同可能性,尤其是 alloc_gpu_mem
的工作方式。但我不知道该怎么办。
至于err
返回值,cudaMalloc
返回0
但cudaMemcpy
都返回11。
python 对指针做错了什么?帮助?
最佳答案
问题出在这里:
pycu_alloc.restypes = [c_void_p]
这没有做任何事情。你想要的是:
pycu_alloc.restype = c_void_p
参见 Return types在 ctypes
文档中。
如果没有它,ctypes
会假定您的函数返回一个 C int
。在 32 位平台上,您可能会侥幸逃脱,因为您最终构建了一个 c_void_p
,其值为 int
...但在 64 位平台上,指针将以缺少高 32 位结束。
因此,当您将其传递给 CUDA 时,它会识别出指针不在它知道的任何范围内,并返回给您一个 cudaErrorInvalidValue
(11)。
另外,如果你做对了,这一行应该是不必要的:
c_da = c_void_p(da)
你正在调用一个函数,它的 argtypes
指定了 c_void_p
,所以你可以将一个 int
传递给它,你从一个 c_void_p
-返回函数就好了。
您可以看到与普通旧版 malloc
和 free
相同的行为,除了您可能会在 free
而不是一个不错的错误:
malloc = libc.malloc
malloc.argtypes = [c_size_t]
malloc.restype = c_void_p # comment this line to crash on most 64-bit platforms
free = libc.free
free.argtypes = [c_void_p]
free.restype = None
a = malloc(1024)
free(a) # commenting this line and uncommenting the next two has no effect
#c_a = c_void_p(a)
#free(ca)
关于python - 在带有 ctypes 的 cuda 分配内存上使用 python 句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20623811/