1

pyOpenCL を使用して複雑な計算を行っています。CPU では問題なく動作しますが、NVIDIA GeForce 9400M (256 MB) で実行しようとするとエラーが発生します。Mac OS X Lion (10.7.5) で作業しています

奇妙なことに、このエラーは常に表示されるとは限りません。私の計算でより大きな数を使用した場合(結果としてより大きな反復が発生した場合)に発生するようですが、GPUで実行した場合にのみ発生します。

書き込むべきではないメモリの場所に書き込んでいるわけではありません。コードを単一の作業項目として実行することで、同時修正で起こりうる問題を排除しました。


OpenCL コードを可能な限り単純化し、残ったものから、非常に奇妙な動作をする非常に単純なコードを作成しましたpyopencl.LogicErrorresultこれは、配列に対していくつかの割り当てが行われる 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_buf0OpenCL で計算を実行して、大きな反復で値を設定します。その後、デバイスのメモリからこの値を収集しようとしましたが、ここで問題が発生しました。

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 に切り替えた今、エラーが一貫して発生しないことに不満を感じており、原因がわかりません。

4

2 に答える 2

1

私のアドバイスは、カーネル内でこのような長いループを避けることです。Work Item は 10 億回以上の反復を行っていますが、それは見込みのないことです。おそらく、実行に時間がかかりすぎるため、ドライバーがカーネルを強制終了します。エラーが発生しない最大量まで反復回数を減らし、実行時間を調べます。数秒かかる場合は、多すぎます。

あなたが言ったように、反復回数を減らすと問題が解決し、それが私の意見では証拠です。割り当て操作の数を減らすと、通常は IO 操作が最も遅いため、カーネルの実行も高速になります。

明らかな理由により、CPU はそのような問題に直面しません。

于 2014-07-29T14:25:21.847 に答える
0

このタイムアウトの問題は、Windows と Linux では修正できますが、Mac では修正できないようです。


ウィンドウズ

同様の質問 (Windows での症状の説明) に対するこの回答は、何が起こっているのか、それを修正する方法の両方を示しています。

これは、Windows の既知の「機能」です (Linux については不明)。ビデオ ドライバーが応答しなくなった場合、OS はそれをリセットします。ただし、OpenCL (および CUDA) はドライバーによって実装されるため、時間がかかりすぎるカーネルはフリーズしたドライバーのように見えます。これを追跡するウォッチドッグタイマーがあります(5秒だと思います)。

オプションは次のとおりです。

  1. カーネルに時間がかかりすぎないようにする必要があります (最善)。
  2. ウォッチドッグ タイマーをオフにすることができます: GPU のタイムアウト検出と回復
  3. ディスプレイに接続されていない GPU でカーネルを実行できます。

1で行くことをお勧めします。

この回答では、Windows 7 で (2) を実際に実行する方法について説明しています。ただし、これらのレジストリ キーの MSDN ページには、ターゲット テストまたはデバッグ以外のアプリケーションで操作してはならないことが記載されています。したがって、これは最良の選択肢ではないかもしれませんが、選択肢の 1 つです。


Linux

(Cudaリリースノートより、OpenCLにも適用可能)

ディスプレイが接続されていない GPU は、5 秒のランタイム制限の対象ではありません。このため、X ディスプレイに接続されていない GPU で CUDA を実行することをお勧めします。

CUDA を使用するために X が実行されている必要はありませんが、NVIDIA カーネル モジュールを適切にロードするために、X は起動後に少なくとも 1 回は初期化されている必要があります。X がシャットダウンした後も NVIDIA カーネル モジュールがロードされたままになるため、CUDA は引き続き機能します。


マック

Apple は明らかにこのウォッチドッグをいじることを許可していないため、唯一のオプションは 2 番目の GPU を使用することです (画面が接続されていない)。

于 2014-08-04T10:12:11.237 に答える