😇

BitNet b1.58 2B4T を MacBook Air M2 16G で動かす

に公開

概要

ARM/macOS 環境で Microsoft の BitNet b1.58 2B4T をビルド・実行するまでの一連の手順です。ARM(16G)の場合、リポジトリのREMADME.mdの内容だけでは、おそらく動かせないです。
このページは少ないメモリで動かすためのtipsのメモになります。

手順

1.リポジトリのクローン

git clone --recursive https://github.com/microsoft/BitNet.git
cd BitNet

2.Python 環境&依存パッケージのインストール

conda create -n bitnet-cpp python=3.9 -y
conda activate bitnet-cpp
pip install -r requirements.txt

3.モデルデータのダウンロード

Hugging Face 上の公式モデル(GGUF 形式)をローカルに保存します。

huggingface-cli download microsoft/BitNet-b1.58-2B-4T-gguf \
  --local-dir models/BitNet-b1.58-2B-4T

ここまで、microsoft/BitNetのREADME.mdの通りに進める

4.CMake のインストール

ビルド時に CMake が必要なので、Anacondaパッケージで導入。

conda install anaconda::cmake -y

5. ビルド前のパッチ

公式の setup_env.py をそのまま実行すると、ARM 向けビルドが終了しない問題があります。
事前に以下パッチを当てます。

setup_env.py
@@ -52,7 +52,7 @@ SUPPORTED_QUANT_TYPES = {
 }

 COMPILER_EXTRA_ARGS = {
-    "arm64": ["-DBITNET_ARM_TL1=ON"],
+    "arm64": ["-DBITNET_ARM_TL1=OFF"],
     "x86_64": ["-DBITNET_X86_TL2=ON"]
 }

BITNET_ARM_TL1=OFF にしないと TL1 カーネルが無限ループ?するらしいです
buildコードをちゃんと読み込んだわけではないので、確かな原因はわからないのですが、
上記のパッチを当てるとうまくいきます
参考)https://github.com/microsoft/BitNet/issues/260

6.ビルド用一時ディレクトリ&優先度設定

ビルドでは一時ファイルが多くなりがちなので、作業フォルダを分けてメモリ効率化&CPU優先度を最高に設定します。

@phoepsilonix(silonix phoep)さんのQuitaブログGGUF型式への変換でメモリ不足になる場合の回避策 をほぼそのまま引用します

setup_env.pyの修正

オプションとして、--use-temp-fileを追加しておきます。これによりメモリ不足で実行が停止するのを回避します。

setup_env.py
@@ -115,10 +115,12 @@ def prepare_model():
     if not os.path.exists(gguf_path) or os.path.getsize(gguf_path) == 0:
         logging.info(f"Converting HF model to GGUF format...")
         if quant_type.startswith("tl"):
-            run_command([sys.executable, "utils/convert-hf-to-gguf-bitnet.py", model_dir, "--outtype", quant_type, "--quant-embd"], log_step="convert_to_tl")
+            run_command([sys.executable, "utils/convert-hf-to-gguf-bitnet.py", model_dir, "--outtype", quant_type, "--quant-embd", "--use-temp-file"], log_step="convert_to_tl")
         else: # i2s
             # convert to f32
-            run_command([sys.executable, "utils/convert-hf-to-gguf-bitnet.py", model_dir, "--outtype", "f32"], log_step="convert_to_f32_gguf")
+            run_command([sys.executable, "utils/convert-hf-to-gguf-bitnet.py", model_dir, "--outtype", "f32", "--use-temp-file"], log_step="convert_to_f32_gguf")
             f32_model = os.path.join(model_dir, "ggml-model-f32.gguf")
             i2s_model = os.path.join(model_dir, "ggml-model-i2_s.gguf")
             # quantize to i2s

カレントディレクトリにTMPDIR用のディレクトリを作成する

mkdir -p .tmp

OOM_KILLERの対象外にする

macの場合

sudo renice -20 -p $$

7.ビルド実行

環境変数 TMPDIR を指定して一時ディレクトリを切り替えつつ、ビルドスクリプトを実行します。

TMPDIR=$PWD/.tmp \
python setup_env.py \
  -md models/BitNet-b1.58-2B-4T \
  -q i2_s

8.推論の実行例

python run_inference.py \
  -m models/BitNet-b1.58-2B-4T/ggml-model-i2_s.gguf \
  -p "You are a helpful assistant" \
  -cnv

引用

Discussion