Skip to the content.

[English]

OpenCL

OpenCL を用いたGPUおよびCPUでの並列計算。


■ 1. LUX.GPU.OpenCL ライブラリ

TOpenCL :TCLSystem のシングルトン
 ┃
TCLSystem :システム
 ┗TCLPlatfos :プラットフォームリスト
   ┗TCLPlatfo :プラットフォーム
     ┣TCLExtenss :拡張機能リスト
     ┣TCLDevices :デバイスリスト
     ┃ ┗TCLDevice :デバイス
     ┗TCLContexs :コンテキストリスト
       ┗TCLContex :コンテキスト
         ┣TCLQueuers :コマンドキューリスト
         ┃ ┗TCLQueuer :コマンドキュー
         ┣TCLArgumes :実引数リスト
         ┃ ┣TCLBuffer :バッファー
         ┃ ┣TCLImager :イメージ
         ┃ ┗TCLSamplr :サンプラー
         ┣TCLLibrars :ライブラリリスト
         ┃ ┗TCLLibrar :ライブラリ
         ┗TCLExecuts :実行プログラムリスト
           ┗TCLExecut :実行プログラム
             ┣TCLBuildrs :ビルドリスト
             ┃ ┗TCLBuildr :ビルド
             ┗TCLKernels :カーネルリスト
               ┗TCLKernel :カーネル
                 ┗TCLParames :仮引数リスト
                   ┗TCLParame :仮引数


■ 2. ライブラリの利用方法

TOpenCLクラスは、TCLSystemクラスのシングルトンです。 TCLSystemクラスは、実行マシンにおけるすべての計算用デバイスを自動的に検出します。

⬤ 2.1. プラットフォーム

プラットフォーム”オブジェクト (TCLPlatfo) は、各デバイスベンダーが定義する環境を表します。 TCLSystemクラスは、すべてのプラットフォームを自動的に検出し、Platfos[]プロパティに列挙されます。

Object Pascal

TOpenCL.Platfos.Count :Integer    // 全プラットフォームの数
TOpenCL.Platfos[*]    :TCLPlatfo  // 全プラットフォームの配列

特定のプラットフォームに関する情報は、TCLPlatfoクラスのプロパティから取得できます。

Object Pascal

_Platfo := TOpenCL.Platfos[0];  // 特定プラットフォームの選択

_Platfo.Handle        :T_cl_platform_id  // ポインタ
_Platfo.Profile       :String            // プロファイル
_Platfo.Version       :String            // バージョン
_Platfo.Name          :String            // 名前
_Platfo.Vendor        :String            // ベンダー名
_Platfo.Extenss.Count :Integer           // 拡張機能の数
_Platfo.Extenss[*]    :String            // 拡張機能の配列

⬤ 2.2. デバイス

デバイスオブジェクト (TCLDevice) は、物理的なGPUやCPUを表します。 TCLPlatfoクラスは、特定のプラットフォーム内のすべてのデバイスを自動的に検出し、Devices[]プロパティに列挙されます。

Object Pascal

_Platfo.Devices.Count :Integer    // デバイスの数
_Platfo.Devices[*]    :TCLDevice  // デバイスの配列

特定のデバイスに関する情報は、TCLDeviceクラスのプロパティから取得できます。

Object Pascal

_Device := _Platfo.Devices[0];  // 特定デバイスの選択

_Device.Handle           :T_cl_device_id    // ポインタ
_Device.DEVICE_TYPE      :T_cl_device_type  // タイプ
_Device.DEVICE_VENDOR_ID :T_cl_uint         // ベンダーID
_Device.DEVICE_NAME      :String            // 名前
_Device.DEVICE_VENDOR    :String            // ベンダー
_Device.DRIVER_VERSION   :String            // ドライバのバージョン
_Device.DEVICE_PROFILE   :String            // プロファイル
_Device.DEVICE_VERSION   :String            // バージョン

⬤ 2.3. コンテキスト

コンテキスト” (TCLContex) は、関連するデータやプログラムを管理および保持します。 TCLContexクラスは、TCLPlatfoクラスを引数として生成できます。

Object Pascal

_Contex := TCLContex.Create( _Platfo );

生成されたTCLContexクラスは、TCLPlatfoクラスのContexs[]プロパティへ登録されます。

Object Pascal

_Platfo.Contexs.Count :Integer    // コンテキストの数
_Platfo.Contexs[*]    :TCLContex  // コンテキストの配列

⬤ 2.4. コマンドキュー

コマンドキュー”オブジェクト (TCLQueuer) は、デバイスに送られる命令を管理します。 つまり、コンテキストデバイス間での命令のやり取りを管理します。 TCLQueuerクラスは、TCLContexクラスとTCLDeviceクラスを引数として生成できます。

Object Pascal

_Queuer := TCLQueuer.Create( _Contex, _Device );
  {or}
_Queuer := _Contex.Queuers[ _Device ];

生成されたTCLQueuerクラスは、TCLContexクラスのQueuers[]プロパティへ登録されます。

Object Pascal

_Contex.Queuers.Count :Integer    // コマンドキューの数
_Contex.Queuers[*]    :TCLQueuer  // コマンドキューの配列

なお、異なるプラットフォームコンテキストデバイスを接続するコマンドキューは生成できません。

Object Pascal

P0 := TOpenCL.Platfos[0];
P1 := TOpenCL.Platfos[1];
P2 := TOpenCL.Platfos[2];

D00 := P0.Devices[0];  D01 := P0.Devices[1];  D02 := P0.Devices[2]; 
D10 := P1.Devices[0];
D20 := P2.Devices[0];

C0 := TCLContex.Create( P0 ); 
C1 := TCLContex.Create( P1 ); 
C2 := TCLContex.Create( P2 );

Q00 := TCLQueuer.Create( C0, D00 );  // OK
Q01 := TCLQueuer.Create( C0, D01 );  // OK
Q02 := TCLQueuer.Create( C0, D02 );  // OK

Q10 := TCLQueuer.Create( C1, D00 );  // エラー
Q11 := TCLQueuer.Create( C1, D01 );  // エラー
Q12 := TCLQueuer.Create( C1, D02 );  // エラー

Q20 := TCLQueuer.Create( C2, D00 );  // エラー
Q21 := TCLQueuer.Create( C2, D10 );  // エラー
Q22 := TCLQueuer.Create( C2, D20 );  // OK

⬤ 2.5. 実引数

TCLArgume
 ┣TCLMemory
 ┃ ┣TCLBuffer
 ┃ ┗TCLImager
 ┗TCLSamplr

▼ 2.5.1. メモリー

メモリー”オブジェクト (TCLMemory) は、さまざまなデータを保存し、デバイスと共有します。 TCLMemoryクラスは、TCLContexクラスとTCLQueuerクラスを引数として生成できます。 TCLMemoryクラスは抽象クラスであり、TCLBufferクラスとTCLImagerクラスを派生させます。

▽ 2.5.1.1. バッファー

TCLBufferクラスは、任意の“単純型”や“レコード型”の配列を格納します。

デバイスへ以下のような構造体型の配列を送りたい場合、

OpenCL C

typedef struct {
  int    A;
  double B;
} TItem;

kernel void Main( global TItem* Buffer ) {
  ・・・
}

以下のようにTCLBufferクラスを生成します。

Object Pascal

TItem = record
  A :Integer;
  B :Double;
end;

_Buffer := TCLBuffer<TItem>.Create( _Contex, _Queuer );

配列データは、Data[]プロパティを通して読み書きします。 ホストとデバイスの同期のため、配列データを使用する前に“マップ”し、終了後に“アンマップ”する必要があります。

Object Pascal

_Buffer.Count := 3;                          // 要素数の設定
_Buffer.Data.Map;                            // メモリ領域を展開
_Buffer.Data[0] := TItem.Create( 1, 2.34 );  // 書き込み
_Buffer.Data[1] := TItem.Create( 5, 6.78 );  // 書き込み
_Buffer.Data[2] := TItem.Create( 9, 0.12 );  // 書き込み
_Buffer.Data.Unmap;                          // メモリ領域を同期

▽ 2.5.1.2. イメージ

イメージ”オブジェクト (TCLImager) は、1D~3Dにおけるピクセル配列を格納します。 3Dのボクセルデータもイメージの一種と見なされます。 TCLImagerクラスは抽象クラスであり、カラーチャンネルのレイアウトやビット数に応じて、様々なクラスが派生します。

TCLImager
 ┣TCLImager1D
 ┃ ┣TCLImager1DxBGRAxUInt8
 ┃ ┣TCLImager1DxBGRAxUFix8
 ┃ ┣TCLImager1DxRGBAxUInt32
 ┃ ┗TCLImager1DxRGBAxSFlo32
 ┣TCLImager2D
 ┃ ┣TCLImager2DxBGRAxUInt8
 ┃ ┣TCLImager2DxBGRAxUFix8
 ┃ ┣TCLImager2DxRGBAxUInt32
 ┃ ┗TCLImager2DxRGBAxSFlo32
 ┗TCLImager3D
   ┣TCLImager3DxBGRAxUInt8
   ┣TCLImager3DxBGRAxUFix8
   ┣TCLImager3DxRGBAxUInt32
   ┗TCLImager3DxRGBAxSFlo32

クラス名の1番目の部分は、画像の次元を表しています。

クラス名の2番目の部分は、カラーチャンネルの順番を表しています。

クラス名の3番目の部分は、色のデータ型を表しています。

X/Y/Z方向のピクセル数は、’CountX’/’Y’/’Z’ プロパティで設定できます。

Object Pascal

_Imager := TCLDevIma3DxBGRAxUInt8.Create( _Contex, _Queuer );
_Imager.CountX := 100;  // X方向ピクセル数
_Imager.CountY := 200;  // Y方向ピクセル数
_Imager.CountZ := 300;  // Z方向ピクセル数

▼ 2.5.2. サンプラー

サンプラーオブジェクト (TCLSamplr) は、ピクセル色を実数座標で得るための補間方法を定義します。
TCLSamplr クラスは、’TCLContex’クラスを引数として生成できます。

Object Pascal

_Samplr := TCLSamplr.Create( _Contex );

⬤ 2.6. プログラム

プログラム”オブジェクト (TCLProgra) は、ソースコードを読み込んで、実行可能なバイナリへビルドします。 TCLPrograクラスは、’TCLContex’クラスを引数として生成できます。 TCLPrograクラスは抽象クラスであり、ソースコードの種類に応じて、TCLLibrarクラスまたはTCLExecutクラスの基底クラスとして機能します。

▼ 2.6.1. ライブラリ

TCLLibrarクラスは、直接実行する関数を含まないプログラムです。

Object Pascal

_Librar := TCLLibrar.Create( _Contex );

_Librar.Source.LoadFromFile( 'Librar.cl' );  // ソースコードのロード

▼ 2.6.2. エグゼキュータブル

TCLExecutクラスは、直接実行する関数(カーネル)を含んだプログラムです。

Object Pascal

_Execut := TCLExecut.Create( _Contex );

_Execut.Source.LoadFromFile( 'Execut.cl' );  // ソースコードのロード

⬤ 2.7. ビルド

ビルド (TCLBuildr) はプログラムが行う“行為”ですが、このライブラリでは、ビルドはクラスとして明確に定義されています。 TCLBuildr クラスは、’TCLExecut’クラスと’TCLDevice’クラスを引数として生成できます。

Object Pascal

_Buildr := TCLBuildr.Create( _Execut, _Device );
  {or}
_Buildr := _Execut.Buildrs[ _Device ];
  {or}
_Buildr := _Execut.BuildTo( _Device );

カーネルオブジェクト(2.8.章参照)は、実行時にTCLBuildrクラスを自動的に生成します。 しかし、カーネルの実行前にTCLBuildrクラスを作成することで、コンパイルとリンクのエラーを事前に確認することができます。

Object Pascal

_Buildr.Handle;  // ビルドの実行(ハンドルの生成)

_Buildr.CompileStatus :T_cl_build_status  // コンパイルのスタータス
_Buildr.CompileLog    :String             // コンパイルのログ
_Buildr.LinkStatus    :T_cl_build_status  // リンクのスタータス
_Buildr.LinkLog       :String             // リンクのログ

⬤ 2.8. カーネル

カーネル”オブジェクト (TCLKernel) は、プログラム内の実行可能な関数を指します。

OpenCL C

kernel void Main( ・・・ ) {
  ・・・
}

TCLKernelクラスは、TCLExecutクラスとTCLQueuerクラスを引数にして生成できます。

Object Pascal

_Kernel := TCLKernel.Create( _Execut, 'Main', _Queuer );
  {or}
_Kernel := _Execut.Kernels.Add( 'Main', _Queuer );

▼ 2.8.1. 仮引数

メモリオブジェクトは、TCLKernelクラスのParames[]プロパティを介して、ソースコード内の引数に関連付けられます。

Object Pascal

_Kernel.Parames['Buffer'] := _Buffer;  // バッファーの接続
_Kernel.Parames['Imager'] := _Imager;  // イメージ の接続
_Kernel.Parames['Samplr'] := _Samplr;  // サンプラーの接続

▼ 2.8.2. 反復回数

OpenCL のプログラムは、3重のループ構文のように繰り返し実行されます。

Object Pascal

_Kernel.GloSizX := 100;  // X方向のループ回数
_Kernel.GloSizY := 200;  // Y方向のループ回数
_Kernel.GloSizZ := 300;  // Z方向のループ回数

ループの最小および最大インデックスを指定することも可能です。

Object Pascal

_Kernel.GloMinX := 0;      // X方向の開始インデックス
_Kernel.GloMinY := 0;      // Y方向の開始インデックス
_Kernel.GloMinZ := 0;      // Z方向の開始インデックス

_Kernel.GloMaxX := 100-1;  // X方向の終了インデックス
_Kernel.GloMaxY := 200-1;  // Y方向の終了インデックス
_Kernel.GloMaxZ := 300-1;  // Z方向の終了インデックス

▼ 2.8.3. 実行

Object Pascal

_Kernel.Run;  // 実行

■ 3. 参考文献

⬤ 3.1. The Khronos Group Inc

⬤ 3.2. GitHub