ぎわやまのFPGAといろいろ

大学の研究室から発信中〜

clEnqueueMigrateMemObjectsとclEnqueueMapBufferの概要

まず、OpenCLのメモリオブジェクトについておさらい。

 

メモリオブジェクトは、バッファオブジェクト画像オブジェクトの2つのタイプに分類される。

バッファオブジェクトが1次元配列の要素を格納し、画像オブジェクトが2次元または3次元のテクスチャ、フレームバッファ、または画像を格納する。

OpenCL 詳説より)

メモリオブジェクトは、cl_memオブジェクトで取り扱われます。

バッファオブジェクトの場合、要素は連続した形で格納され、デバイス上で実行しているカーネルからポインタを用いてアクセスできる。

 

f:id:giwayama:20211014151539p:plain

clCreateBuffer関数を用いて生成する。

 

clEnqueueMapBuffer

この関数で、指定したバッファにホストからアクセスできる(ように見える?)ポインタを取得できる。

cl_memオブジェクトには、ホスト側ポインタとデバイス側ポインタの2種類があり、clEnqueueMapBufferを使えば、デバイスアドレス空間にあるグローバルメモリ上の特定のバッファを、ホストのアドレス空間マッピングしてポインタ(ホスト側ポインタ)を返してくれる。

 

clEnqueueMigrateMemObjects

ホストからデバイスにデータを転送したいとき、

clEnqueueMapBufferで取得したホスト側のポインタにそのデータを書き込んで、clEnqueueMigrateMemObjectsにそのポインタを引数として渡すと、データをデバイスに転送できます。

ホストのグローバルメモリ領域に書いたデータをデバイスのグローバルメモリ領域に移してくれる、というイメージなのかな。

 

グローバルメモリをおさらい...

f:id:giwayama:20211014154252p:plain

これはZCU102評価ボードのPlatform DiagramをVitisで表示したものだけど、

LPDとかHP0とか書いてあるメモリのイラストが「グローバルメモリ」で、ZYNQ(ホスト)とZU9EG(デバイス)の両方からアクセスできる。

 

デフォルトでは、カーネルがリンクされる場合、すべてのカーネルからのメモリ インターフェイスが 1 つのデフォルトのグローバル メモリ バンクに接続されます。(UG1188

複数のメモリバンクを使うことも出来るけど、何も指定しなければ1つ。例えば次の図みたいな感じ。

f:id:giwayama:20211014120919p:plain

要点

・ホストとデバイスの両方からアクセスできる「グローバルメモリ」は、それぞれに専有のアドレス空間がある。

 

・グローバルメモリにデバイスからアクセスしたいバッファを作った場合、そこには直接ホストからアクセスできない。なぜなら、バッファはデバイスアドレス空間に置かれているから。

clEnqueueMapBuffer関数を使ってそのメモリオブジェクトの領域をホスト側のアドレス空間マッピングすれば、ホストはその領域に対して読み書きできるようになる。アクセスが終わったらアンマッピングする。

 

次に知りたいこと・疑問

OpenCL詳説もっと読んでOpenCLのこと知ろう。

 

カーネルはどのタイミングでグローバルメモリ上のデータをローカルメモリ(FPGAの内部メモリ BRAMなど)に転送するのか?

ハードウェア関数を呼び出したとき(カーネルを実行したとき)?

ハードウェア関数内で、引数にかかれた配列の要素を使う(読み出す)とき?

 

→おそらく後者。ハードウェア関数内で配列を定義して、そこにホストから転送されたデータを格納するときにグローバルメモリにアクセスする。その配列はBRAMに格納される。