TensorFlowをDockerコンテナ上で動作させるために、M1 MacからWindowsに移行した

こんにちは。永和システムマネジメント FDPメンバの坂部です。

M1 MacでTensorFlowをDockerコンテナ上で動作させるときに、色々ハマり、結局Windowsに移行したので、その経緯をお話しします。

前提

  • チームメンバ4人中、3人はWindows。わたしだけM1 Mac。
  • VS Code Remote Developmentを介して、ローカルコンテナ上で開発。Dockerfileもチームで共有。
  • どうしてもTensorFlowを動作させたい。代替ライブラリは検討せず。

環境

  • Python : 3.9.7
  • TensorFlow : 2.7.0

TensorFlowのインストールでエラー

まずは、TensorFlowの公式ページを読んで、Pythonパッケージとして普通にインストールできることを知り、インストールを試みました。

ちなみに、poetryを使っています。

poetry add tensorflow

すると、RuntimeErrorが…

Skipping virtualenv creation, as specified in config file.
Using version ^2.7.0 for tensorflow

Updating dependencies
Resolving dependencies... (55.7s)

Writing lock file

Package operations: 31 installs, 1 update, 0 removals

  • Updating charset-normalizer (2.0.7 -> 2.0.9)
  • Installing pyasn1 (0.4.8)
  • Installing cachetools (4.2.4)
  • Installing oauthlib (3.1.1)
  • Installing pyasn1-modules (0.2.8)
  • Installing rsa (4.8)
  • Installing zipp (3.6.0)
  • Installing google-auth (2.3.3)
  • Installing importlib-metadata (4.10.0)
  • Installing requests-oauthlib (1.3.0)
  • Installing absl-py (1.0.0)
  • Installing google-auth-oauthlib (0.4.6)
  • Installing grpcio (1.43.0)
  • Installing markdown (3.3.6)
  • Installing protobuf (3.19.1)
  • Installing tensorboard-data-server (0.6.1)
  • Installing tensorboard-plugin-wit (1.8.0)
  • Installing werkzeug (2.0.2)
  • Installing astunparse (1.6.3)
  • Installing flatbuffers (2.0)
  • Installing gast (0.4.0)
  • Installing google-pasta (0.2.0)
  • Installing h5py (3.6.0)
  • Installing keras (2.7.0)
  • Installing keras-preprocessing (1.1.2)
  • Installing libclang (12.0.0)
  • Installing opt-einsum (3.3.0)
  • Installing tensorboard (2.7.0)
  • Installing tensorflow-estimator (2.7.0)
  • Installing tensorflow-io-gcs-filesystem (0.23.1): Failed

  RuntimeError

  Unable to find installation candidates for tensorflow-io-gcs-filesystem (0.23.1)

  at /usr/local/lib/python3.9/site-packages/poetry/installation/chooser.py:72 in choose_for
       68│ 
       69│             links.append(link)
       70│ 
       71│         if not links:
    →  72│             raise RuntimeError(
       73│                 "Unable to find installation candidates for {}".format(package)
       74│             )
       75│ 
       76│         # Get the best link

  • Installing termcolor (1.1.0)

Failed to add packages, reverting the pyproject.toml file to its original content.

しかし、Windowsユーザのチームメンバに確認してもらうと、Windowsマシンではインストールが成功するとのこと。

TensorFlowのPythonパッケージ一覧を確認すると、x86_64の記述しかないので、どうやらARM64に対応していないようです。

ちなみに、Pythonパッケージ以外に、Dockerイメージでの提供もあるのですが、こちらもAMD64向けのイメージしかありません。

AMD64イメージを使ってみる

では、コンテナイメージをARM64じゃないものにすればよいのでは、と考えました。

実は、今までDockerイメージのアーキテクチャについて気にしたことはありませんでした。今回、勉強する良い機会と捉えて、軽く調べることにしました。

Dockerイメージのアーキテクチャは、Dockerfileで指定できるようです。

FROM --platform=linux/amd64 python:3.9.7

指定しない場合は、Dockerを実行しているマシンのOSやアーキテクチャに合うアーキテクチャが選択されます。同じpython:3.9.7を指定しても、マルチアーキテクチャという仕組みで、それぞれのアーキテクチャ用のイメージが選択されます。

明示的にlinux/amd64を指定してコンテナをビルドし、poetry add tensorflowしてみました。すると、インストールに成功しました。

やったーと喜んだも束の間、実際にPythonでTensorFlowをimportしようとすると、下記のエラーが発生しました。

The TensorFlow library was compiled to use AVX instructions, but these aren't available on your machine.
qemu: uncaught target signal 6 (Aborted) - core dumped

QEMUは、Docker Desktop for Apple siliconで使われているエミュレータです。

下記Issueをざっと眺めましたが、AVXという拡張命令セットがQEMUでサポートされていないことが原因のようです。

Docker Desktop for Apple siliconについてのドキュメントを読んでいると、“best effort”という馴染みのある単語が目に入ってきました。

Not all images are available for ARM64 architecture. You can add --platform linux/amd64 to run an Intel image under emulation. In particular, the mysql image is not available for ARM64. You can work around this issue by using a mariadb image.

However, attempts to run Intel-based containers on Apple silicon machines under emulation can crash as qemu sometimes fails to run the container. In addition, filesystem change notification APIs (inotify) do not work under qemu emulation. Even when the containers do run correctly under emulation, they will be slower and use more memory than the native equivalent.

In summary, running Intel-based containers on Arm-based machines should be regarded as “best effort” only. We recommend running arm64 containers on Apple silicon machines whenever possible, and encouraging container authors to produce arm64, or multi-arch, versions of their containers. We expect this issue to become less common over time, as more and more images are rebuilt supporting multiple architectures.

https://docs.docker.com/desktop/mac/apple-silicon/#known-issues より

どうやら、ARM64以外のアーキテクチャのイメージを利用することは可能ですが、エミュレーションは完全じゃないようです。

M1 MacでTensorFlowを動作させたいだけなら

M1 MacでTensorFlowを動作させたいだけなら、TensorFlowをARM64向けにビルドすることで実現できます。

自前でビルドするのは、考慮事項が多く大変ですが、先駆者がARM64向けのDockerイメージを配布してくれています。

ただ、同イメージはAMD64には対応しておらず、チームでDockerfileを共有しているわたしたちには扱いにくいです。

また、ARM64向けのイメージビルドだけでも考慮することが多いので、ARM64 / AMD64両対応のイメージを自前でビルドすることは現実的でないと判断しました。

色々調べたが、Intelマシンに移行するのが手っ取り早そう

他にもLimaでIntel on ARMすればいけるのでは?と思い試したりしましたが、だめでした。

調査が長引いてきて、これ以上M1 Macでの動作に挑戦するより、Windowsに移行する方が適切と判断しました。

MacでもIntel Macなら問題ないと思いますが、既にチームでWindowsが普及していたこと、社内でWindowsの方が調達しやすそうなことから、Windowsを選択しました。

今後の動向

ARM64向けのPythonパッケージを配布して欲しいというIssueは存在します。

https://github.com/tensorflow/tensorflow/issues/52973

わたしはWindowsに慣れておらず、Macに戻りたいなーと思っているので、今後も関連Issueに注目していきたいです。

参考