在cuda上使用python句柄分配内存和ctypes

时间:2013-12-17 00:39:10

标签: python c cuda ctypes void-pointers

我正在尝试使用python来控制cuda,通过ctypes。在这里,为了说明我的问题,我使用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是什么?救命?

1 个答案:

答案 0 :(得分:5)

问题在于:

pycu_alloc.restypes = [c_void_p]   

这没有任何作用。你想要的是:

pycu_alloc.restype = c_void_p

请参阅ctypes文档中的Return types

如果没有,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 - 返回函数。< / p>


您可以看到普通旧mallocfree的相同行为,但您可能会在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)