pyOpenCL を使用して複雑な計算を行っています。CPU では問題なく動作しますが、NVIDIA GeForce 9400M (256 MB) で実行しようとするとエラーが発生します。Mac OS X Lion (10.7.5) で作業しています
奇妙なことに、このエラーは常に表示されるとは限りません。私の計算でより大きな数を使用した場合(結果としてより大きな反復が発生した場合)に発生するようですが、GPUで実行した場合にのみ発生します。
書き込むべきではないメモリの場所に書き込んでいるわけではありません。コードを単一の作業項目として実行することで、同時修正で起こりうる問題を排除しました。
OpenCL コードを可能な限り単純化し、残ったものから、非常に奇妙な動作をする非常に単純なコードを作成しましたpyopencl.LogicError
。result
これは、配列に対していくつかの割り当てが行われる 2 つのネストされたループで構成されます。この割り当ては、ループの状態に依存する必要さえありません。shape = (1,)
これは、GPU上の単一のスレッド (または作業項目) で実行されます。
__kernel void weirdError(__global unsigned int* result){
unsigned int outer = (1<<30)-1;
for(int i=20; i--; ){
unsigned int inner = 0;
while(inner != outer){
result[0] = 1248;
result[1] = 1337;
inner++;
}
outer++;
}
}
奇妙な部分は、結果配列への割り当てのいずれかを削除するとエラーが削除されることです。また、outer の初期値を ((1<<20)-1
たとえば に) 減らすと、エラーも解消されます。これらの場合、コードは正常に戻り、対応するバッファーで正しい結果が使用可能になります。CPU では、エラーが発生することはありません。
OpenCL コードは、PyOpenCL を使用して Python から実行されます。
セットアップに特別なものはありません:
platform = cl.get_platforms()[0]
device = platform.get_devices(cl.device_type.GPU)[0]
context = cl.Context([device])
program = cl.Program(context, getProgramCode()).build()
queue = cl.CommandQueue(context)
この Python コードでは、 を に設定しresult_buf
、0
OpenCL で計算を実行して、大きな反復で値を設定します。その後、デバイスのメモリからこの値を収集しようとしましたが、ここで問題が発生しました。
result = numpy.zeros(2, numpy.uint32)
result_buf = cl.Buffer(context, mem_flags.READ_WRITE | mem_flags.COPY_HOST_PTR, hostbuf=result)
shape = (1,)
program.weirdError(queue, shape, None, result_buf)
cl.enqueue_copy(queue, result, result_buf)
最後の行は私に与えます:
pyopencl.LogicError: clEnqueueReadBuffer failed: invalid command queue
この繰り返しの代入がどのようにエラーを引き起こす可能性がありますか?
さらに重要なことは、どうすれば回避できるかということです。
この問題はおそらくプラットフォームに依存しているため、再現が難しいことを理解しています。しかし、これは私がアクセスできる唯一のマシンなので、コードはこのマシンで動作するはずです。
免責事項: OpenCL (または CUDA) を使用したことはありません。GPU が OpenCL をサポートしていないマシンでコードを書きました。私はいつもCPUでそれをテストしました。GPU に切り替えた今、エラーが一貫して発生しないことに不満を感じており、原因がわかりません。