0

私の PC には、OpenCL をサポートしていない ATI 3200 GPU を搭載した AMD プロセッサが搭載されています。残りのコードはすべて「CPU自体にフォールバック」して実行されます。

コードの 1 つを CUDA から OpenCL に変換していますが、OpenCL に正確な変換コードがない特定の部分でスタックしています。私は OpenCL の経験が少ないため、これを理解することはできません。うまくいくと思われる解決策を提案してください。

CUDAコードは、

size_t pitch = 0;   
cudaError error = cudaMallocPitch((void**)&gpu_data, (size_t*)&pitch, 
                          instances->cols * sizeof(float), instances->rows);

for( int i = 0; i < instances->rows; i++ ){ 
    error = cudaMemcpy((void*)(gpu_data + (pitch/sizeof(float))*i), 
                       (void*)(instances->data + (instances->cols*i)), 
                       instances->cols * sizeof(float) ,cudaMemcpyHostToDevice);

上記からピッチ値を削除すると、デバイス メモリ "gpu_data" に書き込まれないという問題が発生します。

誰かこのコードを OpenCL に変換して返信してください。OpenCL に変換しましたが、動作せず、データが "gpu_data" に書き込まれません。私の変換されたOpenCLコードは

gpu_data = clCreateBuffer(context, CL_MEM_READ_WRITE, ((instances->cols)*(instances->rows))*sizeof(float), NULL, &ret);
for( int i = 0; i < instances->rows; i++ ){ 
    ret = clEnqueueWriteBuffer(command_queue, gpu_data, CL_TRUE, 0, ((instances->cols)*(instances->rows))*sizeof(float),(void*)(instances->data + (instances->cols*i)) , 0, NULL, NULL);

このコードではうまく動作し、読み取り部分でスタックすることがあります。

ret = clEnqueueReadBuffer(command_queue, gpu_data, CL_TRUE, 0,sizeof( float ) * instances->cols* 1 , instances->data, 0, NULL, NULL);

あそこに。そして、それは次のようなエラーを出します

CL_kmeans.exe の 0x10001098 で未処理の例外: 0xC000001D: 不正な命令。

ブレークが押されると、次のようになります。

コール スタック フレームのシンボルは読み込まれません。ソースコードを表示できません。

デバッグ中。コール スタックでは、次のように表示されます。

OCL8CA9.tmp.dll!10001098()
[以下のフレームは、OCL8CA9.tmp.dll のシンボルがロードされていないため、正しくないか欠落している可能性があります]
amdocl.dll!5c39de16()

私はそれが何を意味するのか本当にわかりません。誰かがこの問題を取り除くのを手伝ってください。

4

1 に答える 1

4

まず第一に、CUDA コードでは、データをコピーするために非常に非効率的なことを行っています。CUDA ランタイムには、cudaMemcpy2Dさまざまな行をループすることで、まさに実行しようとしている機能があります。

最適なcudaMallocPitchピッチ (= 2D 配列の行間のバイト単位の距離) を計算して、新しい行が合体に最適なアドレスで始まるようにし、行数のピッチ倍の大きさのメモリ領域を割り当てます。あなたが指定します。最初に最適なピッチを計算し、次に正しいサイズの割り当てを行うことで、OpenCL で同じことをエミュレートできます。

最適なピッチは、(1) カードのベース アドレス アライメント設定を取得することによって計算されます (clGetDeviceInfo を使用した CL_DEVICE_MEM_BASE_ADDR_ALIGN プロパティ: 返される値はビット単位であるため、バイト単位で取得するには 8 で割る必要があることに注意してください)。これを(2)自然なデータピッチ(sizeof(type)×列数)以上baseの最大倍数を見つけます。baseこれがあなたの になりますpitch

pitch次に、行バイト数の倍数を割り当て、pitch情報をカーネルに渡します。

また、ホストからデバイスにデータをコピーするとき、および逆に、clEnqueue{Read,Write}BufferRect2D データをコピーするために特別に設計された を使用する必要があります (これらは に対応しcudaMemcpy2Dます)。

于 2012-05-05T18:45:51.220 に答える