我试图通过ctypes使用python来控制cuda.在这里,为了说明我的问题,我使用python将指针传递给c函数,这些函数分配cuda内存,将numpy数组复制到cuda mempory,并将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); }}
代码应该将随机向量复制a
到cuda内存,然后将该cuda内存复制回空向量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
见返回类型的ctypes
文档.
并且没有,ctypes
假设你的函数返回一个C int
.在32位平台上,你可能会侥幸成功,因为你最终会构造一个c_void_p
值为int
......但是在64位平台上,该指针最终会丢失高32位.
因此,当您将其传递给CUDA时,它会识别出指针不在它知道的任何范围内,并返回a 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)