OpenCL1.2仕様書邦訳

# 本記事の内容
　OpenCLの仕様把握を兼ねて、仕様書（[The OpenCL Specification 1.2](https://www.khronos.org/registry/OpenCL/specs/opencl-1.2.pdf)）の内容を邦訳・一部要約したものです。仕様書の完全な日本語版を作ることが目的ではありませんのでご注意ください。図や例に関する記述などを省略しています。特に、関数の詳細な仕様はKhronosの公式ページを参照してください。

<font color="Red">現状では5章12節以降は翻訳できていません。(2018/03/14)</font>

# 対象読者
・OpenCLの全体像を理解したい人

# 1. イントロダクション
　OpenCL（Open Computing Language）はCPU・GPU・その他の異種混在の計算資源を用いたオープンな並列計算を行うための標準規格です。

# 2. 用語集
**バリア**：バリアには2種類あります。OpenCL APIが提供するコマンドキューバリアと、OpenCL C言語が提供するワークアイテム間のバリアです。
**バッファオブジェクト**：バッファとはカーネルからアクセスできるポインタのことを指します。
**コマンド**：コマンドキューに送信されるOpenCL操作のことで、カーネルの実行やメモリの制御などがこれに当たります。
**コマンドキュー**：コマンドを保持するオブジェクト。コンテキスト上の特定のデバイスに対して作成されます。コマンドはキューイングした順番に実行しないことも可能です。
**コンピュートユニット（CU）**：デバイスは一つ以上のCUを持ちます。ワークグループは一つのCU上で実行されます。CUは一つ以上のPEとローカルメモリを持ちます。また、専用のテクスチャフィルタユニットを含むことができ、これはPEから参照することができます。
**コンテキスト**：カーネルを実行する環境で、同期およびメモリ管理が定義されています。コンテキストには複数のデバイスが含まれ、メモリはこれらのデバイスから参照することができます。
**カスタムデバイス**
**デバイス**：コンピュートユニットの集まりで、通常はCPU・GPU・その他のプロセッサに対応しています。
**イベントオブジェクト**：コマンド操作のステータスをカプセル化したもので、コンテキスト内でコマンド実行を同期するために使用することができます。
**イベント待機リスト**：イベントオブジェクトのリストで、特定のコマンドを実行するタイミングを制御することができます。
**イメージオブジェクト**：2次元あるいは3次元に構造化された配列で、書き込み・読み込み関数を使って参照することができます。読み込み関数ではサンプラを使用します。
**順次実行**：コマンドキューに先に入ったコマンドの実行が完了した後に次のコマンドが実行されるモデル。
**カーネル**：デバイス上で実行される関数です。
**マーカー**：マーカーはコマンドの一種で、マーカーの前に挿入されたすべてのコマンドにタグ付けすることができます。マーカーはイベントオブジェクトを返します。このイベントオブジェクトを使うことで、マーカーよりも前に挿入されたすべてのコマンドの実行完了を待機することができます。
**親デバイス**：サブデバイスを作るために分割されたデバイス。分割されたサブデバイスを親デバイスにして、さらに分割することも可能。
**プラットフォーム**：ホストおよびOpenCLフレームワークで管理されるデバイスの集合。プラットフォーム内ではリソースの共有が可能。
**プロセッシングエレメント（PE）**：一つのワークアイテムを処理するためのプロセッサ。
**参照カウント**：OpenCLオブジェクトが参照されている数を保持する内部カウンタ。retain API(clRetainContext、clRetainCommandQueueなど)を使用することでカウンタがインクリメントされ、release API(clReleaseContext, clReleaseCommandQueueなど)を使用することでカウンタがデクリメントされる。カウンタがゼロになるとオブジェクトは破棄される。
**サンプラ**：カーネル関数からテクスチャメモリを読み込むときに、どのようにサンプリングするかを記述したオブジェクト。
**SIMD**：カーネルが共有のプログラムカウンタと独自のデータを持つ複数のPEで実行されるモデル。すべてのPEは厳密に同じ命令セットを実行する。
**SPMD**：カーネルが独自のプログラムカウンタと独自のデータを持つ複数のPEで実行されるモデル。それぞれが独自のプログラムカウンタを持つため、分岐命令などによってすべてのPEが同じ命令セットを実行しないこともある。
**サブデバイス**：親デバイスから分割されたデバイス。親デバイスの使用時にサブデバイスの領域も使用される可能性がある。サブデバイスに分割しても親デバイスは破棄されることなく、サブデバイスと混在して使用することができる。
**スレッドセーフ**：OpenCL APIが複数のホストスレッドから呼び出されたとき、OpenCLの内部状態が一貫している場合スレッドセーフであるとみなされ、安全です。

# 3. OpenCLのアーキテクチャ
## 3.1 プラットフォームモデル
　プラットフォームモデルは、1つ以上のOpenCLデバイスに接続されたホストで構成されています。OpenCLデバイスは、1つ以上のCUに分割され、さらに1つ以上のPEに分割されます。 デバイス上の計算はPEで行われ、各PEはSIMDユニットまたはSPMDユニットとして命令の単一ストリームを実行します。
### 3.1.1 プラットフォーム混在のサポート
　OpenCLは単一のプラットフォームで異なる能力を持つデバイスをサポートするように設計されています。OpenCLではプラットフォーム・デバイス・OpenCL C言語の3つの要素のバージョンが考慮されます。プラットフォームのバージョンはOpenCLランタイムのバージョンを示しています。具体的にはコンテキストやメモリオブジェクトなど、ホストとOpenCLランタイムが対話するためのすべてのAPIが含まれます。デバイスのバージョンはclGetDeviceInfoで取得できるようなデバイスの性能を示します。例としては、リソースの上限や拡張機能などがこれに当たります。
　OpenCL C言語のバージョンはデバイスでサポートされているOpenCL C言語のバージョンを示しています。OpenCL Cは下位互換性があるように設計されているため、デバイスは複数の言語バージョンをサポートする必要はありません。複数の言語バージョンがサポートされている場合、コンパイラはデフォルトで、デバイスでサポートされている最高のバージョンを使用します。言語バージョンはプラットフォームのバージョンよりも高いことはありませんが、デバイスのバージョンを超えている可能性があります。
## 3.2 実行モデル
　OpenCLの実行はデバイス上でのカーネル実行と、ホスト上でのコンテキスト定義やカーネル実行制御という、2つのパートに分けられます。OpenCL実行モデルの核心はカーネルの実行方法です。ホストによってカーネル実行が送信されるとあるインデックス空間が定義され、カーネルのインスタンスはこのインデックス空間の各ポイントに対して実行されます。カーネルのインスタンスはワークアイテムと呼ばれ、グローバルIDが与えられインデックス空間上で一意に識別することができます。各ワークアイテムは同じコードを実行しますが、コードの実行経路と操作されるデータはワークアイテムごとに異なる可能性があります。
　ワークアイテムはワークグループを構成します。ワークグループはより大きくインデックス空間を分割します。ワークグループにはワークグループIDが与えら、各ワークアイテムにはワークグループ内で一意なローカルIDが与えられます。ワークアイテムはグローバルIDか、ワークグループIDとローカルIDの組み合わせを用いて一意に識別することができます。同一のワークグループに属するワークアイテムは、単一のCU上にあるPEで処理されます。
　OpenCLでサポートされているインデックス空間はNDRangeと呼ばれています。NDRangeはN次元のインデックス空間で、Nは1・2または3です。NDRangeはオフセットインデックスF（デフォルトではゼロ）で始まる、各次元のインデックス空間の範囲を記述した長さNの配列の整数配列で定義されます。ワークアイテムに与えられるグローバルIDとローカルIDはそれぞれN個の数値がペアになったものです。グローバルID要素は、Fから、Fにその次元の要素数を足してマイナス1した値までの範囲になります。
### 3.2.1 コンテキストとコマンドキュー
ホストはカーネル実行のためにコンテキストを定義します。コンテキストは次のリソースを含んでいます。

・ホストから使用されるデバイスの一覧
・デバイスで実行されるカーネル
・プログラムソースとカーネルを実装した実行可能ファイル
・ホストおよびデバイスから参照可能なメモリ

　コンテキストはOpenCL APIを通してホストによって作成および操作されます。ホストはコマンドキューと呼ばれるデータ構造を作成して、デバイス上のカーネルの実行を調整します。ホストは、コマンドをコマンドキューに入れ、コンテキスト内のデバイスにスケジュールします。これらには、

・カーネル実行のコマンド
・メモリ読み書き、あるいはメモリマップ・アンマップのコマンド
・同期のためのコマンド

が含まれます。コマンドキューはデバイス上で実行するためのコマンドをスケジュールします。これらはホストとデバイスの間で非同期に実行されます。コマンドは、次の2つのモードのいずれかで実行されます。

**順次実行**：コマンドを挿入した順に実行します。
**非順次実行**：ユーザの同期コマンドによって実行順が制御されます。

　カーネル実行およびメモリ操作のコマンドはキューイング時にイベントオブジェクトを生成します。これらはコマンド間の実行を制御し、ホストとデバイス間の実行を調整するために使用できます。複数のキューを同じコンテキストに関連付けることは可能です。これらのキューを同期するためにOpenCL内で同時に並行して実行されます。
### 3.2.2 カーネルのカテゴリ
OpenCL実行モデルは2種類のカーネルをサポートしています。

**OpenCLカーネル**はOpenCL C言語で記述され、OpenCL Compilerでコンパイルされます。すべてのOpenCL実装はOpenCLカーネルをサポートしています。
**Nativeカーネル**はホスト関数ポインタを介してアクセスされます。Nativeカーネルは、OpenCLカーネルとともに実行するためにキューに入れられ、OpenCLカーネルとメモリオブジェクトを共有します。たとえばこれらのNativeカーネルは、アプリケーションコードで定義された関数、またはライブラリからエクスポートされた関数です。Nativeカーネルを実行する機能はOpenCL内のオプションの機能であり、Nativeカーネルの意味は実装定義です。 OpenCL APIにはデバイスの機能を照会し、この機能がサポートされているかどうかを判断する機能が含まれています。

## 3.3 メモリモデル
　カーネルを実行するワークアイテムは、異なる4つのメモリ領域にアクセスすることができます。

**グローバルメモリ**：このメモリ領域はすべてのワークグループのすべてのワークアイテムに対する読み書きを許可します。ワークアイテムはメモリオブジェクトの任意の要素に対して読み書きを行うことができます。グローバルメモリへの読み書きはデバイスの機能に応じてキャッシュされます。
**コンスタントメモリ**：グローバルメモリの一部領域で、カーネルの実行中も一定のままです。ホストは定数メモリに配置されたメモリオブジェクトを割り当て、初期化できます。
**ローカルメモリ**：ワークグループで共有されるメモリ領域。このメモリ領域を使用して、そのワークグループ内のすべてのワークアイテムによって共有される変数を割り当てることができます。これはデバイスのメモリ上の専用領域として実装されているか、あるいはグローバルメモリにマッピングされています。ホストからはアクセスできません。
**プライベートメモリ**：ワークアイテム専用のメモリ領域。 あるワークアイテムのプライベートメモリに定義された変数は、別のワークアイテムからは参照できません。ホストからはアクセスできません。

　ホストとデバイスのメモリはお互いに独立しています。お互いのメモリを対応させるには、明示的にデータをコピーするか、またはメモリオブジェクトの領域をマッピングおよびアンマップする必要があります。
　データを明示的にコピーする場合は、ホストからメモリ転送コマンドを送信します。メモリ転送コマンドは、ブロッキングまたは非ブロッキングで呼び出せます。ブロッキングの場合、ホスト上のメモリリソースを安全に再利用できるようになると、メモリ転送のOpenCL関数呼び出しが返されます。非ブロッキング転送の場合、OpenCL関数呼び出しはコマンドが送信されるとすぐに戻ります。
　ホストメモリとメモリオブジェクトを対応させるマッピング・アンマッピング法は、メモリオブジェクトからホストのアドレス空間に領域をマップします。メモリマップコマンドは、ブロッキングまたは非ブロッキングで呼び出せます。メモリオブジェクトからの領域がマップされると、ホストはこの領域を読み書きできます。ホストはこのマップされた領域への読み書きが完了したら、その領域をアンマップする必要があります。
### 3.3.1 メモリ一貫性
　OpenCLは緩やかな整合性メモリモデルを使用します。すなわち、ワークアイテムから見えるメモリの状態は、ワークアイテム全体で常に一貫していることが保証されません。プライベートメモリには、ロード・ストアの一貫性があります。ローカルメモリは、ワークグループバリアによって、単一のワークグループ内のワークアイテム間で一貫しています。グローバルメモリは、ワークグループバリアによって単一のワークグループ内のワークアイテム間で一貫していますが、異なるワークグループ間のメモリ一貫性は保証されていません。送信されたコマンド間で共有されるメモリオブジェクトのメモリ一貫性は、同期ポイントで強制されます。
## 3.4 プログラミングモデル
　OpenCL実行モデルはデータ並列およびタスク並列、これらの2つのモデルのハイブリッドをサポートしています。OpenCL設計の主なモデルはデータ並列です。
### 3.4.1 データ並列プログラミングモデル
　データ並列プログラミングモデルは、メモリオブジェクトの複数の要素に適用される計算順序を定義します。OpenCL実行モデルに関連付けられたインデックス空間は、ワークアイテムとデータがどのようにマップされるかを定義します。厳密なデータ並列モデルではワークアイテムとメモリオブジェクト内の要素との間に1対1のマッピングが存在しますが、OpenCLは1対1マッピングが必須ではない緩和バージョンを実装しています。
　OpenCLは階層データ並列プログラミングモデルを提供します。明示的に階層を指定する場合、並行して実行されるワークアイテムの総数と、ワークアイテムがワークグループ間でどのように分割されるかを定義します。暗黙的に階層を指定する場合、並列に実行するワークアイテムの総数のみを指定し、ワークグループへの分割はOpenCL実装によって管理させます。
### 3.4.2 タスク並列プログラミングモデル
　タスク並列プログラミングモデルは、あるカーネルのインスタンスがインデックス空間とは独立して実行されるモデルを定義します。論理的には、単一のワークアイテムを含むワークグループを持つ計算ユニット上でカーネルを実行することと同じです。このモデルでは、ユーザーは次のように並列処理を表現します。

・ベクトル型を使用して、複数のタスクを送信する
・ベクトル型を使用して、OpenCLに直交するプログラミングモデルを使用して開発されたNativeカーネルを送信する

### 3.4.3 同期
　OpenCLには2種類の同期が存在します。

・単一ワークグループ内のワークアイテム間の同期
・同期コマンドの送信による単一コンテキスト内の同期

　単一ワークグループ内のワークアイテム間の同期は、ワークグループバリアを使用して行われます。ワークグループのすべてのワークアイテムは、バリアを超えて実行を継続する前にバリアを実行する必要があります。ワークグループバリアはワークグループのすべてのワークアイテムがバリアに到達しなくてはなりません。ワークグループ間の同期の仕組みはありません。
　コマンドキュー内のコマンド間の同期ポイントは、以下のものがあります。

**コマンドキューバリア**：コマンドキューバリアは、以前にキューに入れられたすべてのコマンドの実行が完了し、次のコマンドが実行される前にメモリオブジェクトに対するすべての更新が反映されるようにします。このバリアは、単一のコマンドキュー内のコマンド間の同期化にのみ使用できます。
**イベント待機**：コマンドを送信するすべてのOpenCL API関数は、更新するコマンドとメモリオブジェクトを識別するイベントを返します。 そのイベントで待機している後続のコマンドは、コマンドが実行を開始する前にそれらのメモリオブジェクトの更新が反映されることが保証されます。
## 3.5 メモリオブジェクト
　メモリオブジェクトはバッファオブジェクトとイメージオブジェクトの2種類に分類されます。バッファオブジェクトは要素の1次元コレクションを格納し、イメージオブジェクトは2次元または3次元のテクスチャ、フレームバッファまたはイメージを格納するために使用されます。
　バッファオブジェクトの要素は、スカラー型（int、floatなど）、ベクター型、またはユーザー定義の構造体です。イメージオブジェクトの要素は、予め定義された画像フォーマットのリストから選択します。バッファとイメージオブジェクトの基本的な違いは次のとおりです。

・バッファ内の要素はシーケンシャルに格納され、カーネルからポインタを使用してアクセスできます。イメージの要素はユーザーに不透明な形式で格納され、ポインターを使用して直接アクセスすることはできません。組み込み関数がOpenCL C言語によって提供され、カーネルのイメージに対する読み書きを可能にします。
・バッファオブジェクトの場合、データはカーネルによってアクセスされるのと同じフォーマットで格納されますが、イメージオブジェクトの場合、イメージ要素を格納するために使用されるデータフォーマットは、カーネル内部で使用されるデータフォーマットと同じでない場合があります。イメージ要素は、カーネル内で常に4成分ベクトル（各成分は浮動小数点数または符号付き・符号なし整数）です。イメージから読み取る組み込み関数は、格納されているフォーマットからイメージ要素を4成分ベクトルに変換します。同様に、イメージに書き込む組み込み関数は、イメージ要素を4要素ベクトルから、例えば4つの8ビット要素など指定された適切なイメージ形式に変換します。

　メモリオブジェクトはcl_memオブジェクトによって記述されます。カーネルはメモリオブジェクトを入力として受け取り、1つ以上のメモリオブジェクトに出力します。
## 3.6 OpenCLフレームワーク
　OpenCLフレームワークにより、アプリケーションはホストと1つ以上のデバイスを単一の異種混在の並列コンピュータシステムとして使用できます。フレームワークには次のコンポーネントが含まれています。
**OpenCLプラットフォーム層**：プラットフォーム層はホストプログラムがデバイスとその機能を使用し、コンテキストを作成することを可能にします。
**OpenCLランタイム**：ランタイムによって、ホストプログラムは作成されたコンテキストを操作することができます。
**OpenCLコンパイラ**：コンパイラはカーネルを含むプログラム実行可能ファイルを作成します。コンパイラによって実装されたOpenCL C言語は、並列処理の拡張機能を持つISO C99言語のサブセットをサポートしています。

# 4. OpenCLプラットフォーム層
　このセクションでは、アプリケーションがデバイスとデバイス設定情報を照会し、1つまたは複数のデバイスを使用してコンテキストを作成できるようにするプラットフォーム固有の機能を実装するOpenCLプラットフォーム層について説明します。
## 4.1 プラットフォーム情報の照会
***
　使用可能なプラットフォームの一覧は、次の関数を使用して取得できます。

```c
cl_int clGetPlatformIDs (
    cl_uint num_entries,
    cl_platform_id *platforms,
    cl_uint *num_platforms
)
```

詳細は[clGetPlatformIDs](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetPlatformIDs.html)を参照。
***
　次の関数はOpenCLプラットフォームに関する特定の情報を取得します。

```c
cl_int clGetPlatformInfo (
    cl_platform_id platform,
    cl_platform_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetPlatformInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetPlatformInfo.html)を参照。
***
## 4.2 デバイスの照会
***
　プラットフォーム上で利用可能なデバイスのリストは、次の関数を使用して取得できます。

```c
cl_int clGetDeviceIDs (
    cl_platform_id platform,
    cl_device_type device_type,
    cl_uint num_entries,
    cl_device_id *devices,
    cl_uint *num_devices
)
```

詳細は[clGetDeviceIDs](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetDeviceIDs.html)を参照。
***
　アプリケーションは、clGetDeviceIDsによって返されたOpenCLデバイスの特定の機能を照会できます。 これは、アプリケーションが使用するデバイスを決定するために使用できます。

```c
cl_int clGetDeviceInfo (
    cl_device_id device,
    cl_device_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetDeviceInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetDeviceInfo.html)を参照。
***
## 4.3 分割したデバイス
***
　次の関数はプロパティによって与えられるパーティションスキームに従って、in_device内のCUのそれぞれ重複しない領域を参照するサブデバイスの配列を作成します。出力されるサブデバイスはコンテキストの作成、プログラムの作成、さらにclCreateSubDevicesの呼び出し、コマンドキューの作成など、ルート（または親）デバイスと同様に使用できます。コマンド・キューがサブデバイスに対して作成されると、キューに送信されたコマンドはサブデバイス上でのみ実行されます。

```c
cl_int clCreateSubDevices (
    cl_device_id in_device,
    const cl_device_partition_property *properties,
    cl_uint num_devices,
    cl_device_id *out_devices,
    cl_uint *num_devices_ret
)
```

詳細は[clCreateSubDevices](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateSubDevices.html)を参照。
***
　次の関数はdeviceがclCreateSubDevicesの呼び出しによって作成された有効なサブデバイスである場合、デバイス参照カウントをインクリメントします。デバイスがルートレベルのデバイス、つまりclGetDeviceIDsによって返されるcl_device_idの場合、デバイス参照カウントは変更されません。

```c
cl_int clRetainDevice (
    cl_device_id device
)
```

詳細は[clRetainDevice](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainDevice.html)を参照。
***
　次の関数はdeviceがclCreateSubDevicesの呼び出しによって作成された有効なサブデバイスである場合、デバイス参照カウントをデクリメントします。デバイスがルートレベルのデバイス、つまりclGetDeviceIDsによって返されるcl_device_idの場合、デバイス参照カウントは変更されません。

```c
cl_int clReleaseDevice (
    cl_device_id device
)
```

詳細は[clReleaseDevice](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseDevice.html)を参照。
***
## 4.4 コンテキスト
***
　次の関数はコンテキストを作成します。コンテキストは1つまたは複数のデバイスで作成されます。コンテキストは、コマンドキュー、メモリ、プログラムおよびカーネルオブジェクトなどのオブジェクトを管理するため、およびコンテキストで指定された1つ以上のデバイス上でカーネルを実行するために、OpenCLランタイムによって使用されます。

```c
cl_context clCreateContext (
    const cl_context_properties *properties,
    cl_uint num_devices,
    const cl_device_id *devices,
    void (CL_CALLBACK *pfn_notify)(
        const char *errinfo,
        const void *private_info,
        size_t cb,
        void *user_data
    ),
    void *user_data,
    cl_int *errcode_ret
)
```

詳細は[clCreateContext](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateContext.html)を参照。
***
　次の関数は、使用する特定のデバイスを識別するデバイスタイプからOpenCLコンテキストを作成します。clGetDeviceIDsによって返される値がdevice_typeのデバイスだけがコンテキストの作成に使用されます。コンテキストは、これらのデバイスから作成されたサブデバイスを参照しません。

```c
cl_context clCreateContextFromType (
    const cl_context_properties *properties,
    cl_device_type device_type,
    void (CL_CALLBACK *pfn_notify)(
        const char *errinfo,
        const void *private_info,
        size_t cb,
        void *user_data
    ),
    void *user_data,
    cl_int *errcode_ret
)
```

詳細は[clCreateContextFromType](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateContextFromType.html)を参照。
***
　次の関数は、コンテキスト参照カウントをインクリメントします。

```c
cl_int clRetainContext (
    cl_context context
)
```

詳細は[clRetainContext](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainContext.html)を参照。
***
　次の関数は、コンテキスト参照カウントをデクリメントします。

```c
cl_int clReleaseContext (
    cl_context context
)
```

詳細は[clReleaseContext](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseContext.html)を参照。
***
　次の関数は、コンテキストに関する情報を照会するために使用できます。

```c
cl_int clGetContextInfo (
    cl_context context,
    cl_context_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetContextInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetContextInfo.html)を参照。
***
# 5. OpenCLランタイム
　このセクションでは、コマンドキュー、メモリオブジェクト、プログラムオブジェクト、プログラム内のカーネルオブジェクトなどのOpenCLオブジェクトを管理するAPI、およびカーネル実行やメモリ読み書きをコマンドキューに送信するAPIの呼び出しについて説明します。
## 5.1 コマンドキュー
　メモリ、プログラム、カーネルオブジェクトなどのOpenCLオブジェクトは、コンテキストを使用して作成されます。これらのオブジェクトに対する操作は、コマンドキューを使用して実行されます。コマンドキューは、一連の操作（コマンドと呼ばれる）を順番にキューに入れるために使用できます。複数のコマンドキューを持つことで、アプリケーションは同期を必要とせずに複数の独立したコマンドをキューに入れることができます。これらのオブジェクトが共有されていない限り、これは機能します。複数のコマンドキュー全体でオブジェクトを共有するには、アプリケーションが適切な同期を実行する必要があります。
***
　次の関数は特定のデバイスに対してコマンドキューを作成します。

```c
cl_command_queue clCreateCommandQueue (
    cl_context context,
    cl_device_id device,
    cl_command_queue_properties properties,
    cl_int *errcode_ret
)
```

詳細は[clCreateCommandQueue](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateCommandQueue.html)を参照。
***
　次の関数は、command_queue参照カウントをインクリメントします。

```c
cl_int clRetainCommandQueue (
    cl_command_queue command_queue
)
```

詳細は[clRetainCommandQueue](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainCommandQueue.html)を参照。
***
　次の関数は、command_queue参照カウントをデクリメントします。

```c
cl_int clReleaseCommandQueue (
    cl_command_queue command_queue
)
```

詳細は[clReleaseCommandQueue](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseCommandQueue.html)を参照。
***
　次の関数は、コマンドキューに関する情報を照会するために使用することができます。

```c
cl_int clGetCommandQueueInfo (
    cl_command_queue command_queue,
    cl_command_queue_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetCommandQueueInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetCommandQueueInfo.html)を参照。
***
## 5.2 バッファオブジェクト
　バッファオブジェクトは、要素の1次元コレクションを格納します。バッファオブジェクトの要素は、スカラー型（int、floatなど）、ベクター型、またはユーザー定義構造体です。
### 5.2.1 バッファオブジェクトの作成
***
　バッファオブジェクトは、以下の関数を使用して作成されます

```c
cl_mem clCreateBuffer (
    cl_context context,
    cl_mem_flags flags,
    size_t size,
    void *host_ptr,
    cl_int *errcode_ret
)
```

詳細は[clCreateBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateBuffer.html)を参照。
***
　次の関数は、既存のバッファオブジェクトから新しいバッファオブジェクト（サブバッファオブジェクトと呼ばれる）を作成するために使用できます。

```c
cl_mem clCreateSubBuffer (
    cl_mem buffer,
    cl_mem_flags flags,
    cl_buffer_create_type buffer_create_type,
    const void *buffer_create_info,
    cl_int *errcode_ret
)
```

詳細は[clCreateSubBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateSubBuffer.html)を参照。
***
### 5.2.2 バッファオブジェクトの読み書きとコピー
***
　次の関数は、バッファオブジェクトからホストメモリへの読み出しまたはホストメモリからのバッファオブジェクトへの書き込みコマンドを送信します。

```c
cl_int clEnqueueReadBuffer (
    cl_command_queue command_queue,
    cl_mem buffer,
    cl_bool blocking_read,
    size_t offset,
    size_t size,
    void *ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
cl_int clEnqueueWriteBuffer (
    cl_command_queue command_queue,
    cl_mem buffer,
    cl_bool blocking_write,
    size_t offset,
    size_t size,
    const void *ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueReadBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueReadBuffer.html)、[clEnqueueWriteBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueWriteBuffer.html)を参照。
***
　次の関数は、バッファオブジェクトからホストメモリに2次元または3次元の矩形領域を読み込むコマンド、あるいはホストメモリからバッファオブジェクトに2次元または3次元の矩形領域を書き込むコマンドを送信します。

```c
cl_int clEnqueueReadBufferRect (
    cl_command_queue command_queue,
    cl_mem buffer,
    cl_bool blocking_read,
    const size_t *buffer_origin,
    const size_t *host_origin,
    const size_t *region,
    size_t buffer_row_pitch,
    size_t buffer_slice_pitch,
    size_t host_row_pitch,
    size_t host_slice_pitch,
    void *ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
cl_int clEnqueueWriteBufferRect (
    cl_command_queue command_queue,
    cl_mem buffer,
    cl_bool blocking_write,
    const size_t *buffer_origin,
    const size_t *host_origin,
    const size_t *region,
    size_t buffer_row_pitch,
    size_t buffer_slice_pitch,
    size_t host_row_pitch,
    size_t host_slice_pitch,
    const void *ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueReadBufferRect](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueReadBufferRect.html)、[clEnqueueWriteBufferRect](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueWriteBufferRect.html)を参照。
***
　次の関数は、src_bufferのバッファオブジェクトをdst_bufferのバッファオブジェクトにコピーするコマンドを送信します。

```c
cl_int clEnqueueCopyBuffer (
    cl_command_queue command_queue,
    cl_mem src_buffer,
    cl_mem dst_buffer,
    size_t src_offset,
    size_t dst_offset,
    size_t size,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueCopyBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueCopyBuffer.html)を参照。
***
　次の関数は、src_bufferのバッファオブジェクト内の2次元または3次元の矩形領域から、dst_bufferのバッファオブジェクト内のを2次元または3次元の矩形領域にコピーするコマンドを送信します。コピーはsrc_originとdst_originの説明で後述するように、計算されたソースオフセットとデスティネーションオフセットから始まります。領域の幅方向の各バイトは、ソースオフセットからデスティネーションオフセットにコピーされます。幅方向の各バイトをコピーした後、ソースオフセットとデスティネーションオフセットは、それぞれのソース行ピッチとデスティネーション行ピッチだけインクリメントされます。各2次元矩形領域をコピーした後、ソースオフセットおよびデスティネーションオフセットは、それぞれのソースおよびデスティネーションスライスピッチだけインクリメントされます。

```c
cl_int clEnqueueCopyBufferRect (
    cl_command_queue command_queue,
    cl_mem src_buffer,
    cl_mem dst_buffer,
    const size_t *src_origin,
    const size_t *dst_origin,
    const size_t *region,
    size_t src_row_pitch,
    size_t src_slice_pitch,
    size_t dst_row_pitch,
    size_t dst_slice_pitch,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueCopyBufferRect](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueCopyBufferRect.html)を参照。
***
### 5.2.3 バッファオブジェクトの充填
***
　次の関数は、指定されたパターンサイズのパターンでバッファオブジェクトを塗りつぶすコマンドを送信します。clEnqueueFillBufferは、バッファ作成時に指定されたcl_mem_flags引数の値によって、カーネルやホストからメモリオブジェクトを読み書きできるかどうかを示す使用情報を無視します。

```c
cl_int clEnqueueFillBuffer (
    cl_command_queue command_queue,
    cl_mem buffer,
    const void *pattern,
    size_t pattern_size,
    size_t offset, size_t size,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueFillBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueFillBuffer.html)を参照。
***
### 5.2.4 バッファオブジェクトのマッピング
***
　次の関数は、bufferによって与えられたバッファオブジェクトの領域をホストアドレス空間にマップするコマンドを送信し、このマップされた領域へのポインタを返します。

```c
void * clEnqueueMapBuffer (
    cl_command_queue command_queue,
    cl_mem buffer,
    cl_bool blocking_map,
    cl_map_flags map_flags,
    size_t offset,
    size_t size,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event,
    cl_int *errcode_ret
)
```

詳細は[clEnqueueMapBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueMapBuffer.html)を参照。
***
## イメージオブジェクト
　イメージオブジェクトは、1次元、2次元または3次元のテクスチャ、フレームバッファまたは画像を格納するために使用されます。イメージオブジェクトの要素は、予め定義された画像フォーマットのリストから選択します。
### 5.3.1 イメージオブジェクトの作成
***
　以下の関数を用いて、1次元画像、1次元画像バッファ、1次元画像配列、2次元画像、2次元画像配列、3次元画像オブジェクトを生成することができます。

```c
cl_mem clCreateImage (
    cl_context context,
    cl_mem_flags flags,
    const cl_image_format *image_format,
    const cl_image_desc *image_desc,
    void *host_ptr,
    cl_int *errcode_ret
)
```

詳細は[clCreateImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateImage.html)を参照。
***
#### 5.3.1.1 イメージフォーマット記述子
***
　イメージフォーマット記述子構造体は、以下のように定義されます。

```c
typedef struct _cl_image_format {
          cl_channel_order image_channel_order;
          cl_channel_type  image_channel_data_type;
} cl_image_format;
```

詳細は[cl_image_format](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/cl_image_format.html)を参照。
***
#### 5.3.1.2 イメージ記述子
***
　イメージ記述子構造体は、画像または画像配列のタイプおよび寸法を記述し、以下のように定義されます。

```c
typedef struct _cl_image_desc {
          cl_mem_object_type image_type;
          size_t image_width;
          size_t image_height;
          size_t image_depth;
          size_t image_array_size;
          size_t image_row_pitch;
          size_t image_slice_pitch;
          cl_uint num_mip_levels;
          cl_uint num_samples;
          cl_mem buffer;
} cl_image_desc;
```

詳細は[cl_image_desc](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/cl_image_desc.html)を参照。
***
### 5.3.2 サポートされている画像フォーマットリストの照会
***
　次の関数は、イメージメモリオブジェクトに関する以下の情報が指定されている場合、OpenCL実装でサポートされているイメージ形式のリストを取得するために使用できます。
**コンテキスト**
**画像タイプ**：1次元・2次元・3次元画像、1次元画像バッファ、1次元・2次元画像配列
**イメージオブジェクト割り当て情報**

```c
cl_int clGetSupportedImageFormats (cl_context context, cl_mem_flags flags, cl_mem_object_type image_type, cl_uint num_entries, cl_image_format *image_formats, cl_uint *num_image_formats)
```

詳細は[clGetSupportedImageFormats](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetSupportedImageFormats.html)を参照。
***
#### 5.3.2.1 最低限サポートされている画像フォーマット
　1次元・2次元・3次元画像オブジェクト、1次元および2次元画像配列オブジェクトの場合、イメージをサポートするすべてのデバイス（読み取りと書き込み）でサポートされなければならないイメージフォーマットのリストは以下の通りです。

|image_num_channels|image_channel_order|image_channel_data_type|
|:----------------:|:------------------|:----------------------|
|4|CL_RGBA|CL_UNORM_INT8|
|||CL_UNORM_INT16|
|||CL_SIGNED_INT8|
|||CL_SIGNED_INT16|
|||CL_SIGNED_INT32|
|||CL_UNSIGNED_INT8|
|||CL_UNSIGNED_INT16|
|||CL_UNSIGNED_INT32|
|||CL_HALF_FLOAT|
|||CL_FLOAT|
|4|CL_BGRA|CL_UNORM_INT8|

### 5.3.3 イメージオブジェクトの読み書きとコピー
***
　次の関数は、イメージまたはイメージ配列オブジェクトからホストメモリに読み込むコマンド、またはホストメモリからイメージまたはイメージ配列オブジェクトに書き込むコマンドを送信します。

```c
cl_int clEnqueueReadImage (
    cl_command_queue command_queue,
    cl_mem image,
    cl_bool blocking_read,
    const size_t *origin,
    const size_t *region,
    ize_t row_pitch,
    size_t slice_pitch,
    void *ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
cl_int clEnqueueWriteImage (
    cl_command_queue command_queue,
    cl_mem image,
    cl_bool blocking_write,
    const size_t *origin,
    const size_t *region,
    size_t input_row_pitch,
    size_t input_slice_pitch,
    const void * ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueReadImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueReadImage.html)、[clEnqueueWriteImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueWriteImage.html)を参照。
***
　次の関数は、イメージオブジェクトをコピーするコマンドをエンキューします。

```c
cl_int clEnqueueCopyImage (
    cl_command_queue command_queue,
    cl_mem src_image,
    cl_mem dst_image,
    const size_t *src_origin,
    const size_t *dst_origin,
    const size_t *region,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueCopyImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueCopyImage.html)を参照。
***
### 5.3.4 イメージオブジェクトの充填
***
　次の関数は、イメージオブジェクトを指定された色で塗りつぶすコマンドを送信します。clEnqueueFillImageは、バッファ作成時に指定されたcl_mem_flags引数の値によって、カーネルやホストからメモリオブジェクトを読み書きできるかどうかを示す使用情報を無視します。

```c
cl_int clEnqueueFillImage (
    cl_command_queue command_queue,
    cl_mem image,
    const void *fill_color,
    const size_t *origin,
    const size_t *region,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueFillImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueFillImage.html)を参照。
***
### 5.3.5 イメージオブジェクトとバッファオブジェクト間のコピー
***
　次の関数は、イメージオブジェクトをバッファオブジェクトにコピーするコマンドを送信します。

```c
cl_int clEnqueueCopyImageToBuffer (
    cl_command_queue command_queue,
    cl_mem src_image,
    cl_mem dst_buffer,
    const size_t *src_origin,
    const size_t *region,
    size_t dst_offset,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueCopyImageToBuffer](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueCopyImageToBuffer.html)を参照。
***
　次の関数は、バッファオブジェクトをイメージオブジェクトにコピーするコマンドを送信します。

```c
cl_int clEnqueueCopyBufferToImage (
    cl_command_queue command_queue,
    cl_mem src_buffer,
    cl_mem dst_image,
    size_t src_offset,
    const size_t *dst_origin,
    const size_t *region,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueCopyBufferToImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueCopyBufferToImage.html)を参照。
***
### 5.3.6 イメージオブジェクトのマッピング
***
　次の関数は、imageによって与えられたイメージオブジェクトの領域をホストアドレス空間にマップするコマンドを送信し、このマップされた領域へのポインタを返します。

```c
void * clEnqueueMapImage (
    cl_command_queue command_queue,
    cl_mem image,
    cl_bool blocking_map,
    cl_map_flags map_flags,
    const size_t *origin,
    const size_t *region,
    size_t *image_row_pitch,
    size_t *image_slice_pitch,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event,
    cl_int *errcode_ret
)
```

詳細は[clEnqueueMapImage](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueMapImage.html)を参照。
***
### 5.3.7 イメージオブジェクトの照会
　すべてのメモリオブジェクト（バッファおよびイメージオブジェクト）に共通する情報を取得するには、5.4.5項で説明するclGetMemObjectInfo関数を使用します。
***
clCreateImageで作成されたイメージオブジェクトに固有の情報を取得するには、次の関数を使用します。

```c
cl_int clGetImageInfo (
    cl_mem image,
    cl_image_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetImageInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetImageInfo.html)を参照。
***
## 5.4 メモリオブジェクトの照会・アンマップ・移行・保持および解放
### 5.4.1 メモリオブジェクトの保持と解放
***
　次の関数は、memobjの参照カウントをインクリメントします。

```c
cl_int clRetainMemObject (
    cl_mem memobj
)
```

詳細は[clRetainMemObject](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainMemObject.html)を参照。
***
　次の関数は、memobjの参照カウントをデクリメントします。

```c
cl_int clReleaseMemObject (
    cl_mem memobj
)
```

詳細は[clReleaseMemObject](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseMemObject.html)を参照。
***
　次の関数は、ユーザコールバック関数をメモリオブジェクトに登録します。clSetMemObjectDestructorCallbackを呼び出すたびに、指定されたユーザコールバック関数がmemobjに関連付けられたコールバックスタックに登録されます。登録されたユーザーコールバック関数は、登録された逆の順序で呼び出されます。ユーザーコールバック関数が呼び出され、それからメモリオブジェクトのリソースが解放され、メモリオブジェクトが削除されます。これにより、アプリケーション（およびライブラリ）はmemobjを作成する際に指定したhost_ptrが指すメモリが、再利用もしくは開放できるようになったときに通知を受け取れるようになります。

```c
cl_int clSetMemObjectDestructorCallback (
    cl_mem memobj,
    void (CL_CALLBACK *pfn_notify)(
        cl_mem memobj,
        void *user_data
    ),
    void *user_data
)
```

詳細は[clSetMemObjectDestructorCallback](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clSetMemObjectDestructorCallback.html)を参照。
***
### 5.4.2 マップされたメモリオブジェクトのアンマップ
***
　次の関数は、以前にマップされたメモリオブジェクトの領域をマップ解除するコマンドを送信します。clEnqueueMapBufferまたはclEnqueueMapImageによって返されたポインタを使用した読み書きが完了したとみなされます。

```c
cl_int clEnqueueUnmapMemObject (
    cl_command_queue command_queue,
    cl_mem memobj,
    void *mapped_ptr,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueUnmapMemObject](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueUnmapMemObject.html)を参照。
***
### 5.4.3 メモリオブジェクトのマップされた領域への参照
　このセクションでは、メモリオブジェクトのマップされた領域にアクセスするコマンドの動作について説明します。
　書き込み用にマップされたメモリオブジェクトおよび関連するメモリオブジェクト（この領域と重複するサブバッファオブジェクトまたは1次元イメージバッファオブジェクト）のコンテンツは、この領域がアンマッピングされるまでは未定義です。
　コマンドキュー内の複数のコマンドは、メモリオブジェクトおよび関連するメモリオブジェクト（この領域と重複するサブバッファオブジェクトまたは1次元イメージバッファオブジェクト）の領域を、読み取りのためにマップすることができる。読み取りのためにマップされたメモリオブジェクトの内容は、カーネルおよびデバイス上で実行される他のコマンド（clEnqueueCopyBufferなど）によって読み取ることができます。
　メモリオブジェクトおよび関連するメモリオブジェクト（この領域と重複するサブバッファオブジェクトまたは1次元イメージバッファオブジェクト）の重複する領域を書き込みのためにマップ（およびマップ解除）するのはエラーであり、clEnqueueMapBufferまたはclEnqueueMapImageによってCL_INVALID_OPERATIONエラーが返されます。
　メモリオブジェクトが現在書き込みのためにマップされている場合、アプリケーションはこのメモリオブジェクトおよび関連するメモリオブジェクト（この領域と重複するサブバッファオブジェクトまたは1次元イメージバッファオブジェクト）への読み書きコマンドまたはカーネル実行を送信するより前にメモリオブジェクトがマップ解除されていることを確認する必要があります。それ以外の場合、動作は未定義です。
　メモリオブジェクトが現在読み込みのためにマップされている場合、アプリケーションはこのメモリオブジェクトまたは関連するメモリオブジェクト（この領域と重複するサブバッファオブジェクトまたは1次元イメージバッファオブジェクト）への書き込みコマンドまたはカーネル実行を送信するより前にメモリオブジェクトがマップ解除されていることを確認する必要があります。それ以外の場合、動作は未定義です。
　アンマップされたポインタによってメモリ領域の内容にアクセスすることは定義されていません。上記のルールが守られていれば、clEnqueueMapBufferまたはclEnqueueMapImageによって返されるポインタはclEnqueue{Read|Write}Buffer・clEnqueue{Read|Write}BufferRect・clEnqueue{Read|Write}Imageへのptr引数として使用できます。
### 5.4.4 メモリオブジェクトの移行
　このセクションでは、メモリオブジェクトをデバイスに割り当てる仕組みについて説明します。これは次のように使用されます。

・使用前にオブジェクトが特定のデバイスに割り当てられていることを確認する
・オブジェクトをあるデバイスから別のデバイスに事前に移行する

***
　次の関数は、メモリオブジェクトのセットをどのデバイスに関連付けるべきかを示すコマンドを送信します。通常、メモリオブジェクトはメモリオブジェクトを使用して送信されたコマンドを対象とするデバイスに暗黙的に移行されます。clEnqueueMigrateMemObjectsを使用すると、この移行を依存コマンドより先に明示的に実行できます。これにより、ユーザは今後のコマンドのために、通常のコマンドキュースケジューリングを用いてメモリオブジェクトの関連付けを事前に変更することが可能です。これはまた、潜在的な転送待ち時間が生じるよりも前に、メモリオブジェクトの配置を他の無関係な動作と同時に実行することを可能にします。mem_objectsで指定されたメモリオブジェクトがcommand_queueに関連付けられたデバイスに正常に移行されると、clEnqueueMigrateMemObjectsから返されたイベントがCL_COMPLETEになります。暗黙または明示的に移動させる別のコマンドが送信されるまで、移行されたメモリオブジェクトはデバイス上に常駐したままになります。
　clEnqueueMigrateMemObjectsを使用して、作成後にメモリオブジェクトの初期配置を指示することもできます。これにより、このオブジェクトを最初に使用するときのインスタンス化オーバーヘッドを回避できます。メモリオブジェクトへのアクセスが重複しないように、このコマンドに関連付けられたイベントの依存関係を管理するのはユーザーの責任です。clEnqueueMigrateMemObjectsに渡されたイベントの依存関係が正しく指定されていないと、結果が未定義になる可能性があります。

```c
cl_int clEnqueueMigrateMemObjects (
    cl_command_queue command_queue,
    cl_uint num_mem_objects,
    const cl_mem *mem_objects,
    cl_mem_migration_flags flags,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueMigrateMemObjects](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueMigrateMemObjects.html)を参照。
***
### 5.4.5 メモリオブジェクトの照会
***
　すべてのメモリオブジェクト（バッファおよびイメージオブジェクト）に共通する情報を取得するには、次の関数を使用します。

```c
cl_int clGetMemObjectInfo (
    cl_mem memobj,
    cl_mem_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetMemObjectInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetMemObjectInfo.html)を参照。
***
## 5.5 サンプラオブジェクト
　サンプラオブジェクトは、イメージがカーネル内で読み込まれたときにイメージをサンプリングする方法を記述します。カーネル内のイメージから読み込む組み込み関数はサンプラーを引数として取ります。イメージ読み取り関数へのサンプラー引数は、OpenCL関数を使用して作成され、引数値としてカーネルに渡されるサンプラーオブジェクトでも、カーネル内で宣言されたサンプラーでもかまいません。このセクションでは、OpenCL関数を使用してサンプラーオブジェクトを作成する方法について説明します。
### 5.5.1 サンプラオブジェクトの作成
***
　次の関数は、サンプラオブジェクトを作成します。

```c
cl_sampler clCreateSampler (
    cl_context context,
    cl_bool normalized_coords,
    cl_addressing_mode addressing_mode,
    cl_filter_mode filter_mode,
    cl_int *errcode_ret
)
```

詳細は[clCreateSampler](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateSampler.html)を参照。
***
　次の関数は、sampler参照カウントをインクリメントします。 clCreateSamplerは暗黙の保持を実行します。

```c
cl_int clRetainSampler (
    cl_sampler sampler
)
```

詳細は[clRetainSampler](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainSampler.html)を参照。
***
　次の関数はsampler参照カウントを減少させます。サンプラオブジェクトは、参照カウントがゼロになった後、コマンドキュー内のsamplerを使用するコマンドが終了すると削除されます。

```c
cl_int clReleaseSampler (
    cl_sampler sampler
)
```

詳細は[clReleaseSampler](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseSampler.html)を参照。
***
### 5.5.2 サンプラオブジェクトの照会
***
　次の関数は、サンプラオブジェクトに関する情報を返します。

```c
cl_int clGetSamplerInfo (
    cl_sampler sampler,
    cl_sampler_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetSamplerInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetSamplerInfo.html)を参照。
***
## 5.6 プログラムオブジェクト
　OpenCLプログラムは、プログラムソース内の__kernel修飾子で宣言された一連のカーネルで構成されています。OpenCLプログラムには、補助関数とカーネル関数で使用できる定数データも含まれています。実行可能プログラムは、適切なデバイス用のOpenCLコンパイラによってオンラインまたはオフラインで生成することができます。
　プログラムオブジェクトは、以下の情報をカプセル化します。

・関連するコンテキスト
・プログラムソースまたはバイナリ
・最新のビルド済みの実行可能プログラム、ライブラリまたはコンパイルされたバイナリ、実行可能プログラム・ライブラリ・コンパイル済みバイナリが構築されているデバイスのリスト、使用されているビルドオプション、およびビルドログ
・現在接続されているカーネルオブジェクトの数

### 5.6.1 プログラムオブジェクトの作成
***
　次の関数は、コンテキスト用のプログラムオブジェクトを作成し、strings配列内のテキスト文字列で指定されたソースコードをプログラムオブジェクトにロードします。コンテキストに関連付けられたデバイスがプログラムオブジェクトに関連付けられます。stringsで指定されたソースコードは、オンラインコンパイラをサポートするカスタムデバイス用のOpenCL Cプログラムソース・ヘッダー・実装定義ソースのいずれかです。

```c
cl_program clCreateProgramWithSource (
    cl_context context,
    cl_uint count,
    const char **strings,
    const size_t *lengths,
    cl_int *errcode_ret
)
```

詳細は[clCreateProgramWithSource](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateProgramWithSource.html)を参照。
***
　次の関数は、コンテキスト用のプログラムオブジェクトを作成し、binaryで指定されたバイナリをプログラムオブジェクトにロードします。

```c
cl_program clCreateProgramWithBinary (
    cl_context context,
    cl_uint num_devices,
    const cl_device_id *device_list,
    const size_t *lengths,
    const unsigned char **binaries,
    cl_int *binary_status,
    cl_int *errcode_ret
)
```

詳細は[clCreateProgramWithBinary](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateProgramWithBinary.html)を参照。
***
　次の関数は、コンテキスト用のプログラムオブジェクトを作成し、組み込みカーネルに関連する情報をプログラムオブジェクトにロードします。

```c
cl_program clCreateProgramWithBuiltInKernels (
    cl_context context,
    cl_uint num_devices,
    const cl_device_id *device_list,
    const char *kernel_names,
    cl_int *errcode_ret
)
```

詳細は[clCreateProgramWithBuiltInKernels](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateProgramWithBuiltInKernels.html)を参照。
***
　次の関数は、programの参照カウントをインクリメントします。clCreateProgramは暗黙の保持を行います。

```c
cl_int clRetainProgram (
    cl_program program
)
```

詳細は[clRetainProgram](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainProgram.html)を参照。
***
　次の関数は、programの参照カウントを減少させます。プログラムオブジェクトは、プログラムに関連するすべてのカーネルオブジェクトが削除され、programの参照カウントがゼロになった後に削除されます。

```c
cl_int clReleaseProgram (
    cl_program program
)
```

詳細は[clReleaseProgram](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseProgram.html)を参照。
***
### 5.6.2 実行可能プログラムの作成
***
 次の関数は、プログラムに関連するコンテキスト内のすべてのデバイスまたは特定のデバイスのプログラムソースまたはバイナリから実行可能なプログラムをビルド（コンパイルおよびリンク）します。clBuildProgramは、clCreateProgramWithSourceまたはclCreateProgramWithBinaryのいずれかを使用して作成されたプログラムに対して、プログラムに関連付けられた1つまたは複数のデバイスに対して実行可能なプログラムをビルドするために呼び出さなければなりません。プログラムがclCreateProgramWithBinaryで作成された場合、プログラムバイナリは実行可能なバイナリでなければなりません（コンパイルされたバイナリまたはライブラリではありません）。

```c
cl_int clBuildProgram (
    cl_program program,
    cl_uint num_devices,
    const cl_device_id *device_list,
    const char *options,
    void (CL_CALLBACK *pfn_notify)(
        cl_program program,
        void *user_data
    ),
    void *user_data
)
```

詳細は[clBuildProgram](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clBuildProgram.html)を参照。
***
### 5.6.3 コンパイルとリンクを分離する
　OpenCL 1.2は、プログラムをコンパイルおよびリンクする方法を次のように拡張します。

・分割されたコンパイルとリンクの段階。プログラムソースは、コンパイルされたバイナリオブジェクトを生成するようにコンパイルされ、実行可能プログラムを作るための他のコンパイルされたプログラムオブジェクトとのリンクは別の段階で行われます。
・埋め込みヘッダー。OpenCL 1.0および1.1では、-Iビルドオプションを使用してプログラムソースに含まれるヘッダーファイルを検索するディレクトリのリストを指定できます。OpenCL 1.2では、ヘッダファイルだけでなくプログラムオブジェクトからヘッダソースを取得できるように拡張しています。
・ライブラリ。リンカーを使用して、コンパイルされたオブジェクトとライブラリを実行可能プログラムにリンクしたり、コンパイルされたバイナリのライブラリを作成したりすることができます。

***
　次の関数は、programに関連付けられたコンテキスト内のすべてのデバイスまたは特定のデバイスのプログラムソースをコンパイルします。プリプロセッサは、プログラムソースがコンパイルされる前に実行されます。コンパイルされたバイナリは、programに関連付けられたデバイスまたは指定されたデバイスリストのデバイス用に作成されます。コンパイルされたバイナリは、clGetProgramInfoを使用して照会でき、clCreateProgramWithBinaryに指定して新しいプログラムオブジェクトを作成することができます。

```c
cl_int clCompileProgram (
    cl_program program,
    cl_uint num_devices,
    const cl_device_id *device_list,
    const char *options,
    cl_uint num_input_headers,
    const cl_program *input_headers,
    const char **header_include_names,
    void (CL_CALLBACK *pfn_notify)(
        cl_program program,
        void *user_data
    ),
    void *user_data
)
```

詳細は[clCompileProgram](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCompileProgram.html)を参照。
***
　次の関数は、コンパイルされたプログラムオブジェクトとライブラリを、すべてのデバイスまたはコンテキスト内の特定のデバイスにリンクし、実行可能プログラムを作成します。clLinkProgramはこの実行可能プログラムを含む新しいプログラムオブジェクトを作成します。実行可能なバイナリは、clGetProgramInfoを使用して照会でき、clCreateProgramWithBinaryに指定して新しいプログラムオブジェクトを作成することができます。

```c
cl_program clLinkProgram (
    cl_context context,
    cl_uint num_devices,
    const cl_device_id *device_list,
    const char *options,
    cl_uint num_input_programs,
    const cl_program *input_programs,
    void (CL_CALLBACK *pfn_notify)(
        cl_program program,
        void *user_data
    ),
    void *user_data,
    cl_int *errcode_ret
)
```

詳細は[clCompileProgram](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCompileProgram.html)を参照。
***
### 5.6.4 コンパイラオプション
　コンパイラオプションはプリプロセッサオプション、組み込み算術関数のオプション、最適化オプションおよびその他のオプションに分類されます。この仕様では実行可能プログラムをオンラインまたはオフラインでビルドするときに、コンパイラが最低限サポートする必要があるオプションを定義しています。これらは、一連のベンダー固有またはプラットフォーム固有のオプションによって拡張される場合があります。
#### 5.6.4.1 プリプロセッサオプション
　これらのオプションは、実際のコンパイルの前に各プログラムソースで実行されるプリプロセッサを制御します。-Dオプションは、clBuildProgramまたはclCompileProgramのoptions引数で指定された順番で処理されます。

-D *name*
　nameをマクロとして定義します。値は自動的に1になります。

-D *name=definition*
　definitionの内容は#defineディレクティブで定義されたかのように処理されます。 ただし、定義は改行文字によって区切られます。

-I *dir*
　ヘッダファイルを検索するディレクトリにdirを追加します。

#### 5.6.4.2 組み込み算術関数のオプション
　これらのオプションは浮動小数点演算に関するコンパイラの動作を制御します。これらのオプションは、速度と正確さとの間でトレードオフになります。

-cl-single-precision-constant
　倍精度浮動小数点定数を単精度定数として扱います。

-cl-denorms-are-zero
　このオプションは単精度および倍精度の非正規化数の処理方法を制御します。ビルドオプションとして指定された場合、単精度の非正規化数は0に置き換えられます。拡張として倍精度オプションがサポートされている場合、倍精度の非正規化数もゼロに置き換えられます。これはパフォーマンス向上を意図しており、デバイスが単精度（または倍精度）非正規化数をサポートしている場合、コンパイラは非正規化数をゼロに置き換えないことを選択できます。
　デバイスが単精度の非正規化数をサポートしていない場合（CL_FP_DENORMビットがCL_DEVICE_SINGLE_FP_CONFIGに設定されていない場合）このオプションは単精度で無視されます。デバイスが倍精度の非正規化数をサポートしていない場合（CL_FP_DENORMビットがCL_DEVICE_DOUBLE_FP_CONFIGに設定されていない場合）または倍精度浮動小数点数をサポートしていない場合、このオプションは倍精度で無視されます。
このフラグは、スカラ変数とベクトル単精度浮動小数点変数およびこれらの計算にのみ適用されます。イメージオブジェクトの読み書きには適用されません。

-cl-fp32-correctly-rounded-divide-sqrt
　clBuildProgramまたはclCompileProgramにこのオプションを使用すると、プログラムで使用される単精度浮動小数点除算（x/yおよび1/x）およびsqrtが正しく丸められるように指定できます。このビルドオプションを指定しない場合、単精度浮動小数点除算とsqrtの最小数値精度は、OpenCL仕様の7.4節で定義されているとおりです。
　このオプションは、CL_DEVICE_SINGLE_FP_CONFIGにCL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRTが設定されている場合にのみ指定できます。 このオプションが指定されていて、デバイスに対してCL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRTが設定されていない場合、clBuildProgramまたはclCompileProgramはデバイスのプログラムをコンパイルできません。

####5.6.4.3 最適化オプション
　これらのオプションは最適化を制御します。最適化フラグをオンにすると、コンパイル時間を犠牲にしてパフォーマンスおよびコードサイズを縮小させ、場合によってはプログラムをデバッグすることができます。

-cl-opt-disable
　このオプションは、すべての最適化を無効にします。デフォルトでは最適化が有効になっています。

　次のオプションは、浮動小数点演算に関するコンパイラの動作を制御します。これらのオプションは、パフォーマンスと正確さの間でトレードオフであり、明確に有効にする必要があります。これらのオプションは、数学関数のIEEE 754のルールおよび仕様を正確に実装したプログラムの出力がされない可能性があるため、デフォルトではオンになっていません。

-cl-mad-enable
　A * B + Cをmadに置き換えることができます。このmadは精度の低いA * B + Cを計算します。たとえば、一部のデバイスはA * Bの結果をCと加算する前に、その結果を切り捨てる実装をします。

-cl-no-signed-zeros
　符号付きのゼロを無視する浮動小数点演算の最適化を許可します。IEEE 754は+0.0と-0.0で異なる動作を指定するため、x + 0.0や0.0 * xなどの式の簡略化が禁止されます（-clfinite-mathの場合のみ）。このオプションはゼロ結果の符号が重要でないことを意味します。

-cl-unsafe-math-optimizations
　（a）引数と結果が有効であると仮定し、（b）IEEE 754規格に違反し、（c）7.5節の特殊ケースの動作、単精度浮動小数点と倍精度浮動小数点について7.4節で定義されたOpenCL数値準拠要件に違反する可能性がある、浮動小数点演算の最適化を許可します。このオプションには-cl-no-signed-zerosオプションと-cl-mad-enableオプションが含まれます。

-cl-finite-math-only
　引数と結果がNaNまたは±∞でないと仮定した浮動小数点演算の最適化を許可します。このオプションは、単精度および倍精度浮動小数点について7.4節で定義されたOpenCL数値準拠要件、および7.5節の特殊ケースの動作に違反する可能性があります。

-cl-fast-relaxed-math
　最適化オプション-cl-finite-math-onlyおよび-cl-unsafe-math-optimizationsを設定します。これにより、IEEE 754標準と、単精度と倍精度の浮動小数点について7.4節で定義されたOpenCL数値準拠要件、および7.5節での特殊ケースの動作に違反する可能性のある浮動小数点演算の最適化が可能になります。このオプションを使用すると、プリプロセッサマクロ__FAST_RELAXED_MATH__がOpenCLプログラムで定義されます。

#### 5.6.4.4 警告を要求または抑制するオプション
 警告は、本質的に誤ってはいないが危険であるか、またはエラーがあった可能性があることを示唆する診断メッセージです。次のオプションは、特定の警告を有効にするのではなく、コンパイラによって生成される診断の種類を制御します。

-w
　すべての警告メッセージを禁止します。

-Werror
　すべての警告をエラーにします。

#### 5.6.4.5 OpenCL Cバージョンの制御オプション
　次のオプションは、コンパイラが受け入れるOpenCL Cのバージョンを制御します。

-cl-std
使用するOpenCL C言語バージョンを決定します。このオプションの有効な値は次のとおりです。
-cl-std=CL1.1
OpenCL 1.1仕様書の6章で定義されたOpenCL C言語機能を使用するすべてのOpenCL Cプログラムをサポートします。
-cl-std=CL1.2
OpenCL 1.2仕様書の6章で定義されたOpenCL C言語機能を使用するすべてのOpenCL Cプログラムをサポートします。

　clBuildProgramまたはclCompileProgramを-cl-std=CL1.1オプションを指定して呼び出すと、CL_DEVICE_OPENCL_C_VERSION=OpenCL C 1.0のデバイスでプログラムをコンパイルできなくなります。
　clBuildProgramまたはclCompileProgramを-cl-std=CL1.2オプションを指定して呼び出すと、CL_DEVICE_OPENCL_C_VERSION=OpenCL C 1.0またはOpenCL C 1.1のデバイスでプログラムをコンパイルできなくなります。

　-cl-std buildオプションが指定されていない場合、各デバイスのプログラムをコンパイルするときに使用するOpenCL CのバージョンはCL_DEVICE_OPENCL_C_VERSIONの値になります。
#### 5.6.4.6 カーネル引数情報を照会するためのオプション

-cl-kernel-arg-info
　このオプションを使用すると、コンパイラは実行可能プログラムにカーネルの引数に関する情報を格納します。格納される引数情報には、引数名、型、使用されるアドレスとアクセス修飾子が含まれます。この情報を照会する方法については、clGetKernelArgInfoの説明を参照してください。

### 5.6.5 リンカーオプション
　この仕様ではコンパイルされたプログラムをオンラインまたはオフラインでリンクするときに、OpenCL Cコンパイラが最低限サポートする必要があるリンカオプションを定義しています。これらのリンカーオプションは、ライブラリリンクオプションとプログラムリンクオプションに分類されます。これらは、一連のベンダー固有またはプラットフォーム固有の拡張がされる可能性があります。
#### 5.6.5.1 ライブラリリンクオプション
　コンパイルされたバイナリのライブラリを作成するときは、次のオプションを指定できます。

-create-library
　clLinkProgramのinput_programs引数で指定されたコンパイル済みバイナリのライブラリを作成します。

-enable-link-options
　このライブラリが実行可能プログラムにリンクされている場合、リンカーは1つ以上のリンクオプション（5.6.5.2項を参照）に基づいてライブラリの動作を変更できます。このオプションは-create-libraryオプションと同時に指定する必要があります。

#### 5.6.5.2 プログラムリンクオプション
　プログラムの実行ファイルをリンクするときは、次のオプションを指定できます。これらのオプションについては、5.6.4.2項と5.6.4.3項で説明しています。リンカーは、clLinkProgramに指定されたコンパイル済みのすべてのプログラムオブジェクトにこれらのオプションを適用できます。リンカは、これらのオプションを-enable-link-optionで作成したライブラリにのみ適用できます。

-cl-denorms-are-zero
-cl-no-signed-zeroes
-cl-unsafe-math-optimizations
-cl-finite-math-only
-cl-fast-relaxed-math

### 5.6.6 OpenCLコンパイラのアンロード
***
　次の関数は、platformのOpenCLコンパイラによって割り当てられたリソースを解放することを可能にします。これはアンロード可能であることを通知するものであり、将来コンパイラが使用されないことや、コンパイラが実装によって実際にアンロードされることを保証するものではありません。clUnloadPlatformCompilerの後にclBuildProgram、clCompileProgramまたはclLinkProgramを呼び出すと、必要に応じてコンパイラがリロードされ、適切な実行可能プログラムが構築されます。

```c
cl_int clUnloadPlatformCompiler (
    cl_platform_id platform
)
```

詳細は[clUnloadPlatformCompiler](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clUnloadPlatformCompiler.html)を参照。
***
### 5.6.7 プログラムオブジェクトの照会
***
　次の関数は、プログラムオブジェクトに関する情報を返します。

```c
cl_int clGetProgramInfo (
    cl_program program,
    cl_program_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetProgramInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetProgramInfo.html)を参照。
***
　次の関数は、プログラムオブジェクト内の各デバイスのビルド情報を返します。

```c
cl_int clGetProgramBuildInfo (
    cl_program program,
    cl_device_id device,
    cl_program_build_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetProgramBuildInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetProgramBuildInfo.html)を参照。
***
## 5.7 カーネルオブジェクト
 カーネルはプログラムで宣言された関数です。カーネルはプログラム内の関数に適用される__kernel修飾子によって識別されます。カーネルオブジェクトは、プログラムで宣言された特定のカーネル関数と、このカーネル関数の実行時に使用される引数値をカプセル化します。
### 5.7.1 カーネルオブジェクトの作成
***
カーネルオブジェクトを作成するには、関数を使用します。

```c
cl_kernel clCreateKernel (
    cl_program program,
    const char *kernel_name,
    cl_int *errcode_ret
)
```

詳細は[clCreateKernel](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateKernel.html)を参照。
***
　次の関数は、プログラム内のすべてのカーネル関数のカーネルオブジェクトを作成します。カーネルオブジェクトは、実行可能プログラムが正常に構築されたすべてのデバイス間で同じ関数定義を持たないカーネル関数に対しては作成されません。

```c
cl_int clCreateKernelsInProgram (
    cl_program program,
    cl_uint num_kernels,
    cl_kernel *kernels,
    cl_uint *num_kernels_ret
)
```

詳細は[clCreateKernelsInProgram](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateKernelsInProgram.html)を参照。
***
　次の関数は、kernelの参照カウントをインクリメントします。

```c
cl_int clRetainKernel (
    cl_kernel kernel
)
```

詳細は[clRetainKernel](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainKernel.html)を参照。
***
　次の関数は、kernelの参照カウントをデクリメントします。

```c
cl_int clReleaseKernel (
    cl_kernel kernel
)
```

詳細は[clReleaseKernel](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseKernel.html)を参照。
***
### 5.7.2 カーネル引数の設定
　カーネルを実行するには、カーネル引数を設定する必要があります。
***
　次の関数は、特定の引数に引数値を設定するために使用されます。

```c
cl_int clSetKernelArg (
    cl_kernel kernel,
    cl_uint arg_index,
    size_t arg_size,
    const void *arg_value
)
```

詳細は[clSetKernelArg](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clSetKernelArg.html)を参照。
***
### 5.7.3 カーネルオブジェクトの照会
***
　この関数は、カーネルオブジェクトに関する情報を返します。

```c
cl_int clGetKernelInfo (
    cl_kernel kernel,
    cl_kernel_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetKernelInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetKernelInfo.html)を参照。
***
　次の関数は、デバイスに固有のカーネルオブジェクトに関する情報を返します。

```c
cl_int clGetKernelWorkGroupInfo (
    cl_kernel kernel,
    cl_device_id device,
    cl_kernel_work_group_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetKernelWorkGroupInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetKernelWorkGroupInfo.html)を参照。
***
　次の関数は、カーネルの引数に関する情報を返します。カーネル引数情報は、kernelに関連付けられたプログラムオブジェクトがclCreateProgramWithSourceで作成され、実行可能プログラムがclBuildProgramまたはclCompileProgramのoptions引数で-cl-kernel-arg-infoオプションを指定して構築されている場合にのみ使用できます。

```c
cl_int clGetKernelArgInfo (
    cl_kernel kernel,
    cl_uint arg_indx,
    cl_kernel_arg_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetKernelArgInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetKernelArgInfo.html)を参照。
***
## 5.8 カーネルの実行
***
　次の関数は、デバイス上のカーネルを実行するコマンドを送信します。

```c
cl_int clEnqueueNDRangeKernel (
    cl_command_queue command_queue,
    cl_kernel kernel,
    cl_uint work_dim,
    const size_t *global_work_offset,
    const size_t *global_work_size,
    const size_t *local_work_size,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueNDRangeKernel](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueNDRangeKernel.html)を参照。
***
　次の関数は、デバイス上のカーネルを実行するコマンドを送信します。 カーネルは、単一のワークアイテムを使用して実行されます。

```c
cl_int clEnqueueTask (
    cl_command_queue command_queue,
    cl_kernel kernel,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueTask](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueTask.html)を参照。
***
　次の関数は、OpenCLコンパイラを使用してコンパイルされていないネイティブC/C++関数を実行するコマンドを送信します。

```c
cl_int clEnqueueNativeKernel (
    cl_command_queue command_queue,
    void (CL_CALLBACK *user_func)(void *) void *args,
    size_t cb_args,
    cl_uint num_mem_objects,
    const cl_mem *mem_list,
    const void **args_mem_loc,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueNativeKernel](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueNativeKernel.html)を参照。
***
## 5.9 イベントオブジェクト
　イベントオブジェクトは、カーネルの実行コマンド、メモリまたはユーザーイベントの読み取り、書き込み、マップ、およびコピーのコマンドを参照するために使用できます。イベントオブジェクトを使用して、コマンドの実行ステータスを追跡できます。コマンドキューにコマンドを送信するAPI呼び出しは、イベント引数で返される新しいイベントオブジェクトを作成します。コマンドキュー内でコマンドを送信する際にエラーが発生した場合、イベント引数はイベントオブジェクトを返しません。
　送信されたコマンドのある時点における実行ステータスは、次のいずれかになります。

**CL_QUEUED**：コマンドがコマンドキューに送信されたことを示します。これは、ユーザーイベント以外のすべてのイベントの初期状態です。
**CL_SUBMITTED**：すべてのユーザーイベントの初期状態です。それ以外のイベントの場合は、ホストからデバイスにコマンドが送信されたことを示します。
**CL_RUNNING**：デバイスがこのコマンドの実行を開始したことを示します。送信されたコマンドの実行ステータスをCL_SUBMITTEDからCL_RUNNINGに変更するには、このコマンドが待機しているすべてのイベントが正常に完了（実行ステータスがCL_COMPLETE）している必要があります。
**CL_COMPLETE**：コマンドが正常に完了したことを示します。
**Error code**：エラーコードは負の整数値であり、コマンドが異常終了したことを示します。異常な終了は、メモリアクセス違反などのさまざまな理由で発生する可能性があります。

　コマンドの実行が終了した場合、この終了したコマンドに関連するコマンドキューおよびコンテキスト（さらにはこのコンテキストの他のすべてのコマンドキュー）は使用できない可能性があります。このコンテキスト（およびこのコンテキストに関連付けられたコマンドキュー）を使用するOpenCL API呼び出しの動作は、現在は実装定義です。コンテキストを作成したときに指定したユーザー定義のコールバック関数を使用して、適切なエラー情報を収集できます。
***
　次の関数は、ユーザーイベントオブジェクトを作成します。 ユーザーイベントによりアプリケーションは、デバイスが実行を開始する前にユーザーイベントの終了を待つコマンドを送信できるようになります。

```c
cl_event clCreateUserEvent (
    cl_context context, cl_int *errcode_ret
)
```

詳細は[clCreateUserEvent](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clCreateUserEvent.html)を参照。
***
　次の関数は、ユーザイベントオブジェクトの実行ステータスを設定します。

```c
cl_int clSetUserEventStatus (
    cl_event event,
    cl_int execution_status
)
```

詳細は[clSetUserEventStatus](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clSetUserEventStatus.html)を参照。
***
　次の関数は、event_list内のイベントオブジェクトと関連するコマンドが完了するまでホストスレッド上で待機します。コマンドの実行ステータスがCL_COMPLETEまたは負の値である場合、コマンドは完了したとみなされます。event_listで指定されたイベントは、同期ポイントとして機能します。

```c
cl_int clWaitForEvents (
    cl_uint num_events,
    const cl_event *event_list
)
```

詳細は[clWaitForEvents](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clWaitForEvents.html)を参照。
***
　次の関数は、イベントオブジェクトに関する情報を返します。

```c
cl_int clGetEventInfo (
    cl_event event,
    cl_event_info param_name,
    size_t param_value_size,
    void *param_value,
    size_t *param_value_size_ret
)
```

詳細は[clGetEventInfo](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clGetEventInfo.html)を参照。
***
　次の関数は、特定のコマンド実行ステータスにユーザーコールバック関数を登録します。登録されたコールバック関数は、イベントに関連づけられたコマンドの実行状態がcommand_exec_statusで指定された状態以上の実行状態に変化したときに呼び出されます。

```c
cl_int clSetEventCallback (
    cl_event event,
    cl_int command_exec_callback_type,
    void (CL_CALLBACK *pfn_event_notify)(
        cl_event event,
        cl_int event_command_exec_status,
        void *user_data
    ),
    void *user_data
)
```

詳細は[clSetEventCallback](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clSetEventCallback.html)を参照。
***
　次の関数は、イベント参照カウントをインクリメントします。イベントを返すOpenCLコマンドは、暗黙の保持を実行します。

```c
cl_int clRetainEvent (
    cl_event event
)
```

詳細は[clRetainEvent](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clRetainEvent.html)を参照。
***
　イベントを解放するには、次の関数を使用してイベント参照カウントを減らします。

```c
cl_int clReleaseEvent (
    cl_event event
)
```

詳細は[clReleaseEvent](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clReleaseEvent.html)を参照。
***
## 5.10 マーカー、バリアとイベント待機
***
　次の関数は、イベントリストのすべてのイベントが完了するのを待機するマーカーコマンドを送信します。リストが空の場合、command_queueに以前に送信されたすべてのコマンドが完了するまで待機します。このコマンドが返すeventは、event_wait_listまたは以前に送信されたすべてのイベントが完了したことを保証するために使用できます。

```c
cl_int clEnqueueMarkerWithWaitList (
    cl_command_queue command_queue,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueMarkerWithWaitList](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueMarkerWithWaitList.html)を参照。
***
　次の関数は、イベントリストのすべてのイベントが完了するのを待機するバリアコマンドを送信します。リストが空の場合、command_queueに以前に送信されたすべてのコマンドが完了するまで待機します。このコマンドはコマンドの実行をブロックします。つまり、これより後に送信されるすべてのコマンドはこのバリアコマンドが完了するまで実行されません。このコマンドが返すeventは、event_wait_listまたは以前にエンキューされたすべてのコマンドが前に送信されたことを確実にします。

```c
cl_int clEnqueueBarrierWithWaitList (
    cl_command_queue command_queue,
    cl_uint num_events_in_wait_list,
    const cl_event *event_wait_list,
    cl_event *event
)
```

詳細は[clEnqueueBarrierWithWaitList](https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/clEnqueueBarrierWithWaitList.html)を参照。
***
## 5.11 カーネルおよびメモリ操作の非順次実行
　コマンドキューに送信されたOpenCL関数は、順次実行または非順次実行で実行するように設定できます。clCreateCommandQueueのproperties引数を使用すると、実行順序を指定できます。コマンドキューのCL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLEプロパティが設定されていない場合、コマンドキューに送信されたコマンドは順番に実行されます。たとえば、アプリケーションがclEnqueueNDRangeKernelを呼び出してカーネルAを実行し、続いてclEnqueueNDRangeKernelを実行してカーネルBを実行すると、アプリケーションはカーネルAが最初に終了し、その後にカーネルBが実行されたと見なすことができます。カーネルAが出力するメモリオブジェクトがカーネルBへの入力である場合、カーネルBはカーネルAの実行によって生成されたメモリオブジェクトの正しいデータを表示します。コマンドキューのCL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLEプロパティが設定されている場合、カーネルBが実行を開始する前にカーネルAが終了するという保証はありません。

　アプリケーションは、コマンドキューのCL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLEプロパティを設定することによって、非順次実行をするようにコマンドキューに送信されたコマンドを構成できます。これは、コマンドキューが作成されたときに指定できます。非順次実行モードでは、エンキューされたコマンドがキューに入れられた順に実行を終了するという保証はありません。カーネルの特定の実行順序を保証するために、特定のイベント（この場合はイベントA）の待機を使用できます。 カーネルBのclEnqueueNDRangeKernelのevent_wait_list引数に、イベントAの待機を指定できます。

　さらに、イベント待ち（clEnqueueMarkerWithWaitList）またはバリア（clEnqueueBarrierWithWaitList）コマンドをコマンドキューにエンキューできます。イベント待機コマンドは、イベントリストのすべてのコマンドが終了するのを待機することで、次のコマンドのバッチが実行される前にすべてのコマンドが確実に終了するようにします。バリアコマンドは、コマンドキュー内のすべての以前に送信されたコマンドが、次のコマンドのバッチが実行される前に実行が終了することを保証します。
　同様に、clEnqueueNDRangeKernel、clEnqueueTaskまたはclEnqueueNativeKernelコマンドの後にエンキューされたメモリオブジェクトの読み込み、書き込み、コピーまたはマップコマンドは、CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLEプロパティが設定されている場合、以前に送信されたカーネルが完了するのを待つことはできません。コマンドの正しい順序付けを保証するために、clEnqueueNDRangeKernel、clEnqueueTaskまたはclEnqueueNativeKernelによって返されたイベントオブジェクトを使用して、メモリオブジェクトへの読み取りまたは書き込みが完了するまで待機する必要があります。

## 5.12
p.192　執筆中(2018/03/14)