2021年12月26日日曜日

Fedora 35でOpen3D(CUDA+TensorFlow)をビルドする

目的


Fedora 35 + CUDAの環境でOpen3Dをビルドできるようにしたい。


環境


2021.12.25時点の環境は以下。
  • Fedora 35 x86_64
  • gcc version 11.2.1 20211203 (Red Hat 11.2.1-7) (GCC) 
  • CUDA 11.5 + cuDNN v8.3.1



Fedora 35で発生するビルドエラー


Open3DはLinuxディストリビューションではUbuntuが公式の環境となっている。

このため、Fedora 35だと様々なエラーが発生する。
  • サポートするPythonバージョンが一致しない。
  • GCCバージョンによる(CUDA、C++14 vs C++17)ビルド、リンク時にエラーが発生。
  • 不足しているモジュールのインストールが必要。

今回はそれらを解決・回避しながら、v0.14.0で追加されたOpen3D for TensorBoardが動作するところまでやってみる。


事前の準備


  • Python3.9のインストール


Fedora 35のPythonは3.10が標準である。
Open3DはPython 3.9までをサポートのため、ビルド時にエラーが発生する。
このため、Open3Dではなく、Fedoraに3.9をインストールし、仮想環境で対応することとする。
Python3.9のパッケージをインストール後、virtualenvwrapperで仮想環境を作成する。

sudo dnf install python3.9
mkvirtualenv --python=python3.9 open3d_p39

以降、仮想環境で作業する。


GCC 11.1のビルド


Fedora 35の場合、Open3DとTensorFlowをCUDAを有効でビルドする場合、GCCのバージョンが問題となる。
前回のブログを参照。

CUDAのコンパイラーのために、GCC11.1をソースビルドしておく。
ビルドについては上記のブログを参照。


TensorFlow 2.5のビルド


Open3D v0.14.0では、TensorFlow v2.5を期待している。

おそらく、TensorFlow v2.7でもOKな気がするが、 v2.5.2をビルドして、インストールする。

ビルド方法は前回のブログと同様なので詳細は割愛。    
ただし、v2.5.2の場合、ビルド中にRuyでビルドエラーが発生してしまう。

external/ruy/ruy/block_map.cc: In function ‘void ruy::MakeBlockMap(int, int, int, int, int, int, int, int, const ruy::CpuCacheParams&, ruy::BlockMap*)’:
external/ruy/ruy/block_map.cc:395:25: error: ‘numeric_limits’ is not a member of ‘std’
  395 |   int best_score = std::numeric_limits<int>::min();
      |                         ^~~~~~~~~~~~~~
external/ruy/ruy/block_map.cc:395:40: error: expected primary-expression before ‘int’
  395 |   int best_score = std::numeric_limits<int>::min();
      |                                        ^~~
Target //tensorflow/tools/pip_package:build_pip_package failed to build

ビルドエラーが発生した後、該当のモジュール(bazelのキャッシュにある)のソースを修正して、再度ビルドする。

<Bazelのキャッシュディレクトリ>external/ruy/ruy/block_map.cc
にヘッダのインクルードを追加する。
詳細は以下を参照。

ビルド後、pipパッケージを作成し、インストールする。


Open3Dのビルド


さて、ここまできたので後はOpen3Dのビルド。


必要なパッケージのインストール(思いつくもの)


Open3D for TensorBoardを動作させるために必要なモジュールをインストールする。
  • yapfはpipパッケージの作成の際にないとエラーとなる。
  • nodejs、jupyter関連のモジュールはTensorBoard起動時にないとエラーとなる。

sudo dnf install nodejs
sudo npm install -g yarn
pip install yapf
pip install jupyter_packaging ipywidgets jupyterlab


ソースコードのCloneと修正


現時点(2021.12.26)のOpen3Dのコードのままだとビルドできない。

一番の問題は、CUDAのコンパイラーを指定するCMAKE_CUDA_HOST_COMPILERフラグが3rdpartyモジュールで指定されないことと、3rdpartyモジュールのfaissはCMAKE_CUDA_HOST_COMPILERフラグにCMAKE_CXX_COMPILERフラグを指定していることである。

このため、3rdpartyモジュールのビルド時にビルドエラーが発生する。

3rdpartyモジュールにもCMAKE_CUDA_HOST_COMPILERフラグを指定することと、faissのCMakeLists.txtにパッチを当てる。

forkリポジトリに上記を対応したブランチを用意した。

これをつかってビルドを行う。

git clone https://github.com/NobuoTsukamoto/Open3D.git
cd Open3D
git ckeckout fedora_cuda_build
cd ..
git clone https://github.com/isl-org/Open3D-ML.git
mkdir build
cd build


CMAKE


BUILD_TENSORFLOW_OPSを有効としてビルドするのだが、そのままビルドすると、pipパッケージの作成でエラーが発生してしまう。
  • https://zenn.dev/link/comments/50c45f4523bb90

これは、TensorFlowはC++14でビルド(std=gun++14)だが、Open3DはC++17(GCC11.2のデフォルト)でビルドしているため。
tf.load_op_libraryでopen3d_tf_ops.soをロードする際にundefined symbolが発生してしまう。
詳細は以下のissueも参照。

このため、CMAKE_CXX_STANDARD=14を指定することで解決する。

上記の2つのポイントは、
  • CMAKE_CUDA_HOST_COMPILERでCUDAのコンパイラー(GCC 11.1)を指定
  • CMAKE_CXX_STANDARDでC++14を指定
である。

cmake ../Open3D \
  -DBUILD_TENSORFLOW_OPS=ON \
  -DBUILD_BENCHMARKS=ON \
  -DBUILD_CUDA_MODULE=ON \
  -DBUNDLE_OPEN3D_ML=ON \
  -DBUILD_JUPYTER_EXTENSION=ON \
  -DBUILD_WEBRTC=ON \
  -DOPEN3D_ML_ROOT=/home/xxxxx/WorkSpace/open3d/Open3D-ML/ \
  -DCMAKE_CXX_STANDARD=14 \
  -DCMAKE_CUDA_HOST_COMPILER=/home/xxxxx/gcc/11.1/bin/gcc


ビルド


あとは、ビルドしてpipパッケージを作成、インストールする。

make -j$(nproc)
sudo make install
make pip-package
pip install lib/python_package/pip_package/open3d-0.14.1+3d75e332f-cp39-cp39-manylinux_2_34_x86_64.whl


ビルド後の確認


Open3D for TensorBoardのサンプルの通りやってみる。

cd ../Open3D
python examples/python/gui/tensorboard_tensorflow.py small_scale
tensorboard --logdir demo_logs/tf

リンクを開くとTensorBoardが起動する。



OK!!!!!!!!!

2021年12月23日木曜日

Fedora 35 の GCC 11.2.1 20211203 で Tensorflow 2.7(CUDA11.5 cuDNN8.3.1)をビルドする

目的



その後、Fedora 35のGCCのバージョンがアップデートした。
  • GCC 11.2.1 20210728 → GCC 11.2.1 20211203

この変更、特にlibstdc++のヘッダーファイルの変更が影響してCUDA関連のビルドが失敗することがわかった。

注)
もちろんCUDAのGCCサポートはFedora 34のGCC 11(おそらく11.1)となっている。

このため、Fedora 35のGCC 11.2はサポート対象外であり、前回ビルドできたことは奇跡だったのである。
(そうでも、ちょっといきなりビルドできなくなるのはひどいが、、、)


GCC 11.2.1 20211203でのCUDA関連のビルドエラー


Fedora 35 の GCC 11.2.1 20211203でビルドすると下記の記事でまとめたが、ビルドエラーが発生する。
なお、これはTensorFlowに限らず、CUDA関連のビルドはすべて失敗すると思われる。


環境


2021.12.18時点の環境は以下。
  • Fedora 35 x86_64
  • Python 3.10.0 (default, Oct  4 2021, 00:00:00) [GCC 11.2.1 20210728 (Red Hat 11.2.1-1)] on linux
  • gcc version 11.2.1 20211203 (Red Hat 11.2.1-7) (GCC) 
  • CUDA 11.5 + cuDNN v8.3.1


事前の準備


対応の方針としては、いつものごとくCUDA用のGCCを別途用意する。
これは過去も同様。今回はGCC11.1を用意する。

GCC 11.1のビルド


ソースのダウンロード&変更


GCC11.1のソースをダウンロードする。

wget https://ftp.gnu.org/gnu/gcc/gcc-11.1.0/gcc-11.1.0.tar.gz
tar xf gcc-11.1.0.tar.gz
cd gcc-11.1.0/


そのままではビルドエラーになってしまうため、コードの一部を変更する。
エラーの内容、変更箇所は以下のGentooのバクレポートを参照。


ビルド


これも今までの通り。
以下のビルドオプションでビルドを行う。

./contrib/download_prerequisites
mkdir build
../configure \
  --enable-bootstrap \
  --enable-languages=c,c++ \
  --prefix=/home/xxxx/gcc/11.1 \
  --enable-shared \
  --enable-threads=posix \
  --enable-checking=release \
  --disable-multilib \
  --with-system-zlib \
  --enable-__cxa_atexit \
  --disable-libunwind-exceptions \
  --enable-gnu-unique-object \
  --enable-linker-build-id \
  --with-gcc-major-version-only \
  --with-linker-hash-style=gnu \
  --enable-plugin \
  --enable-initfini-array \
  --with-isl \
  --enable-libmpx \
  --enable-gnu-indirect-function \
  --build=x86_64-redhat-linux
make -j$(nproc)
make install


ビルド後の設定


ビルド後は、specsファイルを作成、設定する。

/home/xxxx/gcc/11.1/bin/gcc -dumpspecs > specs
$ vi specs

# before
*link_libgcc:
%D

# after
*link_libgcc:
%{!static:%{!static-libgcc:-rpath /home/xxxx/gcc/11.1/lib64/}} %D

$ mv specs /home/xxxx/gcc/11.1/lib/gcc/x86_64-redhat-linux/11/


TensorFlowのビルド


あとは、いつもどおりビルドすればOK。


Configure


configureではCUDAのコンパイラーにGCC11.1を指定する。

 ./configure 
You have bazel 3.7.2 installed.
Please specify the location of python. [Default is /home/xxxx/.virtualenvs/tf2.7/bin/python3]: 


Found possible Python library paths:
  /home/xxxx/.virtualenvs/tf2.7/lib/python3.10/site-packages
  /home/xxxx/.virtualenvs/tf2.7/lib64/python3.10/site-packages
Please input the desired Python library path to use.  Default is [/home/xxxx/.virtualenvs/tf2.7/lib/python3.10/site-packages]

Do you wish to build TensorFlow with ROCm support? [y/N]: 
No ROCm support will be enabled for TensorFlow.

Do you wish to build TensorFlow with CUDA support? [y/N]: y
CUDA support will be enabled for TensorFlow.

Do you wish to build TensorFlow with TensorRT support? [y/N]: 
No TensorRT support will be enabled for TensorFlow.

Found CUDA 11.5 in:
    /usr/local/cuda-11.5/targets/x86_64-linux/lib
    /usr/local/cuda-11.5/targets/x86_64-linux/include
Found cuDNN 8 in:
    /usr/local/cuda-11.5/targets/x86_64-linux/lib
    /usr/local/cuda-11.5/targets/x86_64-linux/include


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. Each capability can be specified as "x.y" or "compute_xy" to include both virtual and binary GPU code, or as "sm_xy" to only include the binary code.
Please note that each additional compute capability significantly increases your build time and binary size, and that TensorFlow only supports compute capabilities >= 3.5 [Default is: 6.1]: 


Do you want to use clang as CUDA compiler? [y/N]:                             
nvcc will be used as CUDA compiler.

Please specify which gcc should be used by nvcc as the host compiler. [Default is /usr/bin/gcc]: /home/xxxx/gcc/11.1/bin/gcc


Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is -Wno-sign-compare]: 


Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: 
Not configuring the WORKSPACE for Android builds.

Preconfigured Bazel build configs. You can use any of the below by adding "--config=<>" to your build command. See .bazelrc for more details.
	--config=mkl         	# Build with MKL support.
	--config=mkl_aarch64 	# Build with oneDNN and Compute Library for the Arm Architecture (ACL).
	--config=monolithic  	# Config for mostly static monolithic build.
	--config=numa        	# Build with NUMA support.
	--config=dynamic_kernels	# (Experimental) Build kernels into separate shared objects.
	--config=v1          	# Build with TensorFlow 1 API instead of TF 2 API.
Preconfigured Bazel build configs to DISABLE default on features:
	--config=nogcp       	# Disable GCP support.
	--config=nonccl      	# Disable NVIDIA NCCL support.
Configuration finished


ビルド


あとはビルド。しばし待つ。

bazel build \
  --config=cuda \
  --config=v2 \
  --config=nonccl \
  --config=opt \
  //tensorflow/tools/pip_package:build_pip_package
./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
pip install /tmp/tensorflow_pkg/tensorflow-2.7.0-cp310-cp310-linux_x86_64.whl


2021年12月10日金曜日

Fedora 35 でTensorflow 2.7(CUDA11.5 cuDNN8.3.1)をビルドする

目的


Tensorflowの2.7をFedora 35でソースビルドする。


環境


  • SW
    • Fedora 35 x86_64
    • Python 3.10.0
    • GCC 11.2.1 20210728
    • CUDA 11.5 + cuDNN v8.3.1
  • HW
    • CPU AMD Ryzen 7 1700
    • GPU GeForce GTX 1070


事前の準備


CUDA、cuDNNのインストール


これは、以前と同様。
RPM FusionからCUDAを、NVIDIAよりcuDNNをそれぞれインストールする。

BAZELのインストール


FedoraのCOPR repositoryからインストールが可能。
3.x系と4.x系が選択可能なので3.x系をインストールする。



TensorFlow v2.7(後述のTensorFlow I/Oも含めて)のビルドにはBazel v3.7.2が必要(4.x系の場合、TensorFlow I/Oのビルドでエラーとなるため)。
しかし、現時点(2021.12.08)ではバージョンがv3.7.1。v3.7.2をソースコードからビルドするにはGCCのバージョンダウン(ソースビルド)が必要になる(Fedora 35のGCC11ではビルドができないため)。今回はv3.7.1で押し通すことにする。


TensorFlow I/Oのビルド


TensorFlow v2.7をビルド後、wheelパッケージをインストールする際にtensorflow_io_gcs_filesystemとtensorflow_ioのインストールを要求される(依存関係)。

しかしながら、Python3.10のパッケージは用意されていないためインストールできない。そこで、TensorFlow I/Oをビルド、io、io_gcs_filesystemのwheelパッケージも作成する。

なお、TensorFlow I/OのビルドにはTensorFlow v2.7が必要なため、デッドロックしてしまう。。。


なんでだよ。

さらにBazelが利用するモジュールがPython3.10に対応していないため、ビルドでエラーが発生してしまう。

ここで、TensorFlow I/Oのビルドは2つの手順に分かれている(TensorFlow I/Oのビルド手順を参照)。
  • Bazelを使ったビルド(共有ライブラリの作成)
  • Wheelパッケージの作成

    このため、ビルドはPython3.9環境で行い、パッケージ作成時にPython3.10環境に切り替えて行うこととする。Python3.9環境であれば、TensorFlowも公式のパッケージが提供されているのでデッドロックも回避できる。
    TensorFlow I/OのGithub Actionがこのような手順になっていたので参考にした。

    (じゃあ、Python3.9環境でよくない?というのは置いておく)


    まず、Python3.9をインストールし、virtualenvwrapper(virtualenv)でビルド用環境を作成し、必要なモジュールをインストールしておく。



    TensorFlow I/Oのリポジトリをクローンする。
    今回はPython3.10ビルドに対応となっていたmainブランチとする(でも対応していないけど、、、)。



    先程述べたBazelのバージョンが一致しない問題があるので、.bazelversionの内容を変更しておく。



    ビルド。


    wheelパッケージの作成。
    setup.pyがpython3.10をサポートしていないので修正。



    TensorFlowをインストールするためのPython3.10環境を作成、切り替えて、wheelパッケージを作成。できたパッケージをインストール。



    TensorFlowのビルド


    さて、あとは本題。

    TensorFlowのリポジトリをクローンしてv2.7.0をチェックアウト。
    Python3.10ではビルドが失敗するため、以下のコミットをcherry-pickする。



    Bazel3.7.1でビルドするために.bazelversionを修正。



    configureの実行。
    ccacheをインストールしているとビルドに失敗するため、host compilerにはGCCを指定する。



    ビルド。あとは待つだけ。



    ビルドが完了すれば、wheelパッケージを作成してインストールする!



    確認


    • tf.__version__が2.7であること。
    • GPUデバイスを認識していること



    OK〜✌

    2021年12月5日日曜日

    2021.11.23の釣行

     あたらしいロッドを買いました。

    カワセミラプソディの2021年モデル。

    ということで、初めて通年エリアに向かいました。

    ニジマスがターゲットです。

    今にも降り出しそう(と言うか、お昼前から降ってきた。。。)


    でもって、入魂!!!



    40オーバー。よく引いた。

    長靴釣行だったので、ネットインが大変だった。バレなくてよかった〜



    カワセミラプソディ、扱いやすくていいね!

    来シーズンが楽しみ!!