19

チュートリアルで両方のバージョンを見ましたが、それらの長所と短所が何であるかを知ることができませんでした。どちらが適切ですか?

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

対。

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL);

ありがとう。

[アップデート]

CL_MEM_COPY_HOST_PTR,正しくするために、2番目の例に追加しました。

4

5 に答える 5

10

OpenCLでの作業中に、私は

cl_mem CT = clCreateImage3DContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , Volume_format, X, Y, Z, rowPitch, slicePitch, sourceData, &error);

cl_mem CT = clCreateImage3D(Context, CL_MEM_READ_ONLY , Volume_format, X, Y, Z, 0, 0, 0, &error);
error = clEnqueueWriteImage(CommandQue, CT, CL_TRUE, origin, region, rowPitch, slicePitch, sourceData, 0, 0, 0);

最初のアプローチでは、OpenCLはGPUに直接ではなくホストポインターをコピーします。まず、ホストに2番目の一時バッファーを割り当てます。これは、CTなどの大きなものをGPUにロードする場合に問題を引き起こす可能性があります。短時間の間、必要なメモリはCTサイズの2倍です。また、この機能の間、データはコピーされません。引数設定時に3D画像オブジェクトを使用するカーネル関数にコピーされます。

2番目のアプローチでは、データをGPUに直接コピーします。OpenCLによって行われる追加の割り当てはありません。これはおそらく通常のバッファオブジェクトでも同じだと思います。

于 2012-08-02T09:58:57.977 に答える
7

inputdataはNULLではないと思います。

その場合、仕様にあるように、次の場合、clCreateBufferはNULLとエラーを返すため、2番目のアプローチはまったく機能しないはずです。

CL_INVALID_HOST_PTR(host_ptrがNULLでCL_MEM_USE_HOST_PTRまたはCL_MEM_COPY_HOST_PTRがフラグに設定されている場合、またはhost_ptrがNULLではないがCL_MEM_COPY_HOST_PTRまたはCL_MEM_USE_HOST_PTRがフラグに設定されていない場合)。

だからあなたはどちらかを意味します

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

また

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

最初のアプローチは、最初に示したアプローチとほぼ同じである必要がありますが、2番目のアプローチは実際にはデータをコピーしませんが、代わりに、提供されたメモリ位置をバッファストレージに使用します(デバイスメモリにデータの一部またはすべてをキャッシュします) 。これら2つのうちどちらが優れているかは、明らかに使用シナリオによって異なります。

個人的には、最初にバッファーを割り当て、その後writeToBufferで埋めるという、2ステップのアプローチを使用することを好みます。何が起こるかを確認するのが簡単だからです(もちろん、1ステップの方が速いかもしれません(またはそうでないかもしれませんが、それは単なる推測です))

于 2010-10-01T03:07:31.773 に答える
4

最初のアプローチの優れた点は、「clEnqueueWriteBuffer」を使用すると、バッファーのコピーにイベントを割り当てることができることです。したがって、GPU_Profilingオプションを使用してデータをGPUにコピーするのにかかる時間を測定したい場合、最初のアプローチでは測定できますが、2番目のアプローチでは測定できません。

2番目のアプローチは、よりコンパクトで読みやすく、コーディングに必要な行数が少なくて済みます。

于 2012-05-24T19:25:02.647 に答える
3

私が遭遇した1つの大きな違い:

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL); clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

この最初のコマンドセットは、空のバッファーを作成し、コマンドキューにコマンドをエンキューしてバッファーをいっぱいにします。

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL)

この2番目のコマンドは、バッファーを作成し、すぐにいっぱいにします。この引数リストにはコマンドキューがないため、現在の入力データの内容がそのまま使用されることに注意してください。

すでにCLコードを実行していて、ソースポインターが、コマンドキュー内の前のコマンドの完了に依存している場合(たとえば、前の出力バッファーのキューに入れられた読み取り)、必ず1番目の方法を使用する必要があります。1つのコマンドでバッファを作成して埋めようとすると、前のバッファ読み取りの完了をバッファの内容が適切に待機しない競合状態が発生します。

于 2011-02-12T19:35:26.480 に答える
2

これら2つの主な違いは、最初の1つがデバイスにメモリを割り当ててから、そのメモリにデータをコピーすることです。2番目のものは割り当てるだけです。

それとも意味clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);ですか?

于 2010-09-30T18:43:43.443 に答える