opencl
ホストメモリインタラクション
サーチ…
前書き
このトピックでは、デバイスがアクセスできる場所のどこかにデータを置くさまざまな方法を紹介します。
配列の読み込み
デバイスからホストにアレイを読み込むには、
clEnqueueReadBuffer($queue, $memobj, $blocking, $offset, $size, $target, 0, null, null);
$キューは、デバイス上のメモリを割り当てるために使用されたCommandQueueです。 $ memobjにはデバイスメモリへのアドレスが含まれています。$ offsetと$ sizeは、どこにどのくらいのデータがコピーされるかを定義します。 $ targetは、データが格納されるホストメモリへのポインタです。$ targetは、割り当てられ、適切なサイズを持つ必要があります。
テクスチャを読む
画像を読み取ることは、配列を読み取ることとほとんど同じです。唯一の違いは、サイズとオフセットが3次元である必要があることです。
clEnqueueReadImage($queue, $memobj, $blocking, $offset, $size, $stride, $slice_pitch, $target, 0, null, null);
$ strideは、行に含まれるバイト数を定義します。通常これは単なる幅*(1ピクセルあたりのバイト数)ですが、誰かがそれを変更してメモリバンクとデータを整列させたいかもしれません。 $ slice_pitchについても同じことが言えますが、この値は3次元目のものです。
2Dテクスチャの作成
テクスチャをデバイスにコピーするには、2つのステップが必要です
- デバイスにメモリを割り当てる
- イメージをデバイスにコピーする
_mem = clCreateImage2D($context, $mem_flags, $image_format, $width, $height, $stride, $source, &err);
$ mem_flagsはメモリの割り当て方法を定義します。読み取り専用、書き込み専用、または両方のいずれかになります。さらに、メモリがどこにどのように割り当てられるかを定義することができます。 $ width、$ height、$ strideはかなり自明です。
あなたのmem_flagsがデータをコピーするなら、あなたは完了です。後で手動で行う場合は、準備ができたら別の関数を呼び出す必要があります。
err = clEnqueueWriteImage($queue, _mem, $blocking, $offset, $size, $stride, $slice_pitch, $source, 0, null, null);
$ offsetと$ sizeは、ターゲットメモリにコピーしたい画像領域を定義します。 $ strideは、行に含まれるバイト数を定義します。通常これは単なる幅*(1ピクセルあたりのバイト数)ですが、誰かがそれを変更してメモリバンクとデータを整列させたいかもしれません。 $ slice_pitchについても同じことが言えますが、この値は3次元目のものです。 $ strideと$ slice_pitchの両方が入力データと一致する必要があります。
メモリフラグ
メモリを割り当てるときは、さまざまなモードの中から選択することができます。
- 読み取り専用メモリ
- メモリのみ書き込み
- メモリの読み書き
読み取り専用メモリは__constantメモリ領域に割り当てられ、他の2つは通常の__global領域に割り当てられます。
アクセシビリティに加えて、メモリが割り当てられる場所を定義することができます。
- 指定されていない:メモリは、期待どおりにデバイスメモリに割り当てられます。 $ sourceポインタはnullに設定できます。
- CL_MEM_USE_HOST_PTR:これは、データがシステムRAMにあり、移動してはならないことをデバイスに伝えます。その代わりに、データはRAM内で直接操作されます。
- CL_MEM_COPY_HOST_PTR:指定されたアドレスのすべての値をデバイスメモリにコピーするか、またはCL_MEM_ALLOC_HOST_PTRを使用して、システムRAM内の別のメモリ領域にコピーするようにデバイスに指示します。
- CL_MEM_ALLOC_HOST_PTR:システムRAMに領域を割り当てるようにデバイスに指示します。唯一のパラメータとして使用すると、$ sourceポインタをnullに設定できます。
高速で、デバイスのグローバルメモリへのアクセスが最も高速です。しかし、データをコピーするには、それを2度呼び出す必要もあります。 Alloc_host_ptrはより速いスピードを提供しますが、ホストポインタを使用するのが最も遅いです。
use_host_ptrを使用すると、デバイスは正確にそれを行います。システムRAM内のデータを使用します。もちろん、osによってページされます。したがって、すべてのメモリコールは、潜在的なページフォールトを処理するためにCPUを通過する必要があります。データが利用可能になると、CPUはそれをピンメモリにコピーし、貴重なCPUクロックサイクルを使用してDMAコントローラに渡します。反対に、alloc_host_ptrは、システムRAM内の固定メモリを割り当てます。このメモリーはpageswap機構の外部に置かれているため、可用性が保証されています。したがって、デバイスはシステムRAMにアクセスするときにCPUを完全にスキップし、DMAを使用してデータをデバイスにすばやくコピーできます。
配列を書く
配列の作成は、次の2つのステップで構成されます。
- メモリの割り当て
- データのコピー
メモリを割り当てるには、
_mem = clCreateBuffer($queue, $mem_flags, $size, $host_ptr, &err);
十分です。 mem_flagsを介してホストポインタをコピーすることに決めたなら、あなたは完了です。それ以外の場合は、いつでも好きなときにデータをコピーすることができます
err = clEnqueueWriteBuffer($queue, _mem, $blocking, $offset, $size, $source, 0, null, null);