我正在将模拟移动到pyOpenCL中,无法使我的数据访问工作。我正在尝试提供一维矢量数组(好吧,实际上有几个,但我刚刚使用过的一个例子)。
目前,几个向量被复制得很好,但数据根本就不是我提供的。
我认为我之前没有在这里发布,所以如果任何格式/演示文稿错误,请道歉。另外,我刚刚删除了所有的模拟代码,所以我意识到这个代码目前实际上并没有做任何事情,我只想让缓冲区传递正确。
提前致谢。
内核(kertest.py):
step1 = """
#pragma OPENCL EXTENSION cl_amd_printf: enable
#define X xdim
#define Y ydim
__kernel void k1(__global float3 *spins,
__local float3 *tile)
{
ushort lid = 2 * get_local_id(0);
ushort group = 2 * get_group_id(0);
ushort num = get_num_groups(0);
int lim = X*Y*3;
for (ushort i = 0; i < lim; i++)
{
if (lid == 0 && group == 0)
{
printf("%f :: %d\\n", spins[i].x, i);
}
}
}"""
代码本身(gputest.py):
import kertest as k2D
import numpy as np
import pyopencl as cl
class GPU_MC2DSim():
def __init__(self, x, y):
self.x = x
self.y = y
if x >= y:
self.xdim = int(self.x)
self.ydim = int(self.y)
else:
self.xdim = int(self.y)
self.ydim = int(self.x)
if self.xdim % 2 != 0: self.xdim += 1
if self.ydim % 2 != 0: self.ydim += 1
self.M = np.ones((self.xdim*self.ydim, 3)).astype(np.float32)
self.M[:, 1] += 1.0
self.M[:, 2] += 2.0
print self.M
def simulate(self):
ctx = cl.create_some_context()
q = cl.CommandQueue(ctx)
mf = cl.mem_flags
#Pass buffer:
M_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf = self.M)
#Insert kernel parameters:
params = {"xdim" : "%d" % (self.xdim),
"ydim" : "%d" % (self.ydim),
}
for name in params:
k2D.step1 = k2D.step1.replace(name, params[name])
#Compile kernel:
step1 = cl.Program(ctx, k2D.step1).build()
locmem = cl.LocalMemory(self.xdim*4*4)
step1.k1(q, ((self.xdim*self.ydim)/4,), (self.xdim/2,), M_buf, locmem).wait()
return None
xdim = 4
ydim = 4
sim = GPU_MC2DSim(xdim, ydim)
sim.simulate()
答案 0 :(得分:3)
您将数据复制到设备的代码很好。但是,你的内核至少有两个问题:
float3
值预计为16字节对齐:
对于3分量矢量数据类型,数据类型的大小为4 *
sizeof
(分量)。这意味着3分量矢量数据类型将与4 *sizeof
(分量)边界对齐。 vload3 和 vstore3 内置函数可用于分别从打包标量数据类型数组中读取和写入3分量矢量数据类型。
您上传到设备的值未正确对齐,内核无法直接读取float3
值。
您的限额计算int lim = X*Y*3;
略有偏差。您已尝试从float3
数组中读取,因此*3
是多余的。
这两个问题的解决方案很简单:如规范中所述,您应该使用 vload3 从float
的数组中加载:
#pragma OPENCL EXTENSION cl_amd_printf: enable
#define X xdim
#define Y ydim
__kernel void k1(__global float *spins,
__local float3 *tile)
{
ushort lid = 2 * get_local_id(0);
ushort group = 2 * get_group_id(0);
ushort num = get_num_groups(0);
int lim = X*Y;
for (ushort i = 0; i < lim; i++)
{
if (lid == 0 && group == 0)
{
float3 vec = vload3(i, spins);
printf("(%f, %f, %f) :: %d\\n", vec.x, vec.y, vec.z, i);
}
}
}