PyCUDA 未对齐地址清理失败

PyCUDA misaligned address cleanup failure

我是 CUDA 编程的新手,正在从 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 "/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 GPU 的集群上执行此操作。由于我没有 root 访问权限,我不得不在本地安装 Python3 并将 numpy、pyCUDA 等添加到本地安装。 Ubuntu 12.04.1 LTS 上的集群 运行s。我正在使用 Python 3.6.0 与 PyCUDA 2016.1.2 和 CUDA 6.0

这里的问题是你对什么是“二维数组”的理解不正确。默认情况下,Numpy 数组(以及 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)

您应该会发现现在可以正常工作了。