NVIDIAが提供するCUDAは、NVIDIA製のGPUを用いて高速な並列処理を行うためのプラットフォームであり、ツールキットです。ここ数年話題になっている深層学習でも基本的な技術の一つとして採用されています。今回はこのCUDAの最新版である8.0をUbuntu 16.04 LTSにインストールする方法を紹介しましょう。
CUDAを使うために必要なハードウェア
グラフィック処理の心臓部であるGPU(Graphics Processing Unit)は、その用途からシェーダーの汎用化・並列化が進んだ結果、特定の精度の単純な計算処理であればCPUの数倍の能力を持つまでに至りました。これは3Dゲームを主体としたCGのレンダリングに使われるべく進化したのですが、せっかくの計算能力をゲームだけに使うのはもったいないとして生まれたのが「GPGPU(General-Purpose computing on Graphics Pocessing Units)」という考え方です。ただしグラフィックス向けのAPIを使って汎用的な計算をさせるとなると、そのプログラミングには幅広い知識が必要です。NVIDIAはC/C++のような「普通の」言語でGPUを操作できる開発環境である「CUDA」を提供することで、GPGPU向け開発のハードルを一気に下げたのです[1]。
CUDAを使うのであればCUDAに対応したGPUが必要です。たとえばGPGPU専用として高性能コンピューティング向けに提供されているTeslaシリーズはもちろんのこと、ワークステーション向けのQuadroやデスクトップ・ゲーム向けのGeForce、モバイル向けのTegraにいたるまで、ここ数年でNVIDIAからリリースされたGPUやGPUを組み込んだチップであれば、大抵はGPGPU用途としてCUDAを利用可能です。
特にアーキテクチャーを刷新したKepler以降のGPUがよく使われています。昨年リリースされたPascalを搭載したGPUはもちろんのこと、Pascalの登場によって旧世代となったMaxwellを搭載するGPUもハイエンド側の価格が下がっており、「深層学習などを人間が学習する」ためにお手頃な存在となっているようです。今から入手するのであれば、Maxwellアーキテクチャーを搭載したGPUのうち値段が下がっているものか、Pascalアーキテクチャーを搭載したGPUになるでしょう。予算と電源が許せばよりハイエンドなGPUが選択肢に、「とりあえず試す」だけなら安めで低消費電力なGPUが選択肢になります。「用途に合わせてグレードを選ぶ」必要はあるものの、Kepler以降であればどのグレードであってもCUDAがまったく使えないということはまずありません[2]。
GPUを動かすようなスペースがないということであれば、クラウドのGPUインスタンスを使うという手もあります。
Amazon EC2のg2.2xlargeだとKepler世代のGPUを東京リージョンのオンデマンドインスタンスで「$0.898/1時間」ぐらいの価格になるようです。100時間ぐらいであればGPUボードを買うよりも安いですし、CUDA用に新しいマシンを用意したり、さらには電気代や場所代、ご家庭内での立場も考えると、大抵の人にとってはもっと長時間使ってもペイすることでしょう。
GPUインスタンスそのものにいくつかの制約はあるものの、基本的にLinuxが起動してしまえばあとは物理マシンと同じです。第454回で紹介したNVIDIAドライバーのインストール方法もそのまま使えます。ディスプレイの出力先がNVIDIAのGPUになっており、変更するすべはないという点については注意が必要です。Ubuntuのクラウドイメージは「Ubuntu Cloud Image Finder」で検索すると良いでしょう。Amazon EC2であればこのページのリンクをクリックするだけで、インスタンスの立ち上げページに移動できます[3]。
Ubuntuの公式リポジトリのCUDAについて
CUDAは残念ながらプロプライエタリなソフトウェアです。しかしながらUbuntuの公式リポジトリにもそのパッケージは存在します。
Ubuntu 16.04 LTSでインストールできるパッケージ版のバージョンはCUDA 7.5となります[4]。それに対してCUDAの最新バージョンは昨年9月末にリリースされたCUDA 8.0です。PascalアーキテクチャーのサポートやUnified Memoryの機能強化、Mixed-Precision、コンパイラーの機能拡張、Ubuntu 16.04 LTSのサポートなどなど、CUDA 8.0にはさまざまな機能拡張や不具合の修正が行われているため、今からCUDAをインストールするのであれば、最新の8.0を導入したいところでしょう。また公式リポジトリのパッケージ版のCUDAは、NVIDIAのドライバーについても公式リポジトリのパッケージを使う前提になっています。つまり第454回のように、NVIDIA製のドライバーをスクリプトでインストールした場合は、このパッケージは使えません。Maxwellアーキテクチャー以前のGPUに対して、デスクトップ用途でCUDAをお手軽に利用したい場合のみパッケージ版が選択肢となります。
そこで、今回もNVIDIA製のスクリプトを使ってCUDA 8.0をインストールしましょう。
CUDA 8.0をインストールするいくつかの方法
最初にCUDA 8.0をインストールするスクリプトをダウンロードします。CUDA 8.0のダウンロードページから「Linux
」「x86_64
」「Ubuntu
」「16.04
」を順番に選択してください。
現在のCUDAは、ホストとして32bitアーキテクチャーを利用できません。32bit版のUbuntuでは動きませんので注意してください。また、今回はタイトルにもあるようにUbuntu 16.04 LTSへとインストールしますが、手順としては16.04固有の話はないため、Ubuntu 14.04 LTSでもそのまま利用できるはずです。
最後に「Install Type」として次の4つのタイプが提示されます。
- runfile (local)
- 「全部入り」の実行スクリプトです。CUDAのツールキットはもちろんのこと、サンプルコードやドライバーも同梱されています。そのためサイズが1.4GBと非常に大きくなっています。
- deb (local)
- 「runfile (local)」の中身を個別にDebianパッケージにしたものです。ダウンロードするサイズは、さらに大きく(1.9GB)なります。
- deb (network)
- NVIDIAが提供するパッケージリポジトリを登録するためのパッケージです。上の2つに比べるとサイズは小さくなりますが、このパッケージをインストールしたあとに、CUDA本体をパッケージマネージャーを用いてネットワーク越しにダウンロード・インストールする必要があります。
- cluster (local)
- 名前からの推測ですがクラスタ向けのインストールパッケージです。原則としてライブラリとドライバーのみを複数のノードにインストールすることを想定していて、CUDAコンパイラーなどは「開発用パッケージ」という扱いになっています。単に「普通のPCでCUDAを試す」場合は、このタイプを使うことはありません。
デスクトップ用途で使うのであれば「deb (network)」をおすすめします。このタイプであればNVIDIAのパッケージリポジトリが追加されるため、CUDAの新バージョンへの更新が簡単になります。またNVIDIA製ドライバーの比較的新しいバージョンも同じリポジトリに登録されているため、このパッケージをインストールするだけでどちらも新しいバージョンに保てるというメリットがあるのです。
「deb (local)」は一度ダウンロードした上で、複数のマシンにデプロイしたい場合に有用です。こちらは「/var/cuda-repo-8-0-local
」にローカルパッケージリポジトリを作成し、そこからCUDA関連のパッケージをインストールすることになります。たとえばリポジトリ用のインスタンスを1つ用意し、そのインスタンスに「deb (local)」をインストールします。他のマシンはリポジトリ用インスタンスからパッケージをインストールすれば、インターネット上のトラフィックは最小限で済みます。
ただし「deb (network)」にしろ「deb (local)」にしろ、2017年1月時点でインストールできるNVIDIA製ドライバーは367.48と、Ubuntu公式リポジトリにある367.57より古いバージョンになっています。また367はGeForce GTX 1050/1050 Tiなどをサポートしていません。また、パッケージ版をそのままインストールしようとするとデスクトップグラフィック向けのライブラリやX Window Systemなども一緒にインストールします。インストールするプログラムをある程度制限したい場合は、「runfile (local)」が最善の方法になるでしょう。
パッケージ版を使ってインストール
まずはパッケージ版をインストールする方法を紹介しましょう。デスクトップであれば、単純にウェブブラウザーからダウンロードリンクをクリックして、ダウンロードダイアログで「ソフトウェアのインストール」を選べばインストールが始まります。
「ソフトウェアのインストール」は使わずに、SSHログインしてインストールしたいなら次の手順でコマンドを実行していきましょう。まずはパッケージファイルをダウンロードします。
以降の説明では、ファイル名は「deb (network)」で統一します。必要に応じて置き換えて読んでください。
パッケージファイルの中身はdpkg-deb
コマンドで確認できます。公式リポジトリの外からパッケージファイルをダウンロードする場合は、まずその中身を確認する習慣をつけておきましょう。ちなみに下記の内容であれば単にless
コマンドにパッケージファイルを指定するだけでも確認できます。
「deb (network)」は単にパッケージリポジトリのファイルをインストールするだけであることがわかります[5]。「deb (local)」の方は、上記に加えてパッケージファイル一式を「/var/cuda-repo-8-0-local/
」以下に保存します。
内容に問題がなければ、パッケージをインストールしましょう。インストールが完了すれば「ソフトウェアのインストール」を使った場合と同じ状態になります。
パッケージのインストール後にapt-key
で確認すると、NVIDIAのサイトにあるリポジトリ鍵も追加されていることがわかります。
リポジトリが追加されたのでパッケージリストを更新しましょう。「deb (local)」の場合もローカルのパッケージリストを参照することになるため、同様にリストの更新が必要です。
警告が出てしまいました。これはRelease
ファイルのDate
フィールドは、GMT以外のタイムゾーンの指定は許されていないにも関わらず、NVIDIAの提供するRelease
ファイルには「-0700
」が指定されているためです。
現時点ではこの警告は無視しても問題ありません。
最後にcudaパッケージをインストールしましょう。cudaパッケージはツールキットやサンプル、ドライバーなどすべてのパッケージをインストールするためのメタパッケージです。
Ubuntuサーバー上でcudaパッケージをインストールしようとすると、上記のように674個(1.6GB)のパッケージをダウンロードする必要があります。また、インストール後にはデスクトップ環境が立ち上がることになります。UbuntuサーバーにCUDAをインストールするなら、次のように「--no-install-recommends
」オプションを指定してください。
Ubuntuデスクトップにインストールするなら大半はインストール済みのパッケージとなりますので、「--no-install-recommends
」をつけるかどうかは好みで判断すると良いでしょう。前述した通り上記リポジトリにはNVIDIA製ドライバーパッケージも含まれています。この方法を使うなら第454回のようにインストーラースクリプトを使わず、CUDAのインストーラーパッケージからドライバーをインストールしたほうが便利です。
パッケージ版のCUDAをアンインストールするなら、インストールしたパッケージを一通り削除した上で、以下の手順でリポジトリリストとリポジトリ鍵も削除しておきましょう。
スクリプト版を使ってインストール
スクリプト版はNVIDIA製ドライバーと同じく、インストーラースクリプトをダウンロードして実行するだけです。インストーラースクリプトはシェルスクリプトとバイナリアーカイブが結合したフォーマットになっています。
いろいろオプションが表示されますが、基本的に対話形式で設定していきます。オプションを指定することで対話部分を飛ばすことは可能ではあるものの、初めてインストールするなら一通り見ておいたほうがいいでしょう。
ちなみにNVIDIA製ドライバーのインストーラーはncursesを用いたCUIなスクリプトでしたが、CUDAのインストーラーはコンソールにひたすら文字が表示されるだけのPerlスクリプトです。
これでスクリプトを用いた必要なファイルのインストールは完了です。
アンインストールしたい場合は、一緒にインストールされたアンインストールスクリプトを実行してください。
インストール後の設定
パッケージ版にしろスクリプト版にしろ、ツールキットのコマンド群は「/usr/local/cuda-8.0/bin
」に、各種ライブラリは「/usr/local/cuda-8.0/lib64
」にインストールされます[6]。どちらもUbuntu標準の設定ではコマンドやライブラリの検索対象にならないため、まずは検索対象にする設定を行いましょう。特定のユーザーのみCUDAを使うのであればセッションローカルな方法で、そのシステムのすべてのユーザーがCUDAを使う予定があるのならシステムワイドな方法で設定します。
セッションローカルに設定する方法
Ubuntu標準のBashを使用しており、セッションローカルで設定したい場合は、環境変数の「PATH
」と「LD_LIBRARY_PATH
」を「~/.profile
」に記述するのが一番無難です。
環境変数「PATH
」は「コマンドを実行する時の検索パス」です。「foo
」コマンドを実行したとき、PATH
に設定されているパスから順番に実行できる「foo
」ファイルを探す仕組みになっています。
Ubuntuの標準のPATH
の値はおおよそ上記のとおりです。「/usr/local/cuda-8.0/bin
」が含まれていないため、CUDAのコンパイラである「nvcc
」を実行したい時は、わざわざ「/usr/local/cuda-8.0/bin/nvcc
」と入力しなくてはなりません。そこでログインした時点でPATH
に、「/usr/local/cuda-8.0/bin
」を追加するよう「~/.profile
」を編集します。
Ubuntuでアカウントを作成するとBashがログインシェルとして設定されます。UbuntuのBashはログインシェルとして実行された時には「~/.profile
」と「~/.bashrc
」を、さらに単純にシェルとしてBashが起動するたびに「~/.bashrc
」を読み込みます[7]。加えてBashには環境変数をexport
すると、その環境から起動したプログラムにも環境変数の値が引き継がれるという仕組みが存在します。Ubuntuの環境変数PATH
はあらかじめexport
されているので、ログインシェルで一度設定すれば良いということになります。
環境変数LD_LIBRARY_PATH
は、コマンドを実行する時に「ローダーが必要なライブラリを検索するためのパス」を設定します。環境変数PATH
のライブラリファイル版ぐらいに思っておけば良いでしょう。こちらはUbuntuにログインした時点では特に設定はされていませんので、明示的にexport
する必要があります。
ということで「~/.profile
」に次の最初の3行を記述しましょう。
通常は末尾に記載すれば問題ありません。ただしByobuを利用している場合は別です。Byobuをログイン時に自動的に実行するよう設定すると「~/.profile
」の末尾にbyobu-launch
を実行するコードを追記します。この行より後ろで環境変数を設定したとしても実際には反映されませんので、Byobuを使用している場合は、次のようにByobu関連の設定よりは前に環境変数の設定が来るようにしてください。
システムワイドに設定する方法
システムワイドに設定を反映させたい場合は、やり方が若干異なります。
まず環境変数PATH
を設定するために、「cuda.sh
」という名前で以下の設定スクリプトファイルを「/etc/profile.d
」に置きます。
ログインシェルが「/etc/profile
」を読み込んだあとに「/etc/profile.d
」以下のファイルが順番に読み込まれていきます。なお、ファイル名の末尾が「.sh
」でないものは無視されます。また実行権限を付けておく必要はありません。
ライブラリの検索パスは、ローダーの設定ディレクトリ「/etc/ld.so.conf.d
」を使用します。このディレクトリに「cuda.conf
」という名前で作成してください。こちらもファイルの末尾は「.conf
」にしておく必要があります。
ld.so.conf.d
を変更したので、次のコマンドでld.so.cacheを再構築します。
動作確認
環境変数の設定を反映させるために、一度ログアウトしてから再度ログインしてください。最後に期待通り設定されているか確認しておきましょう。
サンプルプログラムのビルドと実行
CUDAには「サンプルプログラム」が含まれています。パッケージ版であればcuda-samples-8-0パッケージをインストールすれば「/usr/local/cuda-8.0/samples/
」にサンプルコードがインストールされます。スクリプト版なら同じ場所にインストールした上で、コンパイルしやすいようにユーザーのホームディレクトリにもコードをコピーしてくれます。
実際にサンプルプログラムをビルドしてみましょう。まずC++コンパイラなどをあらかじめインストールしておきます。
あとはサンプルプログラムのトップディレクトリでmake
を実行するだけです。ちなみにそれなりに時間はかかります。
個々のプログラムの詳細はサンプルリファレンスに掲載されています。このうち「Dependencies」に「X11」や「GL」が記載されているサンプルは実行にデスクトップ環境などが必要になりますので注意しておきましょう。
deviceQueryはCUDAデバイスの情報を表示するためのプログラムです。接続しているデバイスの詳細な情報を確認したい場合に便利でしょう。
bandWidthTestはGPUデバイス間やホストとのメモリコピーに関わる帯域幅を簡易的に計測するツールです。
最後に計算量の大きなサンプルも実行してみましょう。よく使われているのはnbodyです。その名の通り重力多体計算を行うプログラムで、N個の粒子の重力相互作用を計算しながら系の時間変換をシミュレートしていく、まさに並列処理が効いてくる計算です。ただCUDAのnbodyは、計算結果の表示のためにX11とGLに依存しています。デスクトップ環境にCUDAをインストールした場合であれば実行できますが、Ubuntuサーバーの場合はヘッダーファイルやライブラリが足りないためにビルドをスキップします。
nbody
コマンドそのまのは-benchmark
オプションをつけることで、X11環境ではなくても実行できるようです。そこでビルドに必要なライブラリだけ別途インストールします。
もう一度make
しなおせば、nbody
コマンドがあらわれるはずです。
エントリークラスのGPUであるにも関わらず単精度で1TFLOPSは普通に出ているようです。ちなみにGeForce GTX 1050 Tiの理論値は2TFLOPSぐらいだとか。さらにnbody
は「-cpu
」オプションをつけるとCPUのみで計算します。
もうひとつcdpLUDecompositionも実行してみましょう。「cdp」は「CUDA Dynamic Parallelism」の略で、簡単に言うとGPU側の計算中のスレッドからさらにスレッドを起動できる仕組みです。「Compute Capability 3.5」以降に追加された機能なので、Keplerアーキテクチャーでも動かない可能性があります[8]。「LUDecomposition」は「LU分解」のことで、行列を下三角行列と上三角行列に分解します[9]。実際はLAPACKのdgetrfをCUDAに移植して使っているようです。
cdpLUDecomposition
は「-matrix_size
」オプションで正方行列の次数を指定できます。
こちらはほぼ倍精度の理論値(62 Gflops)に近い値が出ています。
実際に計算中に裏でnvidia-smi -l
コマンドを実行すれば、GPUの使用率やメモリ・電力の使用量などが目に見えて変わるはずです。
それ、Dockerなら簡単だよ
いかがでしたでしょうか。なるべく丁寧に説明したので手順が多く感じるかもしれませんが、一度理解してしまえばそこまで難しくありません。とはいえ「apt
コマンド一発」というほどお手軽ではないのも事実です。この先、複数のバージョンを併用したい場合もあるかもしれません。さらにCUDAをインストールするだけで終わるということはまずありません。たとえば深層学習向けのCUDAライブラリであるcuDNNをインストールするなら、さらにひと手間必要になります。
NVIDIAはCUDA環境を簡単に構築できるDockerfileを提供しています。そこで次回はDockerやLXDといったコンテナ上にCUDA環境を構築する方法について説明します。