pyopencl 在数组中返回错误的 float3 值

Posted

技术标签:

【中文标题】pyopencl 在数组中返回错误的 float3 值【英文标题】:pyopencl returns wrong float3 values in array 【发布时间】:2013-01-28 20:13:38 【问题描述】:

我的 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 的问题还是我做错了什么。

感谢任何帮助。谢谢。

【问题讨论】:

我对 PyOpenCL 一无所知,但在 C 语言中,float *x; x[0]=1.0; 正在为您尚未分配的内存分配值,基本上 x 没有任何意义。 @GradyPlayer float3 *x 是 OpenCL 中内核函数的函数头,x[i] = (float3)(1,1,1) 是函数体。 函数头?我知道 C 语言中的 OpenCL……不知道这意味着什么。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

根据official OpenCL specs,任何由 3 分量元素组成的向量都将被对齐,就好像每个元素都有 4 个分量一样。

6.1.5 类型对齐

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

【讨论】:

以上是关于pyopencl 在数组中返回错误的 float3 值的主要内容,如果未能解决你的问题,请参考以下文章

在 pyopencl 中添加复杂的 3D 数组

在 pyOpencl 中传递向量数组

解决 pyopencl 数组偏移限制

pyopencl array sum 添加一个数组

pyopencl中基本字符串复制程序中的Unicode解码错误

如何使用 PyOpenCL 将带有数组和变量的 C 结构传递给 OpenCL 内核