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) でいっぱいの配列を返すことを期待しています。ただし、出力は次のようになります。

[(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

hereのアドバイスに従って、すべてのコードをfloat4代わりに使用するように変更しfloat3、すべての問題がなくなりました。

確かに、これは非常にイライラしますが、3*sizeof() にアラインされた型の使用はお勧めしません。GPU はそれをうまく処理できないからです。ホスト側でこれらの型のサイズを尋ねると、sizeof(cl_float3) = sizeof(cl_float4) となります。そのため、ホスト側でさえ適切に使用していない場合、デバイスが適切に使用していても、非常に面倒になります。GPU は、4 バイトまたは 16 バイトのいずれかにアラインされた型に対して高度に最適化されています。ベクトルに必要な変数が 3 つだけの場合でも、float4 を使用して最後の要素を無視します。メモリを無駄にしたくない場合は、3 つの独立した float 配列を使用します。
于 2013-01-28T21:28:34.497 に答える