我正在将模拟移至 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);
}
}
}"""
Run Code Online (Sandbox Code Playgroud)
代码本身(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()
Run Code Online (Sandbox Code Playgroud)
您将数据复制到设备的代码就很好。但是,您的内核至少有两个问题:
float3根据 OpenCL 1.2 规范 6.1.5,值预计为 16 字节对齐:
对于 3 分量向量数据类型,数据类型的大小为 4 *
sizeof(分量)。这意味着 3 分量向量数据类型将与 4 *sizeof(分量)边界对齐。vload3和vstore3内置函数可分别用于从压缩标量数据类型数组中读取和写入 3 分量向量数据类型。
您上传到设备的值未正确对齐,内核无法float3直接读取值。
您的极限计算int lim = X*Y*3;略有偏差。您已经在尝试从 的数组中读取float3,因此这*3是多余的。
这两个问题的解决方案很简单:如规范中所述,您应该使用vload3float从s数组加载:
#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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1814 次 |
| 最近记录: |