SSブログ

OS XのOpenCL - その9 [OS XのOpenCL]

すごい!スタック深さ1以上の証明!ちゃんとAppleのOpenCLガイドの抄訳の前回の続きになっている。

今日のところはOpenCLで使えるメモリを作って使って捨てる、というところ...

6.4  メモリ管理のワークフロー

図7-2はOpenCLの基本的なメモリ管理ワークフローを示している。
0612fig05.png
基本的なメモリワークフローは
  1. OpenCLで使うためにメモリオブジェクトをホストが作る
    ホストはデバイス上にメモリを確保するように要求する。使えるメモリがある限りメモリオブジェクトを必要な数だけ要求することができる。入力と出力用に分離されたメモリオブジェクトを作ることができるが、必ず必要というわけではない。アルゴリズムにとって意味があるなら、入力と出力の両方にひとつのバッファを使ってもいい。しかしイメージはもっと厳密である。イメージは入力か出力かのどちらかに使われて、入力と出力の両方としていっぺんに使われることはない
  2. ホストはメモリオブジェクトの中身を初期化する。
    ホストはメモリオブジェクトの中にしまわれたデータをデバイスに渡すことができる。それはカーネルが処理するべきデータである。ホストは初期化されていないメモリオブジェクトを渡してデバイス上でカーネルが走った時にカーネルに出力用としてデータを埋めるように指示することもできる。
    ホストはデバイスで作られたメモリオブジェクトをカーネルに渡してカーネルを実行するようにデバイスに対して指示する。ホストはカーネルの実行を待つことなく他の仕事を続ける
  3. カーネルはデバイス上で走って、データを処理して、出力を生成する
  4. ホストはメモリオブジェクトから結果を読み出す。ホストがカーネルの仕事が終わったことを検出したら、ホストがアクセス可能なメモリにカーネルメモリから結果をコピーする。
  5. ホストはメモリオブジェクトを解放する
    メモリオブジェクトを必要とするすべてのカーネルの実行が終わったら、ホストはデバイスにカーネルが使うためにとっておいたメモリを解放するように指示する。例えば、一つのバッファがたくさんのカーネル用の入力になっていて、カーネルは何回も実行されるようなシナリオを考える。そのメモリオブジェクトを必要とするそれぞれのカーネルの実行がキューに投入されおわったとき、ホストはメモリを解放する。オブジェクトにファイナライザを指定することができる。ファイナライザはオブジェクトが解放されるときにがベージコレクタによって呼ばれる。「ファイナライザ設定」参照。
注意:OpenCLのメモリオブジェクトはCで作られているので、OS XのARCは自動的に解放しない。ホストコードはカーネルが使うメモリオブジェクトを明示的に解放しなければならない。

6.5  ファイナライザ設定

ファイナライザを指定することができる。ファイナライザはオブジェクトを解放するときにがベージコレクタに自動的に呼ばれる参照クラスの関数のひとつである。オブジェクト引数に指定されたメモリが解放されるときにOpenCLに起動されるようにするには次の関数を呼ぶ。
void gcl_set_finalizer(void *object,
                       void (*gcl_pfn_finalizer)(void *object, void *user_data),
                       void *user_data);
object
ファイナライザを接続するバッファあるいはイメージオブジェクト
(*gcl_pfn_finalizer)(void *object, void *user_data)
指定したオブジェクトが解放されるときガベージコレクタによって呼ばれるコールバック関数
コールバック関数に渡される引数は、
  • ファイナライザが接続されたバッファあるいはイメージオブジェクトへのポインタ
  • ファイナライザに渡されるユーザデータへのポインタ
つぎのリスト7-1はgcl_set_finalizerの使い方を示す例である。
// オブジェクトが解放されるときに呼ばれるファイナライザ関数の例
void my_finalizer(void* memObj,
                  // この引数はオブジェクトへのポインタで
                  // オブジェクトが解放されるときにこのファイナライザが呼ばれる
                  void* importantData
                  // ファイナライザが使うデータへのポインタ
                  )
{
    // なにかやる
}
...
void main() {
    // なにかする
    
    
    void* my_mem_object = gcl_malloc(128, NULL, 0);
    // GCLメモリオブジェクト
    struct foo *special_data =
    (struct foo*)malloc(sizeof(struct foo));
    // プログラム固有のデータ
    
    // ファイナライザコルバックを指定
    gcl_set_finalizer(my_mem_object,
                      // このオブジェクトが解放されるときファイナライザが呼ばれる
                      my_finalizer,
                      // 解放されるとき呼ばれる関数
                      special_data
                      // その関数に渡されるデータ
                      );
    
    // 他に何かする
    // そのあと、my_mem_objectを解放する
    gcl_free(my_mem_object);
    // 解放される前にOpenCLはmy_mem_objectとspecial_dataを引数に
    // my_finalizerを呼ぶ
}

6.6  OS XでのOpenCLのイメージとバッファを記述するパラメータ

イメージやバッファを取り扱う幾つかの関数は原点や範囲や行長さを容認する。
0612fig06.png
図-fig7-3では、画像を保持しているメモリはwidthとheightで帯状に区切られた四角形で表されていて、その中央に塗りつぶされた領域がある。その領域(region widthとregion heightで区切られたピンクで塗りつぶされた四角形)は操作したい画像の一部で、形と大きさが指定されている。別に言い方をすれば、領域は画像内部の与えられたオフセット(あるいはorigin原点)の、ある大きさのメモリである。originは(x,y,z)で指定される画像内部の領域の位置である。

row pitch(行ピッチ)は受け取る領域の幅である。row pitchは画像のひとつの列のバイト単位の長さである。ふつうはrow pitchは画像のピクセル単位の幅とそれぞれのピクセルのバイト単位の大きさとの積である。しかし、ときどきパフォーマンスのために画像に必要な分よりも大きくメモリが取られることがある。図-6に示すようにrow pitchは画像の幅よりも少しだけ大きくなっている。例えば、1000ピクセルの幅でピクセルが4バイトの画像の場合、row pitchは4000バイトになる。しかしハードウェアにとっては一列に4096バイトの方がより効率的に処理できることがあって、その場合はrow pitchに4096が指定される。

注意:row pitchは画像の幅と1画素のサイズの積と同じか大きくなければならない。row ptichを0に指定すると、OpenCLは1画素サイズ×幅をrow pitchにする。

あるOpenCLの多次元バッファを操作する関数、例えばgcl_memcpy_rectのような関数はslice pitchというパラメータを使う。これは3D画像のひとつの2Dレイヤ(スライス)の大きさをバイト単位で表したものである。言い換えれば、slice pitchとは画像のバイト単位のrow pitchの値と高さの積である。2次元画像の場合はslice pitchは0に指定するように。

slice pitchの値はrow pitchと高さの積と等しいか大きくなければならない。0が指定されるとOpenCLはrow pitch×高さをslice pitchにする。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。