python - 在带有 ctypes 的 cuda 分配内存上使用 python 句柄

标签 python c cuda ctypes void-pointers

我正在尝试使用 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 时,我想,它只是 0s。

我曾尝试过 float*void* 的不同可能性,尤其是 alloc_gpu_mem 的工作方式。但我不知道该怎么办。

至于err 返回值,cudaMalloc 返回0cudaMemcpy 都返回11。

python 对指针做错了什么?帮助?

最佳答案

问题出在这里:

pycu_alloc.restypes = [c_void_p]   

这没有做任何事情。你想要的是:

pycu_alloc.restype = c_void_p

参见 Return typesctypes 文档中。

如果没有它,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-返回函数就好了。


您可以看到与普通旧版 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)

关于python - 在带有 ctypes 的 cuda 分配内存上使用 python 句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20623811/

相关文章:

c# - 在 GPU 全局内存中存储选择性元素

c++ - 第一个 cudaMalloc(K40 vs K20)的缓慢,即使在 cudaSetDevice 之后

python - python 脚本中的自动完成文件名

python - 我的EBNF逻辑错了吗?

c++ - Ubuntu 不提供包含 uint24_t 类型的 Clang 的 stdint

c - 为什么我会遇到此代码的段错误?

cuda - CUDA 中 3D 矩阵的列和行的 1D FFT

python - 在 Windows 上出现 UnicodeDecodeError,但在 Mac 上运行完全相同的代码时不会出现

python - 如何使用 Selenium 和 Python 处理 try 循环中的错误

c - 前缀和的并行化 (Openmp)