我试图用pyopencl实现元素乘法,但是当我从pyopencl读取结果缓冲区时,只有8行中的前3行是正确的。我不确定OpenCL或pyopencl是否存在问题。这是我输出的最小例子。我很满意每一个建议。
由于
import pyopencl as cl
import numpy
# OpenCL Kernel code -----------------------------------------------------
KERNEL_CODE = """
__kernel void eMul(
__global float* C,
__global float* A,
__global float* B,
int width, int height)
{
// ID
int x = get_global_id(0);
int y = get_global_id(1);
// Multiplying
C[y * width + x ] = A[y * width + x] * B[y * width + x];
}
"""
# init OpenCL -----------------------------------------------------
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
prg = cl.Program(ctx, KERNEL_CODE).build()
kernel = prg.eMul
# init host memory -----------------------------------------------------
numpy.random.seed(42)
width = 4
height = 8
cl_left= numpy.random.rand(height, width).astype(numpy.float32) * 10
cl_left = cl_left.round()
cl_right= numpy.random.rand(height, width).astype(numpy.float32) * 10
cl_right = cl_right.round()
print "\nleft\n",cl_left,"\n\nright\n",cl_right
# transfer host -> device -----------------------------------------------------
mf = cl.mem_flags
cl_result = numpy.zeros(cl_left.shape).astype(numpy.float32)
d_a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=cl_left)
d_b_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=cl_right)
d_c_buf = cl.Buffer(ctx, mf.WRITE_ONLY, cl_result.nbytes)
kernel.set_arg(0,d_c_buf)
kernel.set_arg(1,d_a_buf)
kernel.set_arg(2,d_b_buf)
kernel.set_arg(3,numpy.uint32(width))
kernel.set_arg(4,numpy.uint32(height))
event = cl.enqueue_nd_range_kernel(queue,kernel,cl_result.shape,cl_result.shape)
event.wait()
# transfer device -> host -----------------------------------------------------
cl.enqueue_read_buffer(queue, d_c_buf, cl_result).wait()
print "\nresult\n", cl_result
输出:
left
[[ 4. 10. 7. 6.]
[ 2. 2. 1. 9.]
[ 6. 7. 0. 10.]
[ 8. 2. 2. 2.]
[ 3. 5. 4. 3.]
[ 6. 1. 3. 4.]
[ 5. 8. 2. 5.]
[ 6. 0. 6. 2.]]
right
[[ 1. 9. 10. 8.]
[ 3. 1. 7. 4.]
[ 1. 5. 0. 9.]
[ 3. 7. 3. 5.]
[ 5. 2. 10. 8.]
[ 9. 9. 6. 9.]
[ 1. 2. 0. 3.]
[ 4. 3. 8. 4.]]
result
[[ 4. 90. 70. 48.]
[ 6. 2. 7. 36.]
[ 6. 35. 0. 90.]
[ 24. 14. 6. 10.]
[ 15. 10. 40. 24.] <== till here correct
[ 138. 69. 87. 35.] <== from here incorrect
[ 130. 47. 109. 49.]
[ 95. 45. 25. 49.]]
答案 0 :(得分:2)
对于如何为内核指定数组的形状,看起来有些混乱 - 基本上,与源numpy数组的大小相比,宽度和高度相反。因此,您尝试使用4个字的间距写入列主要顺序,而不是8。
如果用这个替换内核:
__kernel void eMul(
__global float* C,
__global float* A,
__global float* B,
int width, int height)
{
// ID
int x = get_global_id(0);
int y = get_global_id(1);
// Multiplying
C[y * height + x ] = A[y * height + x] * B[y * height + x];
}
我认为你会发现结果更符合你的期望。