Pycuda возвращает ошибку при объявлении массива с размером по значению в параметре функции

arrays #cuda #pycuda

#cuda #pycuda

Вопрос:

При попытке выполнить приведенный ниже код с 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 Studio2019CommunityVCToolsMSVC14.28.29910binHostx64x64"

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:PythonProjectsTradeAnalysisTestTestCUDAArrayDeclaration.py", line 37, in <module>
    """)

  File "D:ProgramDataAnaconda3libsite-packagespycudacompiler.py", line 291, in __init__
    arch, code, cache_dir, include_dirs)

  File "D:ProgramDataAnaconda3libsite-packagespycudacompiler.py", line 254, in compile
    return compile_plain(source, options, keep, nvcc, cache_dir, target)

  File "D:ProgramDataAnaconda3libsite-packagespycudacompiler.py", line 137, in compile_plain
    stderr=stderr.decode("utf-8", "replace"))

CompileError: nvcc compilation of C:UsersHENRYC~1AppDataLocalTemptmpy0kcq_5ikernel.cu failed

 

Комментарии:

1. Можете ли вы поделиться возникшей у вас ошибкой компиляции?

2. 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 .

Такого рода распределение памяти внутри ядра устройства имеет множество предостережений:

  • по умолчанию общее выделенное пространство (количество потоков, для которых в данный момент открыто выделение, умноженное на размер выделения), используемое вашим ядром, не может превышать 8 МБ. Это регулируется.
  • обычно у вас должна быть соответствующая delete[] операция C после завершения использования указателя (или free() , если вы использовали malloc() ) в вашем коде ядра (что также может помочь с пунктом выше)
  • среда выполнения устройства CUDA указывает здесь на ошибку выделения, возвращая нулевой указатель. При возникновении проблем рекомендуется проверять наличие NULL в коде ядра, прежде чем использовать указатель.
  • сам этап выделения устройства может заметно повлиять на производительность ядра (продолжительность выполнения). Если ваше ядро выполняет много работы / много других вещей, это может быть вообще не заметно. Для ядер, выполняющих мало работы, это может быть очень заметно. После завершения выделения использование выделенного указателя не должно иметь каких-либо существенных отличий в производительности от использования определения массива, где размер известен как константа времени компиляции.