🚀

opencv-pythonを並列ビルドしてビルド時間を5分の1にした

2024/12/18に公開

はじめに

Pythonで画像処理をする場合、pipでインストールするopencv-python(またはopencv-python-headless)パッケージを使うことが多いかと思います。
opencv-pythonパッケージにはOpenCVのビルド済みバイナリが含まれているため、別途OpenCVをインストールする必要もなく、簡単にOpenCVを使うことができます。

ただ、opencv-pythonパッケージに含まれているビルド済みバイナリは、ライセンスの関係でH.264に対応していないなど、H.264対応やGPU(CUDA)対応のためにopencv-pythonパッケージを独自ビルドすることも少なくありません。
そのビルドにえらく時間が掛かった(約25分)ため、並列ビルドする方法を調べてみた、という話です。

結論

結論から言えばMAKEFLAGS="-j$(nproc)" python -m build --wheelと、MAKEFLAGS="-j$(nproc)"を付加するだけで並列ビルドされました。
以下に示す具体例の場合、これだけでビルド時間が約25分から約5分へ、5分の1になりました。もちろんビルド時間、短縮の度合いは環境依存です。

このコマンドはopencv-pythonパッケージに限らず、適切に依存関係が書かれたMakefileがあり、makeコマンドを使っているパッケージに適用できます。(CMakeを使ってMakefileを生成している場合も含む)
なお、$(nproc)の部分は実行するマシンのCPUコア数になるため、16コアマシンではMAKEFLAGS="-j16"として展開されます。
ここではすべてのCPUコアを使用してビルドすることを想定していますが、一部のCPUコアだけを使いたい場合は適宜調整してください。

MAKEFLAGSの他にもCMAKE_ARGSCMAKE_MAKE_PROGRAMCMAKE_BUILD_PARALLEL_LEVELなども使ってみましたがビルドエラーとなり、問題を解決することはできませんでした。

具体例: H.264対応のopencv-python-headlessパッケージをビルドする

具体例として、H.264対応のopencv-python-headlessパッケージ(バージョン4.10.0.84)をビルドする例を示します。
今回はpython:3.11-slimイメージを使い、Dockerコンテナ上でビルドしました。

なお、headless版はGUI関係を含まないため、依存関係が少なく、ビルドされたパッケージも小さくなります。

docker run -it --rm python:3.11-slim bash
# 必要なDebianパッケージをインストールする
apt update
apt install --yes --no-install-recommends build-essential cmake libavcodec-dev libavformat-dev libturbojpeg0-dev libopencv-dev libopenexr-dev libpng-dev libssl-dev libswscale-dev libtiff-dev libwebp-dev libx264-dev

# 必要なPythonパッケージをインストールする
python -m pip install build==1.2.2.post1 packaging==24.2 pyproject_hooks==1.2.0

# opencv-python-headlessパッケージをソースからビルドする
mkdir /tmp/opencv
cd /tmp/opencv/
python -m pip download --no-binary opencv-python-headless opencv-python-headless==4.10.0.84
tar zxfv opencv-python-headless-4.10.0.84.tar.gz
cd opencv-python-headless-4.10.0.84/
MAKEFLAGS="-j$(nproc)" python -m build --wheel

# ビルドしたopencv-python-headlessパッケージをインストールする
python -m pip install dist/opencv_python_headless-4.10.0.84-cp311-cp311-linux_x86_64.whl

おわりに

Pythonパッケージの並列ビルドについて調べる中で、以下のコマンド、環境変数を初めて使いました。

  • python -m pip downloadコマンド
  • python -m build --wheelコマンド
  • MAKEFLAGS環境変数

いかんせん初めて使ったので誤りなどがあるかもしれません。その時は優しく教えて頂けると幸いです。

Discussion