PyOpenCL 还原算法错误
PyOpenCL reduction algorithm error
最近我一直在尝试使用 PyOpenCl 学习 gpu 编程,但是尽管我尽了最大的努力,我仍然无法将下面代码中显示的缩减算法得到 运行。相反,代码 returns
RuntimeError: clEnqueueReadBuffer failed: OUT_OF_RESOURCES
我对这个错误的理解是它表明内存分配不足或内核中的索引越界。对于小的全局大小(即小 (N,A,t)
),代码将 运行 成功,所以我怀疑是前者。但是,我为 (1,1,t)
的工作组大小分配了 np.dtype(np.float32).itemsize*t
字节到本地内存,我认为这应该足够了。有谁知道为什么我会收到此错误?如果有帮助,我会 运行 在 NVIDIA GeForce GTX 960 上安装内核。
import numpy as np
import pyopencl as cl
np.random.seed(5)
N=2500*56
A=6
t=64
plat = cl.get_platforms()
devices = plat[0].get_devices()
ctx = cl.Context([devices[0]])
queue = cl.CommandQueue(ctx)
actions=np.random.randint(0,2,(N,A,t)).flatten(order='F')
tau=np.arange(1,np.add(t,1))
d=np.random.rand(N).astype(np.float32)
baseAct=np.empty((N,A)).astype(np.float32).flatten(order='F')
mf = cl.mem_flags
actions_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR,
hostbuf=actions)
tau_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=tau)
d_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=d)
loc_buf = cl.LocalMemory(np.dtype(np.float32).itemsize*t)
baseAct_buf = cl.Buffer(ctx, mf.WRITE_ONLY, baseAct.nbytes)
prg = cl.Program(ctx, """
__kernel void calc_baseAct(__global const int *actions,
__global const int *tau,
__global const float *d,
__local float *loc,
__global float *baseAct,
int N,
int A,
int t)
{
int xg = get_global_id(0);
int yg = get_global_id(1);
int zg = get_global_id(2);
int xl = get_local_id(0);
int yl = get_local_id(1);
int zl = get_local_id(2);
int xw = get_group_id(0);
int yw = get_group_id(1);
int zw = get_group_id(2);
loc[xl+N*yl+N*A*zl] = actions[xg+N*yg+N*A*zg]*pow(tau[zg],-d[xg]);
barrier(CLK_LOCAL_MEM_FENCE);
for(uint s = t/2; s > 0; s >>= 1) {
if(zl < s) {
loc[xl+N*yl+N*A*zl] += loc[xl+N*yl+N*A*(zl+s)];
}
barrier(CLK_LOCAL_MEM_FENCE);
}
if(zl == 0) baseAct[xw+N*yw+N*A*zw] = loc[xl+N*yl+N*A*zl];
}
""").build()
prg.calc_baseAct(queue, (N,A,t), (1,1,t), actions_buf, tau_buf, d_buf,
loc_buf, baseAct_buf, np.int32(N), np.int32(A), np.int32(t))
cl.enqueue_copy(queue, baseAct, baseAct_buf)
baseAct=baseAct.reshape((N,A), order='F')
显然越界访问 loc
,分配给每个工作组 64 个元素,并使用 xl+N*yl+N*A*zl
的索引进行访问,其中 zl
在 [0,63]
范围内乘以 N=2500*56
和 A=6
。
最近我一直在尝试使用 PyOpenCl 学习 gpu 编程,但是尽管我尽了最大的努力,我仍然无法将下面代码中显示的缩减算法得到 运行。相反,代码 returns
RuntimeError: clEnqueueReadBuffer failed: OUT_OF_RESOURCES
我对这个错误的理解是它表明内存分配不足或内核中的索引越界。对于小的全局大小(即小 (N,A,t)
),代码将 运行 成功,所以我怀疑是前者。但是,我为 (1,1,t)
的工作组大小分配了 np.dtype(np.float32).itemsize*t
字节到本地内存,我认为这应该足够了。有谁知道为什么我会收到此错误?如果有帮助,我会 运行 在 NVIDIA GeForce GTX 960 上安装内核。
import numpy as np
import pyopencl as cl
np.random.seed(5)
N=2500*56
A=6
t=64
plat = cl.get_platforms()
devices = plat[0].get_devices()
ctx = cl.Context([devices[0]])
queue = cl.CommandQueue(ctx)
actions=np.random.randint(0,2,(N,A,t)).flatten(order='F')
tau=np.arange(1,np.add(t,1))
d=np.random.rand(N).astype(np.float32)
baseAct=np.empty((N,A)).astype(np.float32).flatten(order='F')
mf = cl.mem_flags
actions_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR,
hostbuf=actions)
tau_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=tau)
d_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=d)
loc_buf = cl.LocalMemory(np.dtype(np.float32).itemsize*t)
baseAct_buf = cl.Buffer(ctx, mf.WRITE_ONLY, baseAct.nbytes)
prg = cl.Program(ctx, """
__kernel void calc_baseAct(__global const int *actions,
__global const int *tau,
__global const float *d,
__local float *loc,
__global float *baseAct,
int N,
int A,
int t)
{
int xg = get_global_id(0);
int yg = get_global_id(1);
int zg = get_global_id(2);
int xl = get_local_id(0);
int yl = get_local_id(1);
int zl = get_local_id(2);
int xw = get_group_id(0);
int yw = get_group_id(1);
int zw = get_group_id(2);
loc[xl+N*yl+N*A*zl] = actions[xg+N*yg+N*A*zg]*pow(tau[zg],-d[xg]);
barrier(CLK_LOCAL_MEM_FENCE);
for(uint s = t/2; s > 0; s >>= 1) {
if(zl < s) {
loc[xl+N*yl+N*A*zl] += loc[xl+N*yl+N*A*(zl+s)];
}
barrier(CLK_LOCAL_MEM_FENCE);
}
if(zl == 0) baseAct[xw+N*yw+N*A*zw] = loc[xl+N*yl+N*A*zl];
}
""").build()
prg.calc_baseAct(queue, (N,A,t), (1,1,t), actions_buf, tau_buf, d_buf,
loc_buf, baseAct_buf, np.int32(N), np.int32(A), np.int32(t))
cl.enqueue_copy(queue, baseAct, baseAct_buf)
baseAct=baseAct.reshape((N,A), order='F')
显然越界访问 loc
,分配给每个工作组 64 个元素,并使用 xl+N*yl+N*A*zl
的索引进行访问,其中 zl
在 [0,63]
范围内乘以 N=2500*56
和 A=6
。