macでOpenCLのC++バインディングを使う

某社の社内大学の体験をする機会があったのだが、そこで OpenCL のライブコーディングを見た。
概要は理解できたと思うが、さすがにソースの内容をすべて記憶してくることはできなかったので、とりあえず自分でも試してみることにする。

で、普段使いしているのが Mac なので、Mac で OpenCL のプログラミングができる環境を整えることにする。
と言っても、Xcode が入っていればすでに OpenCL は入っているので、C から使うだけであればそのまま書けば良いらしい。
(Apple は macOS Mojave 10.14 で OpenCL を deprecated にすると言う発表をしているらしく、いつまで使えるかわからないが)

ライブコーディングでは Modern C++ でコードを書いていたので、せっかくならば C++ で試したい。
調べてみると、[C++ から OpenCL を使う（その0）：準備 | 雑記帳](https://blog.miz-ar.info/2017/05/opencl-with-cxx-0/)と言うサイトを発見した。
ここに従って、[KhronosGroup/OpenCL-CLHPP: Khronos OpenCL-CLHPP](https://github.com/KhronosGroup/OpenCL-CLHPP)のソースをビルドすると、cl.hpp と cl2.hpp が得られる。
できたものは、そのまま/usr/local/includeにコピーする。(homebrew環境だと、/usr/local/はユーザ権限で書き込める。最近は事情が違ったりするんだっけ？)
homebrew環境の場合、homebrewからcmakeをインストールしておく。

```shell
% git clone https://github.com/KhronosGroup/OpenCL-CLHPP.git
% cd OpenCL-CLHPP/
% mkdir build
% cd build
% cmake -DBUILD_EXAMPLES=0 -DBUILD_TESTS=0 ..
% make
% cd include
% cp -R CL /usr/local/include/
```

最初、cl.hpp が OpenCL 1.X 用で、 cl2.hpp が OpenCL 2.X 用だと勘違いしていたので、cl.hpp を使おうと思って奮闘していたのだが、cl2.hpp を良く読むと cl2.hpp を使っても OpenCL 1.2 が使えるようだ。(Mac に入っているのは OpenCL 1.2)
ちなみに、 cl.hpp を使うと以下の警告が出る。

```shell
% c++ -std=c++17 -framework OpenCL     opencl.cc   -o opencl
In file included from opencl.cc:3:
/usr/local/include/CL/cl.hpp:155:9: warning: This version of the OpenCL Host API
      C++ bindings is deprecated, please use cl2.hpp instead.
      [-W#pragma-messages]
#pragma message("This version of the OpenCL Host API C++ bindings is dep...
        ^
```

cl2.hpp を OpenCL 1.2 で使う場合、CL_HPP_TARGET_OPENCL_VERSION と CL_HPP_MINIMUM_OPENCL_VERSION の二つを定義する必要がある。最初、CL_HPP_TARGET_OPENCL_VERSION だけを定義していたら以下のエラーになった。

```shell
% c++ -std=c++17 -framework OpenCL     opencl.cc   -o opencl
In file included from opencl.cc:7:
/usr/local/include/CL/cl2.hpp:478:3: error: "CL_HPP_MINIMUM_OPENCL_VERSION must
      not be greater than CL_HPP_TARGET_OPENCL_VERSION"
# error "CL_HPP_MINIMUM_OPENCL_VERSION must not be greater than CL_HPP_T...
  ^
```

また、他にも以下のような警告が出るので、メッセージに従って CL_SILENCE_DEPRECATION を定義することにした。

```shell
/usr/local/include/CL/cl.hpp:1667:16: warning: 'clRetainDevice' is deprecated:
      first deprecated in macOS 10.14 - (Define CL_SILENCE_DEPRECATION to hide
      this warning) [-Wdeprecated-declarations]
    { return ::clRetainDevice(device); }
               ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/OpenCL.framework/Headers/cl.h:605:1: note:
      'clRetainDevice' has been explicitly marked deprecated here
clRetainDevice(cl_device_id /* device */) CL_API_SUFFIX__VERSION_1_2 CL_...
```

最終的に、ソースの cl2.hpp を include する部分は以下のようになった。

```c++:opencl.cc
#define CL_HPP_ENABLE_EXCEPTIONS          // エラー時に例外を発生させる
#define CL_SILENCE_DEPRECATION            // 非推奨の警告を抑制する
#define CL_HPP_MINIMUM_OPENCL_VERSION 120 // 最小: OpenCL 1.2
#define CL_HPP_TARGET_OPENCL_VERSION 120  // ターゲット: OpenCL 1.2
#include <CL/cl2.hpp>
```

コンパイルのコマンドラインは、上にも出てるけど、-framework OpenCL をつけて以下のような感じ。

```shell
% c++ -std=c++17 -framework OpenCL     opencl.cc   -o opencl
```

これで、platform と device を表示させてみると、MacBook Pro (Retina, 15-inch, Late 2013)だと、CL_PLATFORM_NAME が Apple、device は3つで、CL_DEVICE_TYPE/CL_DEVICE_NAME はそれぞれ
CPU/Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz, GPU/Iris Pro, GPU/GeForce GT 750M となった。

ここまでで一応ソースを書いて実行できそうなところまで来たけど、環境設定編ってことでいったん終わりにする。