0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ポエム】バッテリーを外したIntel Mac(2017)の1.5GHz縛りをVoltageShiftで解除したメモ

0
Posted at

バッテリーを外したIntel Mac(2017)の1.5GHz縛りをVoltageShiftで解除したメモ

このメモ書きは、膨張したバッテリーをBMSごと取り外したIntel Macで、AI歌声合成ソフトのフリーズ処理が極端に遅くなった件の記録だ。原因の特定から、遠回りを経て実用レベルのクロック解除にたどり着くまでをまとめている。

環境

項目 内容
機種 2017年 13インチ Intel MacBook Pro(Touch Barなし)
CPU Kaby Lake世代 Core i5 2コア4スレッド 定格2.3GHz 最大3.6GHz
メモリ 16GB
電源 純正61W USB-Cアダプタのみ(バッテリー未接続)
DAW Mac標準の無料DAW
用途 AI歌声合成ソフト(AUプラグイン版)+標準ボイスライブラリ
使用ツール VoltageShift 1.25(MSR読み書き用のオープンソースkext)

経緯

以前はリアルタイム再生できていた歌声合成トラックが、ある時期からトラックのフリーズをかけないとまともに再生できなくなっている。同時期にバッテリーが膨張し、BMS(Battery Management System)ごと抜き取った状態でAC駆動のみで運用していた。

フリーズ:DAWの機能で、重いプラグインの出力を一時的にオーディオとして書き出し、再生時の計算を省く仕組みだ。編集時は解除が必要になる。

BMS:Battery Management System。バッテリーの電圧や残量を管理し、Mac側のSMCと通信する基板だ。音ゲーのアレではない。

原因は バッテリー未接続を検知したmacOSとSMCが、CPUを1.5GHzに自主規制していたこと だった。

バッテリーはピーク時の電力をアダプタに上乗せする緩衝材の役割も持っている。これがないと重い瞬間に電力不足で電源が落ちる恐れがあるため、Macは「アダプタだけで確実に足りる速度」まで絞る設計になっている。コンセント直結なら安定するという直感とは逆の挙動だ。

ブレーキの正体

計測で判明したブレーキは2段構えだった。

MSR 名称 読み取り値 意味
0x1FC POWER_CTL 0x24005F bit0=1でBD PROCHOT有効
0x64F PERF_LIMIT_REASONS 全bit 0 熱や電力によるハード側の制限はなし
0x771 HWP_CAPABILITIES 最高36 定格23 効率13 最低1 単位は100MHz
0x774 HWP_REQUEST 0x800F0F04 最大15(1.5GHz)が設定されている

0x774の8bitずつの並びは下表になる。

位置(右から) 意味 元の値 変更後
1番目 最低速度 4(0.4GHz) 4
2番目 最高速度 15(1.5GHz) 23(2.3GHz)または28(2.8GHz)
3番目 希望速度 15 0(CPUにおまかせ)
4番目 省電力バランス(EPP) 128 128

MSR:Model Specific Register。CPU内部の設定スイッチ群だ。書き込みは揮発性で、電源を切れば必ず初期値に戻る。ファームウェアやディスクは一切書き換わらない。

HWP:Hardware P-states。OSが上限と下限を指示し、その範囲でCPU自身が周波数を選ぶ仕組みだ。

電力上限(PL1 100W PL2 125W)や温度(50度前後)には余裕があり、ハードの健康状態とは無関係なOS側の縛り だと確定している。

解決までの道のり

遠回りした内容

試したこと 結果 原因
DAWのI/Oバッファサイズ変更 不可 上位版DAWの機能で、無料版には存在しない
BD PROCHOTのみ解除 1.5GHzのまま XCPMによるHWP上限が別に残っていた
電力上限を疑う 無関係 PL1/PL2は100W/125Wで十分高い
0x774を1回だけ書き換え 秒で元に戻る macOSが定期的に上書きしている
4秒間隔のループ サクサクと重いを繰り返す 書き戻しの方が速い
0.3秒間隔のループ 改善が頭打ち voltageshiftが毎回kextを読み込み外すため1回1.26秒かかる
ループ2本を並列実行 やや改善後にkextが詰まる 同時ロードで衝突し、全readが0、IO Serviceに接続不可になり再起動が必要になった
歌声合成のフリーズ中に計測 1.5GHz固定 2コアが埋まり、書き込みが暇なコアにしか当たらない
Windows用CPU制限ツール 対象外 Windows専用で、上限を下げる方向のツールだ
OSからバッテリーありと偽装 不可 判定はSMCとBMSの専用線通信で行われ、OSから介入できない

最大の遠回りは、ツールのREADMEを読まずにループを組んだこと だ。loadkext の存在を最初から把握していれば、1.3秒の壁とkext詰まりによる再起動は発生していない。

XCPM:macOSカーネルに組み込まれたIntel CPU用電源管理だ。機種ごとの周波数テーブルを持ち、状態に応じてHWPの指示を出し直している。テーブル自体の書き換えは封印されたシステム領域の改変になり、起動不能のリスクがあるため今回は対象外にしている。

解決方法

1. SIPの無効化

起動直後にCommand+Rを押し続けて復旧モードへ入り、メニューバーのユーティリティからターミナルを開く。画面中央の復元や再インストールの項目には触れない。

csrutil disable
reboot

通常起動後の確認。

csrutil status
# System Integrity Protection status: disabled.

2. VoltageShiftの取得

GitHub上にリリースが登録されておらず、リポジトリ直下にzipが置かれている形式だ。APIで中身を確認してから取得している。

curl -s https://api.github.com/repos/<作者>/VoltageShift/contents/ | grep '"name"'
mkdir -p ~/Downloads/VoltageShift
cd ~/Downloads/VoltageShift
curl -L -o voltageshift_1.25.zip https://github.com/<作者>/VoltageShift/raw/HEAD/voltageshift_1.25.zip
file voltageshift_1.25.zip   # Zip archive data なら成功
unzip voltageshift_1.25.zip
sudo chown -R root:wheel VoltageShift.kext
chmod +x voltageshift

grep が何も出力しない場合は該当なしの意味だ。Linuxと同じく無言が成功とは限らない。releases/latest が404を返すのはリリース未登録のためだ。

3. kextの承認

初回の read 実行で「not approved to load」エラーが出る。その直後にシステム環境設定のセキュリティとプライバシーを開き、ロックを解除して開発元の「許可」を押し、再起動が必要になる。ブロック表示は30分程度で消えるため、エラー直後に操作している。

4. 現状の確認

sudo ./voltageshift read 0x1FC   # PROCHOT
sudo ./voltageshift read 0x774   # HWP上限
sudo ./voltageshift read 0x771   # 段階表
sudo ./voltageshift info         # 電力上限 温度 電圧

出力は2進数8バイトで表示される。PROCHOTの解除は末尾が奇数なら1引いた値を書き込む形になる。

sudo ./voltageshift write 0x1FC 0x24005E

5. kextの常駐化

loadkext で読み込みっぱなしにすると、書き込み1回が1.26秒から0.068秒まで短縮される。

sudo ./voltageshift loadkext
time sudo ./voltageshift write 0x774 0x80001704
# real 0m0.068s
方式 1回あたり 主な待ち
通常実行 1.261秒 毎回のkextロードとアンロード
loadkext常駐 0.068秒 ほぼなし

6. 常駐ループスクリプト

2.3GHz版の boost.sh。二重起動防止ロック、終了時のkext解除、回転表示を含んでいる。

#!/bin/bash
cd "$(dirname "$0")"
LOCK=/tmp/boost.lock
if ! mkdir "$LOCK" 2>/dev/null; then
  echo "もう動いてるぞ。2本目は起動しない"
  exit 1
fi
cleanup() {
  ./voltageshift unloadkext > /dev/null 2>&1
  rmdir "$LOCK"
  echo
  echo "止めた(拡張も外した)"
  exit
}
trap cleanup INT TERM
./voltageshift loadkext > /dev/null
./voltageshift write 0x1FC 0x24005E > /dev/null
s='|/-\'
i=0
while true; do
  ./voltageshift write 0x774 0x80001704 > /dev/null
  printf "\rboost中 %s  (止めるときは Control+C) " "${s:i++%4:1}"
  sleep 0.05
done

2.8GHz版の boost_high.sh は書き込み値と表示のみ異なる。ロックファイルを共有しているため、2本の同時起動は弾かれる。

  ./voltageshift write 0x774 0x80001C04 > /dev/null
  printf "\rboost_high (2.8GHz) %s  (止めるときは Control+C) " "${s:i++%4:1}"

起動と停止。

cd ~/Downloads/VoltageShift
sudo ./boost.sh        # 2.3GHz
sudo ./boost_high.sh   # 2.8GHz
# 停止は Control+C

前回の停止が異常終了でロックが残った場合の削除。

sudo rmdir /tmp/boost.lock

ヒアドキュメント cat > boost.sh << 'EOF' から EOF までの間が、そのままファイルの中身として書き出される。chmod +x で実行権限を付与している。voltageshiftはroot権限が必要なため、sudo なしの bash boost.sh では動作しない。

7. 効果の確認

voltageshift infoの周波数表示は暇な瞬間を拾いやすく、当てにならない。確認には標準のpowermetricsを使っている。

sudo powermetrics --samplers cpu_power -i 500 | grep --line-buffered -i "CPU Average frequency"

負荷テスト用の一時コマンド。最後の killall yes を忘れると全開のまま回り続ける。

for i in 1 2 3 4; do yes > /dev/null & done
sleep 5
sudo powermetrics --samplers cpu_power -i 1000 -n 1 | grep -i "freq"
killall yes

計測結果

状態 負荷時の周波数 体感
対策なし 1500MHz固定 文字入力にも遅延
PROCHOT解除のみ 1500MHz固定 変化なし
通常実行ループ(1周約1.6秒) 2300と1500を数秒単位で往復 サクサクとカクつきの繰り返し
同上で歌声合成フリーズ 1500MHz固定 改善なし
loadkext常駐ループ 2.3GHz 1900〜2300MHz フリーズ処理が実用速度
loadkext常駐ループ 2.8GHz 2100〜2800MHz ゲームも入力も軽快

通常実行ループ時の波形は、1500から1540、1670、1960、2300と階段状に戻る形になっていた。論理4コアの平均値で、voltageshiftの書き込みが1回につき実行中の1コアにしか効かないことを示している。

GPU(内蔵Iris Plus 640)は実測で約880MHz(最大約1000MHz)まで回っており、ほぼ制限を受けていない。

余談として、「今はコア数が重要で周波数は昔の話」という説は、世代間でCPUを比較する場面の話だ。同じCPU内で周波数を1.5GHzから2.8GHzに戻すと、1コアあたりの処理速度は約1.9倍になる。ゲームや歌声合成のように1〜2コアに処理が集中するソフトでは、体感差がそのまま出る。

注意点

  • SIPは無効のまま になっている。バッテリー交換後は復旧モードで csrutil enable が必要だ
  • kext常駐中は、他のプログラムがroot権限なしでMSRを操作できる状態になる(作者のREADMEに警告あり)
  • ブレーキ解除中は重い瞬間に電源が落ちる危険がある。作業ファイルはこまめに保存が前提だ
  • 再起動で全設定がリセットされる。起動ごとに sudo ./boost.sh の実行が必要になる
  • 本質的な解決はバッテリー交換だ。互換バッテリー(A1713相当)にもBMSが搭載されており、SMCと正常に通信する。PSEマーク付きで保証のある製品が前提になる

起動不能が心配な場合の逃げ道として、Shiftを押しながらのセーフモード起動と、Command+Rの復旧モードがある。今回の手順は起動に関わる領域を一切書き換えておらず、自動起動の設定(buildlaunchd)も使っていない。

まとめ

論点 結論
重くなった原因 バッテリー未接続を検知したSMCとmacOSがCPUを1.5GHzに制限していた
ブレーキの構成 BD PROCHOT(0x1FC)とXCPMによるHWP上限(0x774)の2段
PROCHOT解除の効果 単独では効果なし
0x774の書き換え macOSが即座に書き戻すため、常時書き直しが必要
通常実行ループの限界 kextの毎回ロードで1回1.26秒かかり、綱引きに負ける
並列実行 kextの取り合いで詰まり、再起動が必要になる
突破口 loadkextで常駐させ、0.05秒間隔で連打
達成値 2.3GHz版で安定、2.8GHz版も電源落ちなく動作
残るリスク SIP無効、kext常駐中の権限、電源落ち
本命の解決策 バッテリー交換

あとがき

歌声合成のウィスパー調整の相談から始まったやり取りが、気づけばCPUのレジスタとの綱引きになっている。「数秒ごとに書けばいい」という素朴な発想が出発点になり、「コアを選べないのか」という疑問からREADMEを読み直して loadkext に行き着いた。道具の説明書は組む前に読むべきだという教訓が一番大きい。バッテリー交換までのつなぎとしては十分な速度が出ており、交換後はSIPを戻して今回のスクリプト群は役目を終えることになる。

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?