データ分析
昨年11月、Googleが機械学習用のフレームワーク「TensorFlow」を公開しました。あのGoogleの知名度をして、今後の深層学習研究開発における、TensorFlowの定位置化を予感された方は多いのではないかと思います。
そんなTensorFlowですが、残念な事に、AWSとの相性は良好であるとは言えません。
というのは、EC2で利用できるGPU(GRID K520)をTensorFlowがサポートしておらず、学習の際にGPU計算の恩恵を受けられないためです。
公式配布のGPU計算用TensorFLowパッケージをAWSに導入して実行すると、
I tensorflow/core/common_runtime/gpu/gpu_device.cc:669] Ignoring gpu device (device: 0, name: GRID K520, pci bus id: 0000:00:03.0) with Cuda compute capability 3.0. The minimum required Cuda capability is 3.5.
最低3.5以上のCudaComputeCapabilityに対応したGPUが必要とのこと。(AWSのGPUは3.0)
TensorFlow公開より随分経った現在では、この不都合は緩和され、多少の手間によりCPU計算が出来る様になりました。
そのために必要となる手法やヒントは、公式サイトを始め、いくつかのサイトで公開されています。
本記事では、これらの情報を参考に、AWSにTensorFlowを導入する流れをまとめます。
※本記事は、参考記事(Installing TensorFlow on EC2)の記載手法に基本準拠して作成しています。 但し、筆者理解の範囲の解説と、僅かなアレンジが混ぜ込まれていますので、ご了承下さい。 また、後述する様に、本手順は開発中のコードを用いて作業を進めます。 不安定なコードに起因する障害の可能性にご注意を願います。 最後に、本記事は2016年1月に作成されています。 今後のTensorFlow導入手順の変化(あるいはAWSのGPU事情の改善)に依っては、これより掲示する手順が陳腐化する可能性があることをご留意下さい。
- 作業概要とその前提
- 必要パッケージの導入
- GPU関連の導入・設定
- Bazelのビルド
- TensorFlowのパッケージのビルド
- インストール、そしてテスト
- おまけ:Python3.x用の非公式TensorFlowのビルド
- 備考
作業概要とその前提
AWSでGPU計算可能なTensorFlowは、ソースコードからビルドされた、非公式のパッケージを用いて導入する事が出来ます。このビルド作業には、いくつかのパッケージやそれらの設定などが、前提として必要になります。
以下、順を追って、その作業を提示します。
なお今回提示の手順は、下記環境で導入検証されています。
・AWS EC2 g2.2xlarge に、適当な大きさのEC2 Containerがアタッチされている環境で作業する
・Ubuntu Server 14.04 LTS (HVM), SSD Volume Type – ami-936d9d93 を導入済み
・各種基本設定(host, user設定など)が完了
・TensorFlow version 0.6.0 のソースコードを元に、GPUサポート付で計算可能な、Python2.x用のインストールパッケージを構築を目的とする
必要パッケージの導入
sudo apt-get update sudo apt-get -y upgrade
upgradeの際、boot/grub/menu.lst関連設定の導入如何が問われますが「install the package maintainer’s version」を選んで下さい。
sudo apt-get -y install build-essential python-pip python-dev git python-numpy swig zip zlib1g-dev sudo apt-get -y install linux-image-extra-virtual
GPU関連の導入・設定
CUDA関連のライブラリは、NVIDIAの開発者向けページより取得できます。
CUDA Toolkit 7.0
cuDNN 6.5 V2
以後の作業では、これらが既に取得済みであることを前提とし、またCUDA Toolkitに含まれるグラフィックドライバを適用するものとします。
なお、cuDNN 6.5 V2を取得するには、NVIDIAのメンバー登録(無料、承認まで数日所要)が必要です。
NVIDIAの純正グラフィックドライバは、ubuntuプリインストールのドライバ「nouveau」と競合してしまうそうです。
そこで、「nouveau」をブラックリストに追加し、競合を回避した上で、純正ドライバのインストールを実施します。
sudo vi /etc/modprobe.d/blacklist-nouveau.conf
を実行して、
blacklist nouveau blacklist lbm-nouveau options nouveau modeset=0 alias nouveau off alias lbm-nouveau off
を記入して、保存します。
同様に、
sudo vi /etc/modprobe.d/nouveau-kms.conf
を実行して
options nouveau modeset=0
を記入して保存します。
カーネル回りの変更の反映と、nouveau無効化のため、ここでインスタンスを再起動しておきます。
sudo update-initramfs -u sudo reboot
Linuxカーネルをアップデートしてから、NVIDIA純正グラフィックドライバとCUDA Toolkitをインストールします。
取得済みのCUDA Toolkitのインストーラ「cuda_7.0.28_linux.run」を実行します。
sudo apt-get -y install linux-source linux-headers-<code>uname -r</code> chmod +x cuda_7.0.28_linux.run sudo ./cuda_7.0.28_linux.run
ライセンス承認後、ドライバやライブラリのインストール是非と、その周辺について、いくつか入力が求められます。
これらを運用体系に合わせて設定します。
#「accept」を指定します Do you accept the previously read EULA? (accept/decline/quit): accept #「y」を指定します Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 346.46? ((y)es/(n)o/(q)uit): y #デフォルト値(yes)を指定します(そのままEnter) Do you want to install the OpenGL libraries? ((y)es/(n)o/(q)uit) [ default is yes ]: #「y」を指定します Install the CUDA 7.0 Toolkit? ((y)es/(n)o/(q)uit): y #デフォルト値(/usr/local/cuda-7.0)を指定します(そのままEnter) Enter Toolkit Location [ default is /usr/local/cuda-7.0 ]: #「y」を指定します Do you want to install a symbolic link at /usr/local/cuda? ((y)es/(n)o/(q)uit): y #「n」を指定します Install the CUDA 7.0 Samples? ((y)es/(n)o/(q)uit): n
グラフィックドライバとCUDA Toolkitのインストールが終了したら、今度はcuDNNを導入します。
cuDNNのアーカイブ「cudnn-6.5-linux-x64-v2.tgz」を展開し、必要なファイルをCUDA Toolkitインストール先の所定フォルダに配置すれば完了です。
tar -xzf cudnn-6.5-linux-x64-v2.tgz sudo cp cudnn-6.5-linux-x64-v2/libcudnn* /usr/local/cuda/lib64 sudo cp cudnn-6.5-linux-x64-v2/cudnn.h /usr/local/cuda/include/
ここで、CUDA関連の環境変数を追加しておきます。
ログインシェル(~/.profile 、運用体系によっては ~/.bashrc)を編集して、以下の2行を追加します。
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64" export CUDA_HOME=/usr/local/cuda
編集後、ログインシェルの読み直しを忘れずに。
source ~/.profile #または source ~/.bashrc
Bazelのビルド
前提にJDK8が必要ですので、先ずはその用意から。
#JDK8を取得する為に「webupd8team/java」をリポジトリに追加します。 sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get -y install oracle-java8-installer
JDK8インストールの際、ライセンスの承認が必要です。
今回は、Bazelをソースコードからビルドして導入します。
Bazelのソースコードを取得し、version 0.1.1をチェックアウト(TensorFlow 0.6.0 のビルドには、旧バージョンのBazelが必要)、
然る後にコンパイルを実施し、完成したbazelを /usr/bin に配置すれば完了です。
git clone https://github.com/bazelbuild/bazel.git cd bazel git checkout tags/0.1.1 ./compile.sh sudo cp output/bazel /usr/bin
TensorFlowのパッケージのビルド
TensorFlowの非公式パッケージのビルドに移ります。
Bazel同様、ソースコードを取得します。
#サブモジュールも必要なので、オプション --recurse-submodules の指定を忘れずに git clone --recurse-submodules https://github.com/tensorflow/tensorflow
非公式設定(TF_UNOFFICIAL_SETTING=1)の元、ビルドのコンフィグを実施します。
各種入力が求められるので、運用体系に合わせて設定します。
cd tensorflow TF_UNOFFICIAL_SETTING=1 ./configure #デフォルト値(/usr/bin/python)を指定します(そのままEnter) Please specify the location of python. [Default is /usr/bin/python]: #「y」を指定します。 Do you wish to build TensorFlow with GPU support? [y/N] y GPU support will be enabled for TensorFlow #デフォルト値(/usr/local/cuda)を指定します(そのままEnter) Please specify the location where CUDA 7.0 toolkit is installed. Refer to README.md for more details. [Default is /usr/local/cuda]: #デフォルト値(/usr/local/cuda)を指定します(そのままEnter) Please specify the location where CUDNN 6.5 V2 library is installed. Refer to README.md for more details. [Default is /usr/local/cuda]: WARNING: You are configuring unofficial settings in TensorFlow. Because some external libraries are not backward compatible, these settings are largely untested and unsupported. Please specify a list of comma-separated Cuda compute capabilities you want to build with. You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus. Please note that each additional compute capability significantly increases your build time and binary size. #「3.0」を指定します [Default is: "3.5,5.2"]: 3.0
この設定により、Python2.x用、GPUによる計算サポート有、(AWSに搭載されている)CUDA Compute Capability 3.0 GPUに対応した、非公式TensorFlowのビルドコンフィグが指定できました。
それではBazelを用いてTensorFlowをビルドし、それをpipパッケージにまとめます。
bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow/
これでインストールの準備が整いました。
インストール、そしてテスト
#パッケージのファイル名は、設定に応じて変わります。 sudo pip install /tmp/tensorflow/tensorflow-0.6.0-cp27-none-linux_x86_64.whl cd tensorflow/models/image/cifar10/ python cifar10_train.py
I tensorflow/stream_executor/dso_loader.cc:101] successfully opened CUDA library libcublas.so.7.0 locally I tensorflow/stream_executor/dso_loader.cc:101] successfully opened CUDA library libcudnn.so.6.5 locally I tensorflow/stream_executor/dso_loader.cc:101] successfully opened CUDA library libcufft.so.7.0 locally I tensorflow/stream_executor/dso_loader.cc:101] successfully opened CUDA library libcuda.so locally I tensorflow/stream_executor/dso_loader.cc:101] successfully opened CUDA library libcurand.so.7.0 locally &amp;gt;&amp;gt; Downloading cifar-10-binary.tar.gz 100.0% Succesfully downloaded cifar-10-binary.tar.gz 170052171 bytes. Filling queue with 20000 CIFAR images before starting to train. This will take a few minutes. I tensorflow/core/common_runtime/local_device.cc:40] Local device intra op parallelism threads: 8 I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:909] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero I tensorflow/core/common_runtime/gpu/gpu_init.cc:103] Found device 0 with properties: name: GRID K520 major: 3 minor: 0 memoryClockRate (GHz) 0.797 pciBusID 0000:00:03.0 Total memory: 4.00GiB Free memory: 3.95GiB I tensorflow/core/common_runtime/gpu/gpu_init.cc:127] DMA: 0 I tensorflow/core/common_runtime/gpu/gpu_init.cc:137] 0: Y I tensorflow/core/common_runtime/gpu/gpu_device.cc:702] Creating TensorFlow device (/gpu:0) -&amp;gt; (device: 0, name: GRID K520, pci bus id: 0000:00:03.0) I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:42] Allocating 3.66GiB bytes. I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:52] GPU 0 memory begins at 0x7023e0000 extends to 0x7ec556000 I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 1.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 2.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 4.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 8.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 16.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 32.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 64.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 128.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 256.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 512.0KiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 1.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 2.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 4.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 8.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 16.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 32.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 64.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 128.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 256.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 512.00MiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 1.00GiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 2.00GiB I tensorflow/core/common_runtime/gpu/gpu_bfc_allocator.cc:66] Creating bin of max chunk size 4.00GiB I tensorflow/core/common_runtime/direct_session.cc:58] Direct session inter op parallelism threads: 8 2016-01-13 07:01:44.412213: step 0, loss = 4.67 (2.7 examples/sec; 46.668 sec/batch) 2016-01-13 07:01:49.269021: step 10, loss = 4.66 (300.2 examples/sec; 0.426 sec/batch) 2016-01-13 07:01:53.716100: step 20, loss = 4.64 (281.7 examples/sec; 0.454 sec/batch) ...
動作が確認できました。
GPUデバイスもちゃんと認識されている模様です。
おまけ:Python3.x用の非公式TensorFlowのビルド
作業の内容やその前提は、基本的にPython2.x用のビルドの場合と同じです。
但し、Python3.x用の非公式ビルドのためには、Python3.xに関する追加のパッケージが必要です。
sudo apt-get -y install python3-pip python3-numpy
また、非公式ビルドのコンフィグ時における、Pythonの参照先指定が異なります。
TF_UNOFFICIAL_SETTING=1 ./configure
・Please specify the location of python. [Default is /usr/bin/python]:?/usr/bin/python3
この設定の上で、上記と同様にビルドすると、python3.x用のパッケージが作成されます。
これをpip3でインストールすれば完了です。
sudo pip3 install /tmp/tensorflow/tensorflow-0.6.0-cp34-none-linux_x86_64.whl
※パッケージのファイル名は、設定に応じて変わります。
※注意
Python3.x用のTensorFlowのビルドは、TensorFlowの開発の都合上、Python2.x用のビルド以上に不安定です。
ライブラリ依存性やコーディングなどに起因したバグにより、ビルドやインストールが失敗する場合が十分あり得ます。
上述のおまけの手順で失敗した場合、公式のIssueの利用や、別コミットのコードのビルドなど、追加の試行錯誤が必要である点をご留意下さい。
備考
■参考元の記事には、本記事に無い、有用なテクニックが含まれています。例えば下記の点が挙げられます。
・EC2の揮発ディスク領域を計算資源として利用する方法TensorFlowをちょっとだけ試したい場合や、EC2 Containerを併用しない場合には、こちらが有効かも知れません
・参考元記事では、CUDA_7.x.xx_linux.runを展開し、グラフィックドライバとCUDA Toolkitを独立にインストールする手法:
導入するグラフィックドライバを選びたい場合は、これに倣うと良いかも知れません。