KelpNetをOpenCL・GPUで動かす

今回は、KelpNetをOpenCLGPUで動かす方法を紹介します。OpenCLは、CPU・GPUFPGAなどで並列処理を行うためのAPIです。KelpNetはCUDAではなくOpenCLを用いるため、GPUを用いる場合でも環境構築がとても簡単に出来ます。また、Nvidia製のGPUだけでなく、AMD製のRadeon系のGPUなどにも対応しています。

この記事でははじめにOpenCLの導入について説明し、次にコードをGPUに対応させる方法について説明します。

OpenCLの導入

OpenCLは、MacNvidia製のGPUの最新のドライバなどはデフォルトでサポートされているため、特に導入の作業が増えることはありません。GPUのドライバを長い間アップデートしていないなという方は、こちらからデバイスにあったバージョンをダウンロード出来ます。また、AMD製のCPU・GPUこちらからダウンロードできます。

以下では、少し手順が必要なIntel製のCPUを用いる場合のOpenCLのドライバのインストール方法について説明します。はじめに、こちらのサイトを開きます。次に、右側のメニューからWindowsもしくはLinuxの内自分のOSに合ったものを選択し、FREE Downloadをクリックしてください。

f:id:jinbeizame007:20180822142015p:plain

すると次のようなページに飛びますので、チェックボックスにチェックを入れ、氏名などの情報を入力し、Submitをクリックしてください。

f:id:jinbeizame007:20180822142549p:plain

Submitをクリックすると、製品名・ライセンスタイプ・シリアル番号などの情報をIntel側に送信してもよいかどうかを尋ねられるので、チェックボックスにチェックを入れます。

f:id:jinbeizame007:20180822143318p:plain

チェックボックスにチェックを入れると、以下のようなダウンロード用のリンクが出現しますので、こちらをクリックしてOpenCLインストーラーをダウンロードします。

f:id:jinbeizame007:20180822143452p:plain

ダウンロードが終わったら、インストーラーを起動してください(注:インストールはVisual Studioを閉じてから行ってください)インストーラーの起動後は基本的にNext連打 & Installで大丈夫です。最後に再起動(Reboot)するかどうかを聞かれますので、再起動してOpenCLのインストールは終了です。

また、以下のようにWeaverを初期化することで、KelpNetをOpenCLで動かすことが可能になります。Weaverとは、CPU・GPU関連の処理を担うマネージャーのようなものです。CPUが2台以上ある場合は、CPUのインデックスを指定することが出来ます。

// Weaverを初期化
Weaver.Initialize(ComputeDeviceTypes.Cpu);
// CPUが2台以上ある場合はインデックスを指定
// Weaver.Initialize(ComputeDeviceTypes.Cpu, 0);

KelpNetのコードをGPUに対応させる

GPUを用いる場合は、まずWeaverのDeviceTypeにGPUを指定して初期化します。CPUの際と同様に、GPUが2台以上ある場合は、GPUのインデックスを指定することができます。次に、ネットワークを定義する際に全結合層(Linear)や畳み込み層(Convolution2D)のGPUフラグ(gpuEnable)をtrueにします。これだけでKelpNetをGPUで動かすことが出来ます。


(2018/09/01 追記

CPU & GPUなど、複数のプラットフォームにOpenCLをインストールしている場合、Weaverを初期化する際に使用したいplatformIdを指定する必要があります。どのプラットフォームにどのIDが割り当てられているかは、以下のコードによって確認することが出来ます。ここで、ClooとKelpNetは同じ名前のクラスを持つため、コンフリクト(衝突)が発生する可能性があります。そのため、using Cloo;は学習を行う際にはコメントアウトしてください。

// ComputePlatformを呼び出すために、Clooを用意
using Cloo;

// Main関数で以下のfor文を実行
for (int i = 0; i < ComputePlatform.Platforms.Count; i++)
    Console.WriteLine("platformId: " + i + " " + ComputePlatform.Platforms[i].Name);

すると、出力が以下のようになります。この際は、CPUを用いる場合はplatformIdに0を、GPUを用いる場合はplatformIdに1を指定してください。

platformId 0 Intel (R) OpenCL
platformId 1 NVIDIA CUDA

// Weaverを初期化 platformIdは上記の方法で確認し, 指定する
Weaver.Initialize(ComputeDeviceTypes.Gpu, platformId: 1);
// デバイスが2台以上ある場合はインデックスを指定可能
// Weaver.Initialize(ComputeDeviceTypes.Gpu, platformId: 1, deviceIndex: 1);

// CPU
FunctionStack model = new FunctionStack(
    new Convolution2D(3, 32, 5, pad: 2, name: "l1 Conv2D"),
    new BatchNormalization(32, name: "l1 BatchNorm"),
    new ReLU(name: "l1 ReLU"),
    new Linear(5 * 5 * 64, 256, name: "l2 Linear"),
    new BatchNormalization(256, name: "l2 BatchNorm"),
    new ReLU(name: "l2 ReLU"),
    new Linear(256, 3, name: "l3 Linear"),
    new Softmax(name: "l3 Softmax")
);

// GPU
FunctionStack model = new FunctionStack(
    new Convolution2D(3, 32, 5, pad: 2, name: "l1 Conv2D", gpuEnable: true),
    new BatchNormalization(32, name: "l1 BatchNorm"),
    new ReLU(name: "l1 ReLU"),
    new Linear(5 * 5 * 64, 256, name: "l2 Linear", gpuEnable: true),
    new BatchNormalization(256, name: "l2 BatchNorm"),
    new ReLU(name: "l2 ReLU"),
    new Linear(256, 3, name: "l3 Linear", gpuEnable: true),
    new Softmax(name: "l3 Softmax")
);