2017-01-03 11 views
0

Я очень новичок в программировании CUDA и начинаю с PyCUDA, чтобы получить основы. Я изучил учебники и проверил несколько простых тестовых кодов. В тестах использовались только 1D массивы. Когда я попытался запустить следующий код с 2D-массивами, я постоянно получаю предупреждение PyCUDA о том, что операция очистки завершилась неудачно из-за неправильного адреса.Неисправность очистки неправильного адреса PyCUDA

import pycuda.autoinit 
import pycuda.driver as drv 
import numpy as np 
from pycuda.compiler import SourceModule 

mod = SourceModule(""" 
    __global__ void multiply(float **dest) { 
     const int i = threadIdx.x; 
     const int j = threadIdx.y; 
     dest[i][j] = 2.0*dest[i][j]; 
    } 
""") 

a = np.random.randn(32, 32).astype(np.float32) 
multiply = mod.get_function("multiply") 
multiply(drv.InOut(a), block=(32,32,1), grid=(1,1)) 

print(a) 

ошибка, что я получаю, когда я бегу выше сценарий:

Traceback (most recent call last): 
    File "cudaTest.py", line 16, in <module> 
    multiply(drv.InOut(a), block=(32,32,1), grid=(1,1)) 
    File "https://stackoverflow.com/users/gpu/local/python3.3/lib/python3.6/site-packages/pycuda-2016.1.2-py3.6-linux-x86_64.egg/pycuda/driver.py", line 405, in function_call 
    Context.synchronize() 
pycuda._driver.LogicError: cuCtxSynchronize failed: misaligned address 
PyCUDA WARNING: a clean-up operation failed (dead context maybe?) 
cuMemFree failed: misaligned address 
PyCUDA WARNING: a clean-up operation failed (dead context maybe?) 
cuModuleUnload failed: misaligned address 

Я проверил другие вопросы на SO и нашли similar one. Следуя приведенному там ответу, я попытался указать размер массива a, но безрезультатно.

Я запускаю это на кластере с двумя графическими процессорами nVidia Tesla K10. Поскольку у меня нет доступа root, мне пришлось установить Python3 локально и добавить numpy, pyCUDA и т. Д. В локальную установку. Кластер работает на Ubuntu 12.04.1 LTS. Я использую Python 3.6.0 с PyCUDA 2016.1.2 и CUDA 6.0

ответ

3

Проблема в том, что ваше понимание того, что представляет собой «2D-массив», неверно. Массивные массивы (и по расширению PyCUDA gpuarrays) хранятся в линейной памяти в строчном порядке по умолчанию. Ваше ядро ​​было написано, чтобы ожидать массив указателей, как во входных данных, и пытается использовать данные с плавающей запятой в качестве адресов, что приводит к ошибке адресации времени выполнения, которую вы видите.

Чтобы исправить ядро ​​для работы с массивом, вы должны изменить его на что-то вроде:

mod = SourceModule(""" 
    __global__ void multiply(float *dest, int lda) { 
     const int i = threadIdx.x; 
     const int j = threadIdx.y; 
     float *p = &dest[i * lda + j]; // row major order 
     *p *= 2.0f; 
    } 
""") 

Обрати внимание, что массив передается как указатель на скатное линейное распределение, а не массив указатели строк. Из-за этого, вам нужно будет пройти шаг массива в элементах к ядру, а также, так что вызывающий код PyCuda хост выглядит следующим образом:

N = 8 
a = np.random.randn(N, N).astype(np.float32) 
print(a) 
multiply = mod.get_function("multiply") 
lda = np.int32(N) 
multiply(drv.InOut(a), lda, block=(N,N,1), grid=(1,1)) 
print(a) 

Вы должны найти это теперь будет работать правильно.