1

我的 pyopencl 程序的行为很奇怪,我认为我从 opencl 内核收到了不准确的值。

给定以下示例:

import pyopencl as cl
import pyopencl.array as cl_array
import numpy
from pyopencl.elementwise import ElementwiseKernel

ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)

n = 20

kernel = ElementwiseKernel(ctx,
    "float3 *x",
    "x[i] = (float3)(1,1,1)",
    "assign")

x = numpy.empty(n, dtype=cl_array.vec.float3)
x_gpu = cl_array.to_device(queue, x)

kernel(x_gpu)

print x_gpu.get()

我希望它返回一个充满 (1, 1, 1)s 的数组。但是,输出如下所示:

[(1.0, 1.0, 1.0) (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 0.0)
 (1.0, 1.0, 1.0) (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 0.0)
 (1.0, 1.0, 1.0) (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 0.0)
 (1.0, 1.0, 1.0) (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 0.0)
 (1.0, 1.0, 1.0) (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 0.0)]

或者像这样

[(1.0, 1.0, 1.0) (4.588972210970911e-41, 1.0, 1.0)
 (1.0, 4.203895392974451e-45, 1.0) (1.0, 1.0, 1.3592595103950726e-43)
 (1.0, 1.0, 1.0) (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 0.0)
 (1.0, 1.0, 1.0) (1.401298464324817e-45, 1.0, 1.0)
 (1.0, 2.0795269210580285e-42, 1.0) (1.0, 1.0, 0.0) (1.0, 1.0, 1.0)
 (0.0, 1.0, 1.0) (1.0, 0.0, 1.0) (1.0, 1.0, 1.401298464324817e-45)
 (1.0, 1.0, 1.0) (4.792440747990874e-43, 1.0, 1.0) (1.0, 0.0, 1.0)
 (1.0, 1.0, 0.0)]

我不确定这是否是 OpenCL、PyOpenCL 的问题,或者我做错了什么。

任何帮助表示赞赏。谢谢你。

4

2 回答 2

1

按照此处给出的建议,我已将所有代码更改为使用float4而不是float3所有问题都消失了。

确实,这非常令人沮丧,但是我不鼓励使用任何与 3*sizeof() 对齐的类型,因为 GPU 不能很好地处理它。如果在主机端询问这些类型的大小,您将得到 sizeof(cl_float3) = sizeof(cl_float4)。因此,即使主机端没有正确使用它,它也会变得非常混乱,即使设备可以正确使用它。GPU 针对对齐到 4 字节或 16 字节的类型进行了高度优化。即使您只需要一个向量中的 3 个变量,也可以使用 float4 并忽略最后一个元素。如果您不想浪费内存,请使用三个独立的浮点数组。
于 2013-01-28T21:28:34.497 回答
0

根据官方 OpenCL 规范,任何 3 分量元素的向量都将对齐,就好像每个元素都有 4 个分量一样。

6.1.5 类型对齐

在内存中声明为数据类型的数据项始终与数据类型的大小(以字节为单位)对齐。例如,float4 变量将与 16 字节边界对齐,char2 变量将与 2 字节边界对齐。对于 3 分量向量数据类型,数据类型的大小为 4 * sizeof(component)。这意味着 3 分量矢量数据类型将与 4 * sizeof(component) 边界对齐。

于 2018-10-24T15:01:59.330 回答