Pycuda 在函数参数中按值声明数组时返回错误

Posted

技术标签:

【中文标题】Pycuda 在函数参数中按值声明数组时返回错误【英文标题】:Pycuda returns error when declaring array with size by value in function parameter 【发布时间】:2021-11-30 17:18:54 【问题描述】:

使用int d[1]; 尝试以下代码时,它可以正常工作,但使用int d[in_integer];int c[in_matrix[0]]; 会导致nvcc 编译失败。我可以看看是否有人可以建议为什么?是否可以在pycuda中声明数组,其大小由函数参数值决定?

import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import os
import numpy as np

_path = r"D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\bin\Hostx64\x64"

if os.system("cl.exe"):
    os.environ['PATH'] += ';' + _path
if os.system("cl.exe"):
    raise RuntimeError("cl.exe still not found, path probably incorrect")

a = np.asarray([1, 2])
a = a.astype(np.int32)
a_gpu = cuda.mem_alloc(a.nbytes)
cuda.memcpy_htod(a_gpu, a)

b = np.zeros(1).astype(np.int32)
b_gpu = cuda.mem_alloc(b.nbytes)
cuda.memcpy_htod(b_gpu, b)

mod = SourceModule("""
  __global__ void array_declaration(int *in_matrix, int *out_matrix, int in_integer)
  
    int d[1];
    //int d[in_integer];
    //int d[in_matrix[0]];
    out_matrix[0] = in_matrix[0];
  
  """)
      
func = mod.get_function("array_declaration")
func(a_gpu, b_gpu, np.int32(1), block=(1,1,1))

b_out = np.empty_like(b)
cuda.memcpy_dtoh(b_out, b_gpu)
print(b_out)

错误如下

Traceback (most recent call last):

  File "D:\PythonProjects\TradeAnalysis\Test\TestCUDAArrayDeclaration.py", line 37, in <module>
    """)

  File "D:\ProgramData\Anaconda3\lib\site-packages\pycuda\compiler.py", line 291, in __init__
    arch, code, cache_dir, include_dirs)

  File "D:\ProgramData\Anaconda3\lib\site-packages\pycuda\compiler.py", line 254, in compile
    return compile_plain(source, options, keep, nvcc, cache_dir, target)

  File "D:\ProgramData\Anaconda3\lib\site-packages\pycuda\compiler.py", line 137, in compile_plain
    stderr=stderr.decode("utf-8", "replace"))

CompileError: nvcc compilation of C:\Users\HENRYC~1\AppData\Local\Temp\tmpy0kcq_5i\kernel.cu failed

【问题讨论】:

你能分享一下你那里的编译错误吗? C++ 以及扩展的 CUDA 不支持动态大小的数组。它们必须是静态大小的。这就是代码无法编译的原因 【参考方案1】:

是否可以在pycuda中声明数组,大小由函数参数值决定?

而不是这个:

int d[in_integer];

这样做:

int *d = new int[in_integer];

或者,等效地:

int *d = (int *)malloc(in_integer*sizeof(d[0]));

从技术上讲,这是一个带有分配的指针,而不是一个数组,但对于 C++ 或 CUDA C++ 中的大多数用例,它的功能类似。

这种内核设备内存分配有很多注意事项:

默认情况下,内核使用的总分配空间(当前具有分配打开的线程数乘以分配大小)不能超过 8MB。 This is adjustable.

在您完成使用指针(或 free(),如果您使用了 malloc())后,您通常应该在内核代码中使用相应的 C++ delete[] 操作(这也可能对上述项目有所帮助)

CUDA 设备运行时通过返回 NULL 指针在此处指示分配错误。遇到问题时,最好在使用指针之前检查内核代码中的 NULL。

设备分配步骤本身会显着影响内核性能(执行持续时间)。如果您的内核正在做很多工作/许多其他事情,它可能根本不会引起注意。对于做很少工作的内核,它可能非常明显。分配完成后,使用分配的指针与使用大小称为编译时常量的数组定义不会有任何显着的性能差异。

【讨论】:

以上是关于Pycuda 在函数参数中按值声明数组时返回错误的主要内容,如果未能解决你的问题,请参考以下文章

javascript在嵌套对象/数组中按值查找

在lisp中按值传递参数

在NodeJS中按值排序数组

为啥我要在 C 中按值传递函数参数?

为啥要在 C 中声明一个只包含数组的结构?

从 ispc 导出的函数中按值返回结构?