0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Anaconda を完全削除して uv + venv に移行した話(macOS / Apple Silicon, LightGBM segfault の原因と対処)

0
Posted at

はじめに

macOS(Apple Silicon)で、Anaconda を完全に削除し uv ベースの venv 環境に移行しました。用途は Kaggle 形式のデータサイエンス/DL コンペで、LightGBM XGBoost CatBoost PyTorch (MPS) を組み合わせて使っています。

移行作業中に「torch の MPS 学習に成功した直後に LightGBM を実行するとセグフォルトする」という厄介な問題にぶつかったので、原因調査から解決までの流れと、Anaconda 削除の手順、そして今後同種のトラブルに遭遇したときのための汎用的な切り分け方をまとめます。

先に結論だけ知りたい方向け: 原因は「torch と scikit-learn が同梱する libomp.dylib」と「Homebrew の libomp.dylib」が別ファイルとしてプロセス内に二重ロードされ、OpenMP の初期化が衝突していたことでした。


最終的な環境構成

  • venv 本体: uv venv で作成(Python 3.13系)
  • パッケージ管理: uv pip(素の pip コマンドではない。venv に pip 自体が同梱されていないため)
  • Homebrew: brew install uv open-mpi libomp cairo android-platform-tools

新規ターミナルで torch(MPS) → LightGBM → XGBoost → CatBoost の全動作を確認できたところで移行完了としています。


ハマったポイントと解決策

1. LightGBM 実行時のセグフォルト(OMP: Error #179

症状

=== LightGBM ===
OMP: Error #179: Function pthread_mutex_init failed:
OMP: System error #22: Invalid argument
zsh: segmentation fault  python3 quick_env_check.py

torch の MPS 学習が成功した直後に LightGBM を実行するとクラッシュします。一方で、LightGBM 単体(torch を import しない状態)を実行した場合には発生しません。この「単体では起きないが、他のライブラリの後だと起きる」という再現条件が、原因調査の大きな手がかりになりました。

根本原因

torchscikit-learn は、それぞれ自分専用の libomp.dylib を wheel に同梱しています(pip/uv でインストールした場合、パッケージ内に埋め込まれています)。これが Homebrew の libomp.dylib(LightGBM/XGBoost/CatBoost が参照するもの)と物理的に別ファイルであるため、同一プロセス内に異なる OpenMP ランタイムが複数ロードされ、初期化処理が衝突します。これは macOS の libomp まわりでよく知られている問題で、LightGBM の Issue でも報告されています(microsoft/LightGBM#4229, #4897)。

確認方法

find <venvのsite-packages> -iname "libomp*.dylib" -exec ls -la {} \;
shasum -a 256 <torch側libomp> <Homebrew側libomp>

サイズやハッシュ値が異なっていれば、別ファイルとして二重にロードされていることが確定します。

解決策

torch / scikit-learn が同梱する libomp を削除し、Homebrew の libomp への symlink に置き換えることで「プロセス内で使われる libomp を1つに統一」します。

# torch
TORCH_LIBOMP=<venv>/lib/python3.13/site-packages/torch/lib/libomp.dylib
HOMEBREW_LIBOMP=/opt/homebrew/opt/libomp/lib/libomp.dylib

cp "$TORCH_LIBOMP" "${TORCH_LIBOMP}.orig_backup"
rm "$TORCH_LIBOMP"
ln -s "$HOMEBREW_LIBOMP" "$TORCH_LIBOMP"

# scikit-learn も同様の手順で対応
# パスは <venv>/lib/python3.13/site-packages/sklearn/.dylibs/libomp.dylib

⚠️ 再発条件に注意

torchscikit-learnuv pip install -U などでアップデートすると、パッケージが再インストールされる際に symlink が通常ファイルへ巻き戻されます。LightGBM が再びクラッシュするようになったら、まず symlink が生きているかを確認してください。

ls -la <venv>/lib/python3.13/site-packages/torch/lib/libomp.dylib
ls -la <venv>/lib/python3.13/site-packages/sklearn/.dylibs/libomp.dylib

lrwxr-xr-x(symlink)ではなく通常ファイル(-rwxr-xr-x)に戻っていたら、上記の symlink 置換を再実行します。


2. venv に pip が同梱されていない

uv venv で作成した環境には、デフォルトでは pip が含まれていません。ここで素の pip install ... を実行すると、PATH 上の別の場所(移行前であれば Anaconda 側など)に誤ってインストールされてしまうことがあるため注意が必要です。

必ず uv pip install ... を使うこと。 python3 -m pip も、そもそも pip モジュール自体が存在しないため使えません。


3. (base) プロンプトの残留は無害だが、原因は別途切り分ける

conda deactivate した後もシェルプロンプトに (base) が残ることがありますが、これ自体は conda init が仕込んだプロンプト書き換え関数の見た目上の残留であり、単独では無害です。ただし CONDA_SHLVLPATH の状態は別問題として必ず確認しましょう。

echo "CONDA_SHLVL: $CONDA_SHLVL"
echo "DYLD_LIBRARY_PATH: $DYLD_LIBRARY_PATH"
which -a python3 pip

CONDA_SHLVL=0 であれば、プロンプト表示だけの問題で実害はないと判断できます。


4. Anaconda 本体削除時の Permission denied

rm -rf /opt/anaconda3 で中身自体は削除できますが、ディレクトリ本体(/opt 直下、root:wheel 所有)の削除には管理者権限が必要な場合があります。

sudo rm -rf /opt/anaconda3

実行時にログインパスワードの入力を求められますが(画面には表示されません)、これは Anaconda の認証情報とは無関係な、macOS の sudo 認証です。


Anaconda 削除の手順まとめ

各ステップでバックアップ・確認を挟みながら進めました。

  1. .zshrc のバックアップを取る

    cp ~/.zshrc ~/.zshrc.backup_<timestamp>
    
  2. conda の base 環境設定を退避する

    conda run -n base anaconda-clean --yes
    

    設定は ~/.anaconda_backup/<timestamp>/ に退避されます。

  3. 削除前チェック

    • CONDA_SHLVL=0 であること
    • カスタム環境が残っていないこと
    • バックアップファイル(backup_base_list.txt 等)が存在すること
  4. Anaconda 本体を削除する

    sudo rm -rf /opt/anaconda3
    
  5. .zshrc から conda 初期化ブロックを削除する

    sed -i '' '/# >>> conda initialize >>>/,/# <<< conda initialize <<</d' ~/.zshrc
    
  6. 新しいターミナルタブを開いて最終確認する

    同じターミナルセッションでは古い環境変数が残ったままになるため、必ず新規タブで確認します。

    • which conda → not found であること
    • which mpicc/opt/homebrew/bin/mpicc が見えること(PATH の恒久化作業は不要で、Anaconda を削除するだけで自動的に解消されました)
    • venv 内で torch → LightGBM → XGBoost → CatBoost が全て問題なく完走すること

トラブルシューティングの型(他の環境構築でも使える汎用パターン)

今回の調査を通じて、ライブラリ絡みの環境トラブルに共通して使える切り分け手順が見えてきたので、まとめておきます。

  1. 切り分け: 単体で import しただけで再現するのか、実際に実行(学習・計算など)したときのみ再現するのかを先に区別する
  2. 環境変数の残留確認: env | grep -iE "対象キーワード" で怪しい環境変数が残っていないか確認する
  3. 新規シェルでの再現確認: 現在のシェルの状態に依存していないか、必ず新しいターミナルを開いて再現するか確認する
  4. バイナリの依存関係を直接見る: otool -L(macOS)で共有ライブラリの実際のリンク先を確認する
  5. 同名ファイルの物理的な同一性を疑う: 同じライブラリ名でも、パッケージごとに複数バージョン・複数コピーが存在しうる。shasum やファイルサイズで比較して同一性を確認する
  6. パッケージ管理コマンドが正しい環境をターゲットにしているか確認する: which -a pip 等で複数の候補が見つかる場合は要注意。今回の uv 環境のように、専用のパッケージマネージャコマンド(uv pip)を使う必要があるケースもある

まとめ

  • Anaconda から uv + venv への移行自体は、本体削除とシェル設定のクリーンアップだけであれば難しくありません。
  • ただし、torch / scikit-learn が同梱する libomp.dylib と、LightGBM/XGBoost/CatBoost が参照する Homebrew の libomp.dylib が衝突し、セグフォルトを起こすことがあります。これは Homebrew 経由で GBM 系ライブラリを使う macOS 環境ではハマりやすいポイントなので、同様の症状に遭遇した方の参考になれば幸いです。
  • ライブラリのアップデートで symlink が巻き戻り再発することがあるため、CI やセットアップスクリプトに組み込む場合はチェック処理を入れておくと安心です。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?