Python 简单pycuda内核的奇怪行为

Python 简单pycuda内核的奇怪行为,python,numpy,cuda,pycuda,Python,Numpy,Cuda,Pycuda,我对cuda和pycuda很陌生。 我需要一个内核,通过简单地“重复”相同的数组n次,从数组(1 x d)中创建一个矩阵(维数为nx d): 例如,假设n=4,d=3,那么如果数组是[1 2 3] 我的内核的结果应该是: [1 2 3 1 2 3 1 2 3 1 2 3] if (y >= n || x >= d) return; out[y * d + x] = in[x]; (矩阵4x3) 基本上,这与执行numpy.tile(数组,(n,1))是一样的 我已经编写了

我对cuda和pycuda很陌生。 我需要一个内核,通过简单地“重复”相同的数组n次,从数组(1 x d)中创建一个矩阵(维数为nx d): 例如,假设n=4,d=3,那么如果数组是
[1 2 3]
我的内核的结果应该是:

[1 2 3
 1 2 3
 1 2 3
 1 2 3]
if (y >= n ||  x >= d) return;
out[y * d + x] = in[x];
(矩阵4x3)

基本上,这与执行numpy.tile(数组,(n,1))是一样的

我已经编写了以下代码:

kernel_code_template = """
__global__ void TileKernel(float *in, float *out)
{
    // Each thread computes one element of out
    int y = blockIdx.y * blockDim.y + threadIdx.y;
    int x = blockIdx.x * blockDim.x + threadIdx.x;

    if (y > %(n)s || x > %(d)s) return;

    out[y * %(d)s + x] = in[x];
}
"""

d = 64
n = 512

blockSizex = 16
blockSizey = 16
gridSizex = (d + blockSizex - 1) / blockSizex 
gridSizey = (n + blockSizey - 1) / blockSizey 

# get the kernel code from the template 
kernel_code = kernel_code_template % {
    'd': d,
    'n': n
    }
mod = SourceModule(kernel_code)
TileKernel = mod.get_function("TileKernel")

vec_cpu = np.arange(d).astype(np.float32) # just as an example
vec_gpu = gpuarray.to_gpu(vec_cpu)
out_gpu = gpuarray.empty((n, d), np.float32)

TileKernel.prepare("PP")
TileKernel.prepared_call((gridSizex, gridSizey), (blockSizex, blockSizey, 1), vec_gpu.gpudata,  out_gpu.gpudata)

out_cpu = out_gpu.get()
现在,如果我用d等于2>=16的幂来运行这段代码,我会得到正确的结果(就像numpy.tile(vec_cpu,(n,1)); 但是如果我把d设为其他值(比如88),我得到输出矩阵的每个元素都有 正确的值,除了第一列:有些条目是正确的,但其他条目有另一个值,显然是随机的,对于每个错误的元素相同,但每次运行都不同, 而且,第一列中具有错误值的条目在每次运行时都是不同的。 例如:

我真的不知道是什么导致了这个问题,但也许这只是一些简单的东西,我错过了


任何帮助都将不胜感激,提前感谢

内核代码中的边界检查不正确。这个

if (y > n ||  x > d) return;
out[y * d + x] = in[x];
应该是:

[1 2 3
 1 2 3
 1 2 3
 1 2 3]
if (y >= n ||  x >= d) return;
out[y * d + x] = in[x];
或者更好:

if ((y < n) && (x < d))
    out[y * d + x] = in[x];
if((y

数组中的所有数组有效索引位于
0
0
。通过允许
x=d
您具有未定义的行为,允许用未知值覆盖输出数组下一行的第一个条目。这就解释了为什么有时候结果是正确的,而有时候则不正确

我用您的代码测试的每个示例似乎都正常工作(例如d=88,n=567)通过
np.allclose(np.tile(vec\u cpu,(n,1)),out\u cpu)
。你能编辑一个你已经确认不适用于你的问题的确切案例吗?我准确地发现了如何重现这个错误:首先我用d=88,n=32运行脚本,它工作正常;然后我把d改成128,同样的n,它仍然可以正常工作;然后我把d改回88,相同的n,我得到了第一列的错误!