curluneの日記

日々試行錯誤。雑多に、気ままに、てきとーに。HoloLens/Oculus Rift,Touchと戯れる日々。

Fedora25 に Caffe(GPU/CUDA8+cuDNN) + pyCaff(Python3) 環境を作る

先日Fedora 25で環境を作ったときに頑張ったので作業メモ。

試行錯誤を繰り返し、なんとか Fedora 25 + CUDA 8 + cuDNN + Caffe(git) + pyCaffe(python3)という環境は作れました。

取りあえず必要なものはnvidiaGPU。今回はGTX 1080です。 Fedora25のLiveイメージをインストールし、アップデートとVimのインストールをしただけの環境です。

.# 先週からちょこちょこと書き足しつづけ、きりがないので取りあえず公開。

最終的にはこんな感じ

いろいろ試していたのでもしかしたら過不足あるかも...。 設定ファイルは差分を最後に載せておきます。

# リポジトリ追加
sudo dnf config-manager --add-repo=http://negativo17.org/repos/fedora-nvidia.repo
# GPUドライバインストール
sudo dnf install nvidia-driver kernel-devel dkms-nvidia
# 念のため再起動
# (sudo reboot)
# いろいろインストール
sudo dnf install cuda-devel gflags-devel glog-devel lmdb-devel cuda-cudnn-devel cuda-cublas atlascpp-devel clang python3-devel boost-python3-devel
# Caffeのコードを取ってくる
# (cd path/to/dir)
git clone https://github.com/BVLC/caffe.git caffe
cd caffe
# 設定をコピーして調整
# 差分 > 別途記述
cp Makefile.config{.example,}
# (vim Makefile.config)
# boost のヘッダファイル調整
# 差分 > 別途記述
# (sudo vim /usr/local/boost/config/suffix.hpp)
# Caffeをビルドしてテストを実行!
make all && make test && make runtest
# pyCaff ビルド
# venv作成 名前や場所はお好みで
python -m vemv ~/venv_caffe
. ~/venv_caffe/bin/activate
pushd python
# 依存パッケージインストール
pip install -r requirements.txt
# python3対応のためアップグレード
pip install python-dateutil --upgrade
popd
# PATH設定 同等の内容を ~/.bash_profile へ追記すると便利
# /path/to/caffe はcaffeのディレクトリ
PYTHONPATH=/path/to/caffe/python/:$PYTHONPATH
export PYTHONPATH
make pycaff

# pythonでインポートしてみる
python
import caffe

cudaのインストール

こちらの成果物をありがたく使わせてもらいました。

negativo17.org

公式配布verでは、依存関係の都合でドライバ周りがややこしい事になってたり、そもそもFedoraは23しかなかったりするのですが、こちらのリポジトリではすんなりと25へ入れられました。感謝!

Caffeビルドの設定

ここでけっこうつまづいていました... 結局のところ以下の4つの改善でどうにかなりました。

最終的な設定ファイルは最後のあたりに。

  • 新しいgccではビルドできないのでclangを使う
  • boost 1.60 はそのままではビルドできないので少し細工する
  • atlasのライブラリインストールと場所指定
  • CUDAの場所指定

gccの代わりにclangを使う

NVCC src/caffe/layers/elu_layer.cu
/usr/lib/gcc/x86_64-redhat-linux/6.2.1/include/stddef.h(436): error: identifier "nullptr" is undefined

/usr/lib/gcc/x86_64-redhat-linux/6.2.1/include/stddef.h(436): error: expected a ";"

/usr/include/c++/6.2.1/x86_64-redhat-linux/bits/c++config.h(2092): error: expected a ";"

/usr/include/c++/6.2.1/exception(63): error: expected a ";"
... (略)

今回の環境は gcc バージョン 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC)。

なにやら新しいめのGCCはサポートされていない模様。試しに実行するもエラーに遭遇...。理由?みたいなものを何処かで見た気がするけどURL失念。

この辺りや、他いくつか見ながらフラグと調整すると、若干は進んだ気がするけれど、また別のエラーに。対処しきれないオーラを感じて別の手段を検討。

bugs.archlinux.org

さすがにgccビルドは面倒オーラがひしひしとしたのでclangへ逃げました! エラーも読み易くなってお得!

CUSTOM_CXX := clang++

boost 1.60 のヘッダファイルを細工

NVCC src/caffe/layers/cudnn_lrn_layer.cu
/usr/include/boost/config/suffix.hpp(511): error: identifier "__float128" is undefined

1 error detected in the compilation of "/tmp/tmpxft_00006b3e_00000000-11_cudnn_lrn_layer.compute_50.cpp1.ii".
Makefile:588: ターゲット '.build_release/cuda/src/caffe/layers/cudnn_lrn_layer.o' のレシピで失敗しました
make: *** [.build_release/cuda/src/caffe/layers/cudnn_lrn_layer.o] エラー 1

下記ページにたどり着いてどうにかビルドは通るようになりました。ちょっと怪しいけれど取りあえずはよし、ということで。 コメントのsource:のリンク先の通りに書き換えで解決?です。

github.com

--- /usr/include/boost/config/suffix.hpp.orig    2016-12-18 02:21:02.614381963 +0900
+++ /usr/include/boost/config/suffix.hpp  2016-12-07 01:23:21.636332835 +0900
@@ -507,7 +507,9 @@
 #if defined(BOOST_HAS_FLOAT128) && defined(__cplusplus)
 namespace boost {
 #  ifdef __GNUC__
-   __extension__ typedef __float128 float128_type;
+   // https://github.com/BVLC/caffe/issues/3578
+   // __extension__ typedef __float128 float128_type;
+   __extension__ typedef long double float128_type;
 #  else
    typedef __float128 float128_type;
 #  endif

atlasのライブラリインストールと場所指定

NVCC src/caffe/solvers/nesterov_solver.cu
AR -o .build_release/lib/libcaffe.a
LD -o .build_release/lib/libcaffe.so.1.0.0-rc3
/usr/bin/ld: -lcblas が見つかりません
/usr/bin/ld: -latlas が見つかりません
clang-3.8: error: linker command failed with exit code 1 (use -v to see invocation)
Makefile:566: ターゲット '.build_release/lib/libcaffe.so.1.0.0-rc3' のレシピで失敗しました
make: *** [.build_release/lib/libcaffe.so.1.0.0-rc3] エラー 1

今回不足していたのはこちら。

  • atlas-static

ライブラリ別枠なのね...。さらに読み込むための設定も必要です。

実は読み込みについてはドキュメントに載っていたのだけれど気づかず。エラー見ながら実体さがしてました。(ここではatlas-devel って書いてあるだけなのに...。

Caffe | Installation: RHEL / Fedora / CentOS

CUDAの場所指定

CXX src/caffe/solver.cpp
In file included from src/caffe/solver.cpp:6:
In file included from ./include/caffe/solver.hpp:7:
In file included from ./include/caffe/net.hpp:10:
In file included from ./include/caffe/blob.hpp:8:
In file included from ./include/caffe/common.hpp:19:
./include/caffe/util/device_alternate.hpp:34:10: fatal error: 'cublas_v2.h' file not found
#include <cublas_v2.h>
         ^
1 error generated.
Makefile:575: ターゲット '.build_release/src/caffe/solver.o' のレシピで失敗しました
make: *** [.build_release/src/caffe/solver.o] エラー 1
NVCC src/caffe/layers/cudnn_lrn_layer.cu
make: /usr/local/cuda/bin/nvcc: コマンドが見つかりませんでした
Makefile:588: ターゲット '.build_release/cuda/src/caffe/layers/cudnn_lrn_layer.o' のレシピで失敗しました
make: *** [.build_release/cuda/src/caffe/layers/cudnn_lrn_layer.o] エラー 127

2種類の設定、CUDA自体のインストール場所と、CUDAのヘッダファイルの場所が必要です。

まずは気づきやすいCUDAのインストール先。 CUDA_DIR/usr/local/cuda から /usr変更します。

もうひとつは分かりづらいヘッダファイルのインクルードパスです。 どうやらサブディレクトリにいるため見つからないと怒られるらしい...。 インクルードパスを追加してあげる事で解決です。 INCLUDE_DIRS += /usr/include/cuda

CUDA周りの悩ましい(?)事は、CUDAのコマンドが見つからないよりも先に、ヘッダが見つからないエラーに遭遇する事です。(なので、nvccが見つからないにはおそらく遭遇しない)

NVCCでのコンパイルより前に、CXX側からCUDAのヘッダファイルを使おうとしています。 そのため CUDA_DIR だけを設定してもエラー内容に変化が無く気づきにくいのです。 cublas周り入れているはずなのに見つからないといわれて割と悩んでました。

pycaffeまわり

>>> import caffe
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
... (略)
  File "/home/user/venv_caffe/lib64/python3.5/site-packages/dateutil/rrule.py", line 55
    raise ValueError, "Can't create weekday with n == 0"
                    ^
SyntaxError: invalid syntax

requirements.txtで指定されているpython-dateutil>=1.4,<2がpython2用な模様。

python-dateutil - Labix

Ported to Python 3, by Brian Jones. If you need dateutil for Python 2.X, please continue using the 1.X series.

最新版ではpython3対応しているようなのでアップグレードしてみます。初期設定がpyhon2用なのでこうなってるのかなと信じて...

pip install python-dateutil --upgrade

今回は 2.6.0 が入りました。その後、改めてimportを実行すると何も起きない!つまりは問題無し、といことで無事インストールは終了です。

終わりに

どーにか入れられました!

個人的な都合でCentOS系でやりたかったので挑戦してみました。 公式でサポートされているUbuntu環境でやった方が無難かと思います。

何かの役に立ちますよーに。

雑多メモ

文章にまとめきれなかったやつ...

  • ドライバを入れて再起動したときにマウスカーソル動くようになった
  • akmod-nvidia は依存解決失敗で dkms-nvidia にした
  • cuDNNリポジトリから入れられた...
  • deviceQuery は cuda-samples をインストールで入る/usr/share/cuda/samples/1_Utilities/deviceQuery/
  • 多分不要だけれど試行錯誤で入れたパッケージ
    • redhat-rpm-config
    • cuda-cli-tools
    • nvidia-settings
    • atlascpp-devel
      • このatlascppは、途中まで必要なものとして書いていた。ふと dnf removeしてもビルドできたので他が原因だった?
  • CUDA_ARCHcode=sm_20sm_21 は警告出ていたので取り除いた
  • ビルドをやり直す時は make clean

書き換え差分

Makefile.config

--- Makefile.config.example  2016-12-05 03:11:35.958259593 +0900
+++ Makefile.config   2016-12-18 01:28:12.538826746 +0900
@@ -2,7 +2,7 @@
 # Contributions simplifying and improving our build system are welcome!

 # cuDNN acceleration switch (uncomment to build with cuDNN).
-# USE_CUDNN := 1
+USE_CUDNN := 1

 # CPU-only switch (uncomment to build without GPU support).
 # CPU_ONLY := 1
@@ -18,23 +18,21 @@
 # ALLOW_LMDB_NOLOCK := 1

 # Uncomment if you're using OpenCV 3
-# OPENCV_VERSION := 3
+OPENCV_VERSION := 3

 # To customize your choice of compiler, uncomment and set the following.
 # N.B. the default for Linux is g++ and the default for OSX is clang++
-# CUSTOM_CXX := g++
+CUSTOM_CXX := clang++

 # CUDA directory contains bin/ and lib/ directories that we need.
-CUDA_DIR := /usr/local/cuda
+#CUDA_DIR := /usr/local/cuda
 # On Ubuntu 14.04, if cuda tools are installed via
 # "sudo apt-get install nvidia-cuda-toolkit" then use this instead:
-# CUDA_DIR := /usr
+CUDA_DIR := /usr

 # CUDA architecture setting: going with all of them.
 # For CUDA < 6.0, comment the *_50 lines for compatibility.
-CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \
-      -gencode arch=compute_20,code=sm_21 \
-      -gencode arch=compute_30,code=sm_30 \
+CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \
        -gencode arch=compute_35,code=sm_35 \
        -gencode arch=compute_50,code=sm_50 \
        -gencode arch=compute_50,code=compute_50
@@ -48,7 +46,7 @@
 # Leave commented to accept the defaults for your choice of BLAS
 # (which should work)!
 # BLAS_INCLUDE := /path/to/your/blas
-# BLAS_LIB := /path/to/your/blas
+BLAS_LIB := /usr/lib64/atlas

 # Homebrew puts openblas in a directory that is not on the standard search path
 # BLAS_INCLUDE := $(shell brew --prefix openblas)/include
@@ -61,8 +59,8 @@

 # NOTE: this is required only if you will compile the python interface.
 # We need to be able to find Python.h and numpy/arrayobject.h.
-PYTHON_INCLUDE := /usr/include/python2.7 \
-      /usr/lib/python2.7/dist-packages/numpy/core/include
+# PYTHON_INCLUDE := /usr/include/python2.7 \
+#      /usr/lib/python2.7/dist-packages/numpy/core/include
 # Anaconda Python distribution is quite popular. Include path:
 # Verify anaconda location, sometimes it's in root.
 # ANACONDA_HOME := $(HOME)/anaconda
@@ -71,16 +69,17 @@
        # $(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include \

 # Uncomment to use Python 3 (default is Python 2)
-# PYTHON_LIBRARIES := boost_python3 python3.5m
-# PYTHON_INCLUDE := /usr/include/python3.5m \
-#                 /usr/lib/python3.5/dist-packages/numpy/core/include
+PYTHON_LIBRARIES := boost_python3 python3.5m
+VENV_HOME := $(HOME)/work/repos/caffe/venv_caffe
+PYTHON_INCLUDE := /usr/include/python3.5m \
+         $(VENV_HOME)/include

 # We need to be able to find libpythonX.X.so or .dylib.
-PYTHON_LIB := /usr/lib
+## PYTHON_LIB := /usr/lib
 # PYTHON_LIB := $(ANACONDA_HOME)/lib

 # Homebrew installs numpy in a non standard path (keg only)
-# PYTHON_INCLUDE += $(dir $(shell python -c 'import numpy.core; print(numpy.core.__file__)'))/include
+PYTHON_INCLUDE += $(dir $(shell python -c 'import numpy.core; print(numpy.core.__file__)'))/include
 # PYTHON_LIB += $(shell brew --prefix numpy)/lib

 # Uncomment to support layers written in Python (will link against Python libs)
@@ -88,6 +87,7 @@

 # Whatever else you find you need goes here.
 INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
+INCLUDE_DIRS += /usr/include/cuda
 LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib

 # If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependenciesf