2013-07-21 17 views
5

私はOpenCLでちょっと試してみましたが、ホストとデバイス間のメモリ転送速度をテストしています。 私はIntel OpenCL SDKを使用していて、統合グラフィックスのIntel i5 Processorで動作していました。 私はそのように同様に固定メモリを使用する場合より速くほぼ10倍であることが判明代わりclEnqueueWriteBufferclEnqueueMapBufferを発見:abret 128ビット整列のint配列であるCL_MEM_ALLOC_HOST_PTRはCL_MEM_USE_HOST_PTRよりも遅い

int amt = 16*1024*1024; 
... 
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, a, NULL); 
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, b, NULL); 
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, ret, NULL); 

int* map_a = (int*) clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error); 
int* map_b = (int*) clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error); 
int* map_c = (int*) clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error); 
clFinish(c_q); 

。 時間は、しかしclEnqueueWriteBuffer を私は91.350065ミリ

k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL); 
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL); 
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL); 

int* map_a = (int*)clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error); 
int* map_b = (int*)clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error); 
int* map_c = (int*)clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error); 

/** initiate map_a and map_b **/ 

時間の増加に自分のコードを変更したときに、どのような可能性が使用して198.604528 MSに比べ、およそ22.026186ミリに出てきました問題なの?それとも、まったく問題なの?

EDIT: これは、私は2番目のコードで配列を初期化する方法である:

for (int i = 0; i < amt; i++) 
{ 
    map_a[i] = i; 
    map_b[i] = i; 
} 

そして今、私がチェックしていること、map_aとmap_b プログラムの最後に右の要素が含まれていますが、ありませんmap_cにはすべて0が含まれます。私はこれでした:

clEnqueueUnmapMemObject(c_q, k_a, map_a, 0, NULL, NULL); 
clEnqueueUnmapMemObject(c_q, k_b, map_b, 0, NULL, NULL); 
clEnqueueUnmapMemObject(c_q, k_c, map_c, 0, NULL, NULL); 

を、私のカーネルは、私の理解では、CL_MEM_ALLOC_HOST_PTRが割り当てるが、コピーされないということであるだけで

__kernel void test(__global int* a, __global int* b, __global int* c) 
{ 
    int i = get_global_id(0); 
    c[i] = a[i] + b[i]; 
} 
+0

2番目のコードでは、a、b、retデータを使ってk_a、k_b、k_cをどのように初期化するか、clFinishはどのように初期化することができますか? 2つのコードが異なることをすると、あなたを助けることは難しいでしょう –

+0

申し訳ありませんが、コードは同じです。私は偶然にすべてをコピーしませんでした。2番目のコードでは、map_cからデータを読み込めると思ったので、k_cをretで初期化しません。 – selena731

+0

マッピングと使用の後で、メモリの一貫性を保証するためにマップされたオブジェクトのマップを解除するか、clWrite/Readを実行する必要があります。 – DarkZeros

答えて

1

です。 2番目のコードブロックは実際にデバイスにデータを取得しますか?

また、CL_MEM_USE_HOST_PTRおよびCL_MEM_COPY_HOST_PTRと一緒に使用する場合、clCreateBufferにはclEnqueueWriteは必要ありません。バッファは、void * host_ptrが指すメモリを使用して作成されるためです。

のOpenCLで「固定」のメモリを使用することのようなプロセスである必要があります。

int amt = 16*1024*1024; 
    int Array[] = new int[amt]; 
    int Error = 0; 

    //Note, since we are using NULL for the data pointer, we HAVE to use CL_MEM_ALLOC_HOST_PTR 
    //This allocates memory on the devices 
    cl_mem B1 = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, &Error); 

    //Map the Device memory to host memory, aka pinning it 
    int *host_ptr = clEnqueueMapBuffer(queue, B1, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &Error); 

    //Copy from host memory to pinned host memory which copies to the card automatically` 
    memcpy(host_ptr, Array, sizeof(int)*amt); 

    //Call your kernel and everything else and memcpy back the pinned back to host when 
    //you are done 

編集:あなたがプログラムをスピードアップするために行うことができる一つの最終のものがCL_FALSEを使用してブロックメモリの読み出し/書き込みをしないことですCL_TRUEの代わりに。コマンドキューが空になり、すべてのコマンドが処理されるように、データがホストにコピーされる前にclFinish()を呼び出すようにしてください。

出典:フラグの適切な組み合わせでOpenCL In Action

+0

Sryが、この回答に同意できません。メモリをマッピングしてmemcpy()を実行すると、実際にはDMAを使用してデータが並列にコピーされるため、高速化する必要があります。ただし、unmap()がなければ、カーネルで使用することはできません。カーネルはバッファの完全ではないコピーを使用する可能性があるためです。通常、これは人為的なスピードアップにつながりますが、それは実際にはうまくいっていませんが、不完全なメモリコピーです。 – DarkZeros

+0

これは、物理ページまたはスワップインを解決する必要がないように、ピンイン(つまりページロック)とマッピング(つまり、一方の面への書き込み時のPCIeトランザクション)を混同しませんか? – einpoklum

0

、あなたは「ゼロコピー」を達成することができるはずのIntel統合グラフィックスに(すなわち、非常に高速な)マップ/アンマップへの「CPUのための必要はありませんので、 GPU "コピーは両方とも同じメモリを使用しているため(「統合」という意味です)メモリのIntel OpenCL Optimization Guideセクションを読んでください。

関連する問題