Llama.cppのデモアプリをCPU-onlyモードでビルドしてiPhoneにデプロイする
この記事ではllama.cppのデモアプリをCPU-onlyモードでビルドし、ローカルのiPhoneにデプロイして任意のモデルでテキストを生成する手順について記述する。
Overview
- Llama.cppはiPhone上で動作するデモアプリをビルドする手順[1]を公開しているが、GPUでの実行は古いiPhoneのチップに対応していない→CPU-onlyモードでビルドするモンキーパッチを当てた
-
TinySwallow-1.5B-Instruct
をiPhone XR(Apple A12 Bionic)で動作確認した - 一般的なXCode上でのiPhoneアプリのビルド手順についても記載(Appendix A)
環境
- iPhone: iPhone XR
- Chip: Apple A12 Bionic
- OS: iOS 18.3
背景: 古いiPhoneでllama.cppを動作させる場合の問題点
問題: Apple7 familyの命令セットに対応していない
Issue#4998によると、Llama.cppをApple Silicon上で動作させる場合は、MTLGPUFamily.apple7
の命令セットに対応した A14, M1以降のデバイス[2, 3]が必要。それより古いデバイスでは以下のようなエラーが出てクラッシュする。
ml_metal_graph_compute_block_invoke: error: unsupported op 'MUL_MAT'
GGML_ASSERT: ggml-metal.m:779: !"unsupported op"
Issue: https://github.com/ggml-org/llama.cpp/issues/4998
確認方法
デバイスがApple7 familyの命令セットに対応しているかどうかはXCodeの画面上でLlama.cppがモデルをロードする時に表示されるログから確認できる。
simdgroup reduction support = false <-- 未対応
ワークアラウンド
メインコミッターのGGは「これらのsimd_
命令を使わないkernelを実装すれば本質的な対処になるが、公式に対応する予定はない」と回答している。
The only way is to implement the respective Metal kernels without using simd_ calls. It's not very difficult, but I don't plan on officially supporting it as it will increase the Metal code by a lot and I'm not convinced it will result in significant gains compared to CPU-only for these machines.
If somebody implements the kernels, we can put them in ggml-metal-intel.metal and have them build as a separate backend for Intel machines
source: https://github.com/ggml-org/llama.cpp/issues/4998#issuecomment-1898421820
従って、本手順ではワークアラウンドとしてCPU-onlyモードで実行させることを目標にする。
アプリのコード修正
以下の1~4のコードを修正してCommand+R
でアプリをビルドする。
1. issue #7085 に対応したcommit hashをチェックアウトする
git clone https://github.com/ggerganov/llama.cpp
git checkout 2c3ffd2944ccfb656d686ccd79edc04c311e6cac
issue: https://github.com/ggml-org/llama.cpp/issues/7085
PR: https://github.com/ggml-org/llama.cpp/pull/4794
2. CPU-onlyモードで動作するようコードを書き換える
CPU-onlyで動作させる。具体的には以下の#if
, #endif
をコメントアウトしてn_gpu_layers=0
に設定する。
変更後:
//#if targetEnvironment(simulator)
model_params.n_gpu_layers = 0
print("Running on simulator, force use n_gpu_layers = 0")
//#endif
3. (Optional)出力テキストのコンテキスト長を延長する
デフォルトだとcontext_len=64なので512に延長する。
変更後:
var n_len: Int32 = 512
4. (Optional)モデルを追加する
デフォルトだと使用するモデルが限られているのでコードを編集してTinySwallow-1.5B-Instruct
を追加する。
Modelの定義にTinySwallow-1.5B-Instruct(Q5_K_M)
を追加する。
Model(
name: "TinySwallow-1.5B-Instruct (Q5_K_M, 1.13 GiB)",
url: "https://huggingface.co/SakanaAI/TinySwallow-1.5B-Instruct-GGUF/resolve/main/tinyswallow-1.5b-instruct-q5_k_m.gguf?download=true",
filename: "tinyswallow-1.5b-instruct-q5_k_m.gguf", status: "download"
)
ref: https://huggingface.co/SakanaAI/TinySwallow-1.5B-Instruct-GGUF
実行時のTips
1. チャットテンプレートの適用
デモアプリではチャットテンプレートの自動付与機能がないため自分で追加する必要がある。
TinySwallowのデモアプリの公式ページに従って、以下のテンプレートを適用する。
[system](あなたは、Sakana AI株式会社が開発したTinySwallowです。小型ながら、誠実で優秀なアシスタントです。)
<|im_start|>user
{{prompt}}<|im_end|>
<|im_start|>assistant
ref: https://github.com/SakanaAI/TinySwallow-ChatUI/blob/main/docs/iphone.md
2. XCodeを落としてiPhoneから実行
公式手順[1]に以下のような説明がある。
Stop Xcode and run the app from the device. This is important because the performance when running through Xcode is significantly slower
具体的には以下のようにする。
- Xcode 上で実行を停止
- Xcode 上部の 停止ボタン (■) をクリック
- Xcode を終了
-
Command + Q
でXcodeを完全に終了
-
- iPhone のホーム画面からアプリを起動
- iPhone のホーム画面にアプリアイコン が表示されているので、タップして起動
参考: 生成速度の違い
XCodeありとなしでは実際に生成速度にかなりの差があった。
- XCodeあり: 5分52秒
- XCodeなし: 1分22秒
アプリ実行手順
- iPhone上からアプリを起動する
- View Modelから
TinySwallow-1.5B-Instruct
の量子化モデルをダウンロードする。ダウンロードが終わったらもう一度クリックしてロードする。 - Backで元の画面に戻り、テキストボックスにプロンプトを貼り付ける
- Sendを押す
実行結果
プロンプト
[system](あなたは、Sakana AI株式会社が開発したTinySwallowです。小型ながら、誠実で優秀なアシスタントです。)
<|im_start|>user
機械学習モデルの正則化にはどのようなアプローチがある?<|im_end|>
<|im_start|>assistant
生成結果
機械学習モデルの正則化には、主に以下のアプローチがあります。
- L1正則化 (Lasso):重みの絶対値の合計をペナルティとして加えることで、モデルの複雑さを抑制します。過学習を防ぎ、重要な特徴量を抽出するのに有効です。
- L2正則化 (Ridge):重みの二乗の合計をペナルティとして加えることで、モデルの複雑さを抑制します。L1正則化よりも汎化性能が優れている傾向があります。
- Dropout:ニューラルネットワークの学習中に、ランダムに一部のニューロンを無効化することで、過学習を防ぎます。
- Weight Decay:重みの初期値を制限することで、モデルの複雑さを抑制します。
- Early Stopping:検証データの性能が低下し始めたら、学習を停止することで過学習を防ぎます。
これらのアプローチは、単独で使用することも、組み合わせて使用することもできます。最適なアプローチは、問題の性質やデータセットによって異なります。
生成時間: 1分50秒
内容の評価: 「L2正則化がL1正則化より汎化性能が優れている」は一般化しすぎなのと、Weight Decayの説明は誤り。それ以外は概ね的確なことを言っている。
Summary
- 本記事ではLlama.cppをCPU-only modeで動作させる手順をiPhone XR(Apple A12 bionic)で動作確認した
- iPhone XR+CPUでの1.5Bモデル(Q5_K_M)の実行速度はあまり実用的でない(簡単な応答に2分程度かかる)
- Llama.cppをAppleデバイスのGPUで動作するにはA14/M1以降のチップが必要。それより古いチップのGPUで動作させるには自分でKernelを実装する必要がある
Reference
- [1] Performance of llama.cpp on Apple Silicon A-series #4508, https://github.com/ggml-org/llama.cpp/discussions/4508
- [2] MTLGPUFamily.apple7, https://developer.apple.com/documentation/metal/mtlgpufamily/apple7
- [3] Metal feature set tables, https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
Appendix
A. XCodeからローカルのiPhoneにアプリをデプロイする手順
A-1. 事前にやっておくこと
- Apple Developerアカウントの登録
- iPhoneの接続(Wi-Fi or USB)
- XCodeのインストール
A-2. XCode側の設定
a. Apple IDの登録
- Xcodeを起動
- メニューから Xcode > Settings (または Preferences) > Accounts を選択
- 左下の + ボタンをクリックし、Apple ID を選択してサインインする
b. Bundle Identifier の設定
- Project Navigator からプロジェクト名をクリック
- TARGETS の下にあるプロジェクトを選択
- General タブ内の Bundle Identifier を確認(例:
com.example.myapp
)
c. チームの設定
- Signing & Capabilities タブを開く
- Team を設定
自分のApple IDを選択
初回のみ、「Provisioning Profile」を自動で作成するため、XcodeがAppleにアクセスする
d. Release Buildの設定
- Xcode の上部メニュー から、
Product > Scheme > Edit Scheme...
を選択 - Edit Scheme ウィンドウ が表示される
- 左ペインの Run を選択
- Info タブを選択
- Build Configuration: "Release" を選択
- Debug executable: チェックを外す
A-3. iPhoneのデバイス登録
a. デバイスの信頼設定
- iPhoneをUSBケーブルで接続
- iPhone上で「このコンピュータを信頼しますか?」と表示されたら「信頼」を選択し、パスコードを入力
- Xcode上部の Device選択メニュー から、接続したiPhoneを選択
b. デバイスの信頼確認 (iPhone 側)
- 初回デプロイ時、iPhone側で 設定 > 一般 > VPNとデバイス管理 に移動
- 自分のApple IDを選択し、「信頼」をタップ
A-4. ビルドとデプロイ
- Xcode 上部の 再生ボタン (▶️) をクリック
- または、Command + R を押す
- ビルドが成功すると、iPhone上でアプリが起動する
Discussion