はじめに
ある共同研究プロジェクトの解析を、NVIDIA GPUを積んだWindowsのデスクトップPCで回していました。ところが解析を走らせた瞬間に電源が落ち、そのまま起動しなくなってしまいました。原因の切り分けは別途進めるとして、研究は止められない。手元にはもう1台、**MacBook Pro 14インチ(Apple Silicon, 64GBユニファイドメモリ, 20コアGPU)**があります。
「MacでもGPU使えるでしょ、同じコマンドで動くはず」——最初はそう思っていました。ところが、Apple SiliconはNVIDIAとは"前提"がかなり違います。この記事は、その違いに戸惑いながら環境を組み直した作業ログです。論文の中身には一切触れず、環境構築の技術的な部分だけを、初心者にも分かるように、でも上級者が読んでも「あるある」と頷ける粒度でまとめます。
結論を先に言うと、Apple Siliconでは「全部ネイティブで組む」のが基本です。理由も含めて順に説明します。
1. まず大前提:NVIDIA と Apple Silicon は別世界
CUDA が無い
NVIDIA GPUでの機械学習は、ほぼ例外なく CUDA という土台の上で動いています。PyTorchで --device cuda と書けばGPUを使う、あの世界です。
Apple SiliconにはCUDAがありません。代わりに MPS(Metal Performance Shaders) という、AppleのGPUを叩くための仕組みを使います。PyTorchは近年MPSに対応しているので、コードのなかで cuda と書いていた部分を mps に変えるのが基本になります。
import torch
print(torch.backends.mps.is_available()) # True ならGPUが使える
ユニファイドメモリという武器
NVIDIAでは「GPUのVRAM」と「PCのRAM」は別物で、VRAMの容量(例:24GB)が大きなモデルを動かせるかの上限でした。
Apple Siliconは **CPUとGPUが同じメモリを共有する「ユニファイドメモリ」**です。私のMacは64GB。この64GBを、CPUもGPUも一緒に使えます。大きなモデルを載せやすいという点では、むしろ強みになります。
Neural Engine は今回は主役ではない
Appleには推論に特化した「Neural Engine」もありますが、PyTorchの一般的な学習・推論から直接ガンガン使うものではありません。今回はMPS(GPU)が主役、と考えておけば十分です。
⚠️ 一番ハマる罠:Mac の Docker は GPU を使えない
これが最大の落とし穴でした。
WindowsのデスクトップではDocker(正確にはWSL2+Docker Desktop)でコンテナからNVIDIA GPUを使う構成にしていました。再現性が高く、環境が汚れないので気に入っていました。
同じ感覚でMacでもDockerを使おうとすると、コンテナの中からApple GPU(MPS)にアクセスできません。Mac上のDockerはLinux仮想マシンの中でコンテナを動かす都合で、AppleのGPUが見えないのです。つまりDockerで動かすとCPUオンリーになり、せっかくのGPUが遊びます。
→ Macでは、Dockerを使わず、macOSに直接(ネイティブに)Python環境を作る。これが鉄則です。
2. 環境構築:ネイティブvenvで組む
用意するもの
- VSCode(エディタ兼ターミナル)
- Python 3.10〜3.12 系(Homebrewやpython.orgのもの推奨。OS標準のPythonは避けると無難)
- git(Xcode Command Line Tools に含まれます)
Command Line Toolsが無ければ、ターミナルで:
xcode-select --install
仮想環境を作る(初心者はここ大事)
システム全体にライブラリを入れると、プロジェクトごとにバージョンが衝突して事故ります。**プロジェクト専用の箱(仮想環境)**を作りましょう。
python3 -m venv ~/ml-env # 箱を作る
source ~/ml-env/bin/activate # 箱に入る(プロンプト頭に (ml-env) が付く)
pip install -U pip
ライブラリを入れる
pip install torch numpy pandas scipy matplotlib biopython requests
macOS版のPyTorchは標準でMPS対応なので、CUDA用の特別なインデックス指定は不要です。ここはWindows/Linuxより楽なポイント。
3. GitHubからリポジトリをMacBookに取ってくる
VSCodeでフォルダを開き、内蔵ターミナル(Ctrl+@)で作業します。
git clone https://github.com/ユーザー名/リポジトリ名.git
cd リポジトリ名
git checkout 作業ブランチ名
プライベートリポジトリの認証
公開リポジトリならこれで終わりですが、プライベートリポジトリはログインを求められます。GitHubはパスワード認証を廃止しているので、次のどれかを使います。
-
GitHub CLI(一番ラク)
brew install gh gh auth login # 画面の指示に従ってブラウザでログイン -
Personal Access Token (PAT)
GitHubの Settings → Developer settings → Personal access tokens でトークンを発行し、git clone時のパスワード欄にそのトークンを貼る。 -
macOSキーチェーン連携(一度通せば以後は自動)
git config --global credential.helper osxkeychain
2回目以降の更新
最新を取り込むときは、そのフォルダで:
git pull origin 作業ブランチ名
これで「他の環境で更新したコード」をMacに反映できます。逆に、Macで出した結果を共有したいときは git add → git commit → git push で戻します。環境をまたいでも、gitが1本の背骨になるわけです。
4. Apple GPU(MPS)で実行する
疎通確認
まず、GPUが見えているかを必ず確認します。
python -c "import torch; print('MPS:', torch.backends.mps.is_available())"
# -> MPS: True
実行するとき:--device mps と「フォールバック」
自作スクリプトやライブラリで、デバイス指定を cuda → mps に変えます。加えて、MPSがまだ対応していない演算にぶつかったとき自動でCPUに逃がすため、環境変数を1つ付けます。
export PYTORCH_ENABLE_MPS_FALLBACK=1
python your_script.py --device mps ...
この PYTORCH_ENABLE_MPS_FALLBACK=1 が地味に重要です。これが無いと、未対応オペレーションに当たった瞬間にエラーで止まります。付けておけば、その部分だけCPUで計算して先に進みます(その分だけ遅くはなります)。
5. ハマりどころ(中級〜上級)
実際に動かして遭遇した/よくある落とし穴を、正直に並べます。
(1) ライブラリのバージョン地雷
「最新を入れれば安心」は逆のことがあります。実際、あるライブラリの最新メジャーバージョンが「PyTorch 2.5以上が必要」と要求し、こちらのPyTorchが2.3系だったために、GPUを"無し"と誤判定して機能が丸ごと無効化される、という事故に遭いました。
対処はバージョンを固定すること。例:
pip install "some-library<5" # メジャーを1つ下げて安定版に寄せる
再現性のためにも、動いた組み合わせを pip freeze > requirements.txt で保存しておくと、後で自分と共同研究者を救います。
(2) fair-esm と esm のような"名前かぶり"
パッケージによっては、別物なのに同じimport名を使うものがあります(例:あるモデル系の旧実装と新実装)。両方を同じ環境に入れると衝突します。
→ 用途ごとに仮想環境を分けるのが安全。~/ml-env-A と ~/ml-env-B のように箱を2つ作れば、衝突は原理的に起きません。
(3) float16 / bfloat16 の相性
省メモリのために半精度(fp16/bf16)を使うと速くなりますが、MPSでは一部の型・演算がまだ不安定なことがあります。まずは通常精度(fp32)で「動く」ことを確認 → 余裕が出たら半精度を試す、の順番が安全です。
(4) CPUフォールバックが遅すぎる問題
PYTORCH_ENABLE_MPS_FALLBACK=1は便利ですが、重い演算がCPUに落ちると一気に遅くなります。「GPUのはずなのに遅い」と感じたら、どの演算がCPUに落ちているかを疑い、そこだけ別実装・別ライブラリに替える、あるいは後述のCPU/クラウド併用に切り替えます。
(5) メモリの使いすぎ
ユニファイドメモリは強力ですが、GPUに割り当てすぎるとシステム全体が重くなることがあります。バッチサイズを下げる、長い入力は分割する(chunk)、といった基本の省メモリ手当ては、NVIDIA時代と同じく有効です。
6. 「Apple Siliconだと厳しい」もの(正直な話)
万能ではありません。次のようなものは、素直に別手段を取った方が早いです。
- CUDA専用のコンパイル拡張が必要なライブラリ:ビルドで詰まりがち。→ 同等機能の純PyTorch実装やHugging Face経由の実装に置き換える。
- 重い構造予測などGPUをフルに使う処理:MPSで不安定ならCPU実行(64GBメモリが効く。遅いが確実)や、公開APIの利用に切り替える。
- Docker内でGPUを使いたい:前述のとおりMac不可。→ ネイティブ実行にする。
- どうしてもNVIDIA前提のもの:クラウドGPU(時間課金)を併用。ローカルは前処理・可視化・軽い推論、重い所だけクラウド、という分業が現実的。
要は「MacでできることはMacで、無理な所だけ外に出す」というハイブリッドが、消耗しないコツです。
7. 共同研究として運用するコツ
個人の実験ノートで終わらせず、チームで再現できるようにする観点も大事でした。
-
環境を固定:
requirements.txt(またはlockファイル)で「動いた組み合わせ」を残す。半年後の自分が一番助かります。 -
結果はgitで共有:小さな表・図はコミットして共有。大きな中間ファイルは
.gitignoreで外し、必要なら別ストレージへ。 - 環境をまたいで結果を突き合わせる:同じ入力・同じseedなら、Windows(NVIDIA)とMac(MPS)で結果が一致するはず。一致を確認できれば、「Mac環境が正しく組めている」証明になり、安心して使えます(浮動小数点の微小差は許容範囲を決めておく)。
- 手順書化:今回のように環境が変わっても慌てないよう、セットアップ手順をREADMEやdocsに残す。壊れてから書くのではなく、動いたその日に書くのがベスト。
まとめ
デスクトップのGPUが壊れるという突発事故から始まりましたが、結果的に「Apple Siliconで機械学習環境を組む」という良い学びになりました。要点を1枚に:
-
CUDAは無い。MPSを使う(
--device mps+PYTORCH_ENABLE_MPS_FALLBACK=1)。 - ユニファイドメモリ(64GB)は大きなモデルに有利。
- MacのDockerはGPU非対応 → ネイティブvenvで組む。
- プライベートリポはPAT/ghで認証、gitを背骨に環境をまたぐ。
- バージョン固定・環境分離・再現性確認でチーム運用に耐える形に。
- 無理な処理はCPU/API/クラウドにハイブリッドで逃がす。
「メインのマシンが1台壊れても、別のアーキテクチャで研究を止めない」——今回いちばんの収穫はこの安心感でした。同じようにApple Siliconへ移る人の、最初の一歩の地図になれば幸いです。