ANN ライブラリの Annoy で build index する時に Illegal Instruction Error が発生した
Table of Contents
Annoy という Spotify が開発している Python 製の ANN (Approximate Nearest Neighbors) のライブラリがあり,それを使ってレコメンドアイテムの類似度を計算する機会があったのだが,コンテナ化したものを Vertex AI Pipelines 上で動かしていたところ,Fatal Python error: Illegal instruction
というエラーが発生して困っていたので,今回はこのエラーの対処方法について書いていく.
※ Annoy については,こちらの ZOZO さんの記事が詳しく解説してくれているので,ここでは説明は割愛する.
docker build 時の環境による問題?
発生した事象
Annoy のライブラリを含んだ Docker イメージを作り,それを元に作成したコンポーネントを機械学習パイプラインである Vertex AI Pipelines で動かしたところ,Fatal Python error: Illegal instruction
というエラーが発生した.これは具体的には,AnnoyIndex
を構築する際に発生している.
※ Annoy を含む Python ライブラリは poetry で管理し,Dockerfile 内で poetry install
している.
エラー原因
今回の問題は,Docker コンテナのイメージをビルドする時に指定するオプションが原因だった.
ローカル環境は Apple M1 Max (ARM アーキテクチャ) で開発していたため,イメージ作成時に以下のオプションを指定してビルドしていた.
docker build --platform linux/amd64 -t sample-recsys:latest -f ./Dockerfile .
AMD 環境でも動くように --platform
フラグにターゲットプラットフォームである linux/amd64
を指定してビルドしていた.このビルドしたイメージを GCP の Artifact Registry にプッシュし,そのイメージを使って Vertex AI Pipelines で各コンポーネントの検証を行っていた.
一方で,--platform
フラグを付けずに M1 Mac からビルドしたイメージを使った場合には,exec format error
というエラーが発生する.
検証時には,ローカル環境から直接イメージをビルド & プッシュし,そのイメージを使ったコンポーネントを Vertex AI Pipelines 上で動かして検証を行っていた.その際に使用していたスクリプトをそのまま GitHub Actions での CI/CD 構築時に使用したことで,今回の Fatal Python error: Illegal instruction
という事象が発生することになる.
Illegal instruction
というエラーが発生するという事象はいくつか Issue が上がっていた.
- Error: illegal hardware instruction (core dumped) #492
- "Illegal instruction: 4" when trying to build index (Python 3.7, Annoy version 1.17.0, macOS 10.14.6) #513
--platform
フラグを付けてイメージをビルドしても問題ないライブラリも多数あるが,Annoy では linux/amd64
を指定したのを GitHub Actions の Runner (ubuntu-latest) で動かしたのがどうも上手く行かなかったみたい...
解決方法
僕の例では,Initializing an AnnoyIndex crashes on AMD processors #472 の Issue に記載されている方法で解決することができた.
Annoy のライブラリをインストールする際に,コンパイルパラメータである ANNOY_COMPILER_ARGS
を Dockerfile 内に環境変数として指定することで解決できる.annoy/setup.py を見ると良いかもしれない.
ENV ANNOY_COMPILER_ARGS -D_CRT_SECURE_NO_WARNINGS,-DANNOYLIB_MULTITHREADED_BUILD,-mtune=native
この環境変数を Dockerfile にセットすると,--platform
に linux/amd64
を付け Docker イメージを GitHub Actions 経由でビルドしたものを Vertex AI Pipelines で使用しても,エラー無く処理が完了した.
あとは,そもそもこれはローカルの M1 Mac と GitHub Actions の両方で同一のスクリプトを使用したいが為に行っている対応策なので,スクリプトを別々にすれば,GitHub Actions でビルドする際には,上記の ANNOY_COMPILER_ARGS
を設定することなく,シンプルに以下のビルドコマンドだけでいける.
docker build -t sample-recsys:latest -f ./Dockerfile .
また,,--platform
のオプションを付けてビルドすると時間が余計にかかるので,無駄なものは付けない方が良さそうに思う.
今回は思いもよらないエラーで悩んでいたので,こうして無事?エラーの原因と解決策が分かって良かった.全然このことに気づかなかったので,Annoy をやめて Faiss を使用することも考えたりしていた.
コンテナイメージをビルドする際のローカルとプロダクション適用時のマシンスペックが違うことも考えた上で,再現性を意識したコードを書かなければと改めて感じたので,良い教訓となった.