opencl 在结构操作期间跳过数据
opencl skipping data during operation on struct
我有一个自定义 struct
,我想对其执行操作以减少我所有结构上的字段 scalar1
。这是一个非常简单的操作。减法似乎正在发生,但 OpenCL 对错误的数据进行了操作。这是一个可能可以在您的计算机上执行的 MWE。
import pyopencl as cl
import pyopencl.tools
import numpy as np
kernelSource = """
__kernel void decreaseScalarFieldBy(__global myStruct *a, float delta)
{
int gid = get_global_id(0);
a[gid].scalar1 -= delta;
}
"""
context = cl.create_some_context()
queue = cl.CommandQueue(context)
device = context.devices[0]
myStruct = np.dtype(
[("vector1", cl.cltypes.float4),
("scalar1", cl.cltypes.float)])
name = "myStruct"
_, c_decl = cl.tools.match_dtype_to_c_struct(device, name, myStruct)
myStruct_dtype = cl.tools.get_or_register_dtype(name, myStruct)
program = cl.Program(context, c_decl + kernelSource).build()
N = 10
HOST_struct = np.empty(N, dtype=myStruct_dtype)
HOST_struct["vector1"] = np.array([cl.cltypes.make_float4(1, 0, 0, 0)]*N, dtype=cl.cltypes.float4)
HOST_struct["scalar1"] = np.ones(N, dtype=cl.cltypes.float)
TARGET_struct = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_struct)
cl.enqueue_copy(queue, dest=TARGET_struct, src=HOST_struct)
program.decreaseScalarFieldBy(queue, (N,), None, TARGET_struct, np.float32(0.5))
cl.enqueue_copy(queue, dest=HOST_struct, src=TARGET_struct)
queue.finish()
print(HOST_struct)
这是输出,减法全部移位,最终在 vector1
字段内减去?
[((1. , 0. , 0. , 0. ), 0.5) ((1. , 0. , 0. , 0. ), 1. )
((1. , 0. , -0.5, 0. ), 1. ) ((1. , 0. , 0. , 0. ), 1. )
((0.5, 0. , 0. , 0. ), 1. ) ((1. , 0. , 0. , -0.5), 1. )
((1. , 0. , 0. , 0. ), 1. ) ((1. , -0.5, 0. , 0. ), 1. )
((1. , 0. , 0. , 0. ), 0.5) ((1. , 0. , 0. , 0. ), 1. )]
有人可以向我解释这段代码有什么问题吗?
我已经分别尝试使用 float
和 float4
并且它们在结构外部时都可以完美地工作。
我不知道内存对齐的概念。
从 OpenCL 1.2 specification 第 6.1 章,我们了解到类型必须在 2^X 上对齐。因此,我的结构未对齐,因为它的大小为 36 字节。 sizeOf(float4) = 16 Bytes
, sizeOf(float) = 4 Bytes
.
但是,numpy
默认对齐数组,但 NOT 与 OpenCL 的对齐方式相同。因此,struct
必须与 OpenCL 对齐匹配。这是
的工作
_, c_decl = cl.tools.match_dtype_to_c_struct(device, name, myStruct)
问题是在我的代码中,_
省略了新的重新声明的结构。需要做的是采用新的重新声明的 struct
并覆盖我们旧的 numpy
声明。
myStruct = np.dtype(
[("position", cl.cltypes.float4),
("direction", cl.cltypes.float4),
("weight", cl.cltypes.float)])
name = "photonStruct"
myStruct, c_decl = cl.tools.match_dtype_to_c_struct(device, name, myStruct)
myStruct_dtype = cl.tools.get_or_register_dtype(name, myStruct)
现在一切正常。
我有一个自定义 struct
,我想对其执行操作以减少我所有结构上的字段 scalar1
。这是一个非常简单的操作。减法似乎正在发生,但 OpenCL 对错误的数据进行了操作。这是一个可能可以在您的计算机上执行的 MWE。
import pyopencl as cl
import pyopencl.tools
import numpy as np
kernelSource = """
__kernel void decreaseScalarFieldBy(__global myStruct *a, float delta)
{
int gid = get_global_id(0);
a[gid].scalar1 -= delta;
}
"""
context = cl.create_some_context()
queue = cl.CommandQueue(context)
device = context.devices[0]
myStruct = np.dtype(
[("vector1", cl.cltypes.float4),
("scalar1", cl.cltypes.float)])
name = "myStruct"
_, c_decl = cl.tools.match_dtype_to_c_struct(device, name, myStruct)
myStruct_dtype = cl.tools.get_or_register_dtype(name, myStruct)
program = cl.Program(context, c_decl + kernelSource).build()
N = 10
HOST_struct = np.empty(N, dtype=myStruct_dtype)
HOST_struct["vector1"] = np.array([cl.cltypes.make_float4(1, 0, 0, 0)]*N, dtype=cl.cltypes.float4)
HOST_struct["scalar1"] = np.ones(N, dtype=cl.cltypes.float)
TARGET_struct = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_struct)
cl.enqueue_copy(queue, dest=TARGET_struct, src=HOST_struct)
program.decreaseScalarFieldBy(queue, (N,), None, TARGET_struct, np.float32(0.5))
cl.enqueue_copy(queue, dest=HOST_struct, src=TARGET_struct)
queue.finish()
print(HOST_struct)
这是输出,减法全部移位,最终在 vector1
字段内减去?
[((1. , 0. , 0. , 0. ), 0.5) ((1. , 0. , 0. , 0. ), 1. )
((1. , 0. , -0.5, 0. ), 1. ) ((1. , 0. , 0. , 0. ), 1. )
((0.5, 0. , 0. , 0. ), 1. ) ((1. , 0. , 0. , -0.5), 1. )
((1. , 0. , 0. , 0. ), 1. ) ((1. , -0.5, 0. , 0. ), 1. )
((1. , 0. , 0. , 0. ), 0.5) ((1. , 0. , 0. , 0. ), 1. )]
有人可以向我解释这段代码有什么问题吗?
我已经分别尝试使用 float
和 float4
并且它们在结构外部时都可以完美地工作。
我不知道内存对齐的概念。
从 OpenCL 1.2 specification 第 6.1 章,我们了解到类型必须在 2^X 上对齐。因此,我的结构未对齐,因为它的大小为 36 字节。 sizeOf(float4) = 16 Bytes
, sizeOf(float) = 4 Bytes
.
但是,numpy
默认对齐数组,但 NOT 与 OpenCL 的对齐方式相同。因此,struct
必须与 OpenCL 对齐匹配。这是
_, c_decl = cl.tools.match_dtype_to_c_struct(device, name, myStruct)
问题是在我的代码中,_
省略了新的重新声明的结构。需要做的是采用新的重新声明的 struct
并覆盖我们旧的 numpy
声明。
myStruct = np.dtype(
[("position", cl.cltypes.float4),
("direction", cl.cltypes.float4),
("weight", cl.cltypes.float)])
name = "photonStruct"
myStruct, c_decl = cl.tools.match_dtype_to_c_struct(device, name, myStruct)
myStruct_dtype = cl.tools.get_or_register_dtype(name, myStruct)
现在一切正常。