我对cuda和pycuda很新。
我需要一个内核,通过简单的"重复"来创建一个矩阵(维数为n x d)的数组(1 x d)。相同的数组n次:
例如,假设我们有n = 4和d = 3,那么如果数组是[1 2 3]
我的内核的结果应该是:
[1 2 3
1 2 3
1 2 3
1 2 3]
(矩阵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)我得到输出矩阵的每个元素都有 正确的值,除了第一列:一些条目是正确的,但其他条目有另一个值,显然是随机的,对于每个错误的元素都是相同的,但每次运行都不同, 并且每次运行时,具有错误值的第一列的条目也不同。 例如:
[0 1 2
0 1 2
6 1 2
0 1 2
6 1 2
...]
我真的无法弄清楚是什么导致了这个问题,但也许它只是一些我想念的简单......
任何帮助将不胜感激,提前谢谢!
答案 0 :(得分:0)
内核代码中的边界检查不正确。此
if (y > n || x > d) return;
out[y * d + x] = in[x];
应该是:
if (y >= n || x >= d) return;
out[y * d + x] = in[x];
或更好:
if ((y < n) && (x < d))
out[y * d + x] = in[x];
数组中的所有数组有效索引都位于0 < x < d
和0 < y < n
。通过允许x=d
您具有未定义的行为,允许输出数组的下一行中的第一个条目被未知值覆盖。这解释了为什么有时结果是正确的,有时则不是。