10月の最終週にAppleからMacの新製品が発表されました。前から「Apple M4搭載のMacが出たら買い替えたい」と考えていた私にとって、ついに出費の時が来たのです。
Apple M4のどこに惹かれたか
Apple M4はiPad Proにすでに搭載されており、実装している命令セットは知られています。LLVMの定義ファイルを見ると、Armv8.7やSMEが並んでいます。
SME (Scalable Matrix Extension) については前に記事を書きました:
また、Armv8.7を実装しているということは、FEAT_AFPが使えるということです(浮動小数点数をサポートするArmv8.7実装はFEAT_AFPも実装しなければなりません)。FEAT_AFPは浮動小数点数の重箱の隅の挙動を変える能力を持ちます。「Binary Hacks Rebooted」でもちょろっと解説したので読んでください。
(家電量販店の店頭のApple M3搭載マシンで sysctl -a hw
を叩くとFEAT_AFPに対応していると出たので、少なくともApple M3の頃からFEAT_AFPには対応していたようです。しかしLLVMの定義ファイルにはFEAT_AFPの有無は載らないので、私がこのことを知ったのはつい最近です。)
そういうわけで、浮動小数点数や命令セットに興味のある私としては、Apple M4の実機が欲しいと思っていたのでした。そのためにiPad Proを買うほどではありませんでしたが(昔買ったiPad Proが手元にあるのでタブレットにはそんなに困っていない)。
どれを買うか
現状使っているMacはM1 Mac miniとIntel (Ice Lake) MacBook Proで、どちらも2020年に購入したものです。M1 Mac miniはメモリーと内蔵ストレージが狭く、Intel MacBook Proは性能がApple Silicon Macに比べてしょぼいので、どちらも買い替えて良さそうですが、一気に2台とも買い替えるのは出費の観点から難しいです。M4搭載のMac Studioが出れば迷いは少なかったかもしれませんが、今回は出ませんでした。
そういう感じで11月4日の発売後もどれを買うか悩んでいましたが、M4 Mac miniを買うことに決めました。スペックは以下です:
- M4 Pro(14コアCPU/20コアGPU)
- M4の無印とProでは、コア数だけを見るとそこまで大きな違いはなさそうな気がしますが、Pコア/Eコアの配分が違うので性能差はありそうです。性能を追求したいのでProにしました。
- 48GBユニファイドメモリ
- 選択肢は24GB/48GB/64GBで、24GBだと少ないかと思って48GBにしました。これまで使ってきたMac miniは16GBで、手狭でした。
- 1TBストレージ
- これまで使ってきたMac miniは内蔵ストレージが512GBで辛い思いをしたので、1TBにしました。
- 10GbE
- 家では2.5GbEとして使います。これまで使ってきたMac miniは1GbEでした。
これまで使ってきたM1 Mac miniは10万程度だったことを考えると、結構大きな出費になりましたが、普段から使うものなのでそれだけの価値はあると信じています。
注文したのが11月8日で、届いたのは11月17日でした。注文直後のお届け日時見積もりは11月末〜12月頭だったので萎えましたが、注文時点では余裕のある日付を提示していたのでしょう。
開封の儀
箱は片手に乗るサイズでした。
M1 Mac mini(上)と前に買ったMINISFORUMのミニPC(左下、「ミニPCを買った」で買ったUM790 Pro)と新しいMac mini(右下)を並べてみます。
ポート類を比較してみます。UM790 Pro(一番上)はACアダプターが外付けなのに対して、Mac miniは(新旧共に)電源内蔵です。一方、UM790 ProはUSB Aポートが4個ついているので、ハブやドッキングステーションがなくてもUSB Aの資産を活かせます。Mac miniでUSB Aの資産を活かすには、USBハブやドッキングステーションか変換ケーブルが必要になるので、「電源内蔵」というメリットを少し打ち消しているかもしれません。このほか、Mac miniはThunderbolt対応です(対応機器持ってないけど……)。
外観からは分かりませんが、Mac miniはスピーカー内蔵です。4年前に初めて買った時にびっくりしました。画面がついていないPC本体は(ブザー以外の)スピーカーを内蔵しないという先入観がありました。
データ移行
データ移行には「移行アシスタント」を使いました。LANやThunderboltでMac同士を繋いでデータを転送するやつです。ThunderboltケーブルがあるとギガビットEthernetよりも高速なのかもしれませんが、持っていないのでEthernet経由でした(転送元が1GbEなので転送速度はその程度)。
「残り10分」のまま永遠の時が過ぎたように思われましたが、なんとか終わりました。
ベンチマーク
Geekbenchの結果はMac16,11 – Geekbenchです。シングルコア3748、マルチコア21705です。UM790 Proを買った時のベンチマーク結果と比べると、性能が向上しているようです。これはベンチマークアプリケーション側でのSME対応の影響があるのかもしれませんが……。
GHCのquickビルド時間は、11分でした。UM790 Proで改めて試したところ13分だったので、UM790 Proよりも強いけれどそこまで差は大きくなさそうです。
sysctl -a hwの結果
ターミナルで sysctl -a hw
を実行すると、対応している命令セット拡張の情報などが出てきます。
$ sysctl -a hw
hw.ncpu: 14
hw.byteorder: 1234
hw.memsize: 51539607552
hw.activecpu: 14
hw.perflevel0.physicalcpu: 10
hw.perflevel0.physicalcpu_max: 10
hw.perflevel0.logicalcpu: 10
hw.perflevel0.logicalcpu_max: 10
hw.perflevel0.l1icachesize: 196608
hw.perflevel0.l1dcachesize: 131072
hw.perflevel0.l2cachesize: 16777216
hw.perflevel0.cpusperl2: 5
hw.perflevel0.name: Performance
hw.perflevel1.physicalcpu: 4
hw.perflevel1.physicalcpu_max: 4
hw.perflevel1.logicalcpu: 4
hw.perflevel1.logicalcpu_max: 4
hw.perflevel1.l1icachesize: 131072
hw.perflevel1.l1dcachesize: 65536
hw.perflevel1.l2cachesize: 4194304
hw.perflevel1.cpusperl2: 4
hw.perflevel1.name: Efficiency
hw.optional.arm.FEAT_FlagM: 1
hw.optional.arm.FEAT_FlagM2: 1
hw.optional.arm.FEAT_FHM: 1
hw.optional.arm.FEAT_DotProd: 1
hw.optional.arm.FEAT_SHA3: 1
hw.optional.arm.FEAT_RDM: 1
hw.optional.arm.FEAT_LSE: 1
hw.optional.arm.FEAT_SHA256: 1
hw.optional.arm.FEAT_SHA512: 1
hw.optional.arm.FEAT_SHA1: 1
hw.optional.arm.FEAT_AES: 1
hw.optional.arm.FEAT_PMULL: 1
hw.optional.arm.FEAT_SPECRES: 0
hw.optional.arm.FEAT_SB: 1
hw.optional.arm.FEAT_FRINTTS: 1
hw.optional.arm.FEAT_LRCPC: 1
hw.optional.arm.FEAT_LRCPC2: 1
hw.optional.arm.FEAT_FCMA: 1
hw.optional.arm.FEAT_JSCVT: 1
hw.optional.arm.FEAT_PAuth: 1
hw.optional.arm.FEAT_PAuth2: 1
hw.optional.arm.FEAT_FPAC: 1
hw.optional.arm.FEAT_DPB: 1
hw.optional.arm.FEAT_DPB2: 1
hw.optional.arm.FEAT_BF16: 1
hw.optional.arm.FEAT_I8MM: 1
hw.optional.arm.FEAT_WFxT: 1
hw.optional.arm.FEAT_RPRES: 1
hw.optional.arm.FEAT_ECV: 1
hw.optional.arm.FEAT_AFP: 1
hw.optional.arm.FEAT_LSE2: 1
hw.optional.arm.FEAT_CSV2: 1
hw.optional.arm.FEAT_CSV3: 1
hw.optional.arm.FEAT_DIT: 1
hw.optional.arm.FEAT_FP16: 1
hw.optional.arm.FEAT_SSBS: 0
hw.optional.arm.FEAT_BTI: 1
hw.optional.arm.FEAT_SME: 1
hw.optional.arm.FEAT_SME2: 1
hw.optional.arm.SME_F32F32: 1
hw.optional.arm.SME_BI32I32: 1
hw.optional.arm.SME_B16F32: 1
hw.optional.arm.SME_F16F32: 1
hw.optional.arm.SME_I8I32: 1
hw.optional.arm.SME_I16I32: 1
hw.optional.arm.FEAT_SME_F64F64: 1
hw.optional.arm.FEAT_SME_I16I64: 1
hw.optional.arm.FP_SyncExceptions: 1
hw.optional.arm.caps: 1152375836863623167
hw.optional.floatingpoint: 1
hw.optional.neon: 1
hw.optional.neon_hpfp: 1
hw.optional.neon_fp16: 1
hw.optional.armv8_1_atomics: 1
hw.optional.armv8_2_fhm: 1
hw.optional.armv8_2_sha512: 1
hw.optional.armv8_2_sha3: 1
hw.optional.armv8_3_compnum: 1
hw.optional.watchpoint: 4
hw.optional.breakpoint: 6
hw.optional.armv8_crc32: 1
hw.optional.armv8_gpi: 1
hw.optional.AdvSIMD: 1
hw.optional.AdvSIMD_HPFPCvt: 1
hw.optional.ucnormal_mem: 1
hw.optional.arm64: 1
hw.features.allows_security_research: 0
hw.physicalcpu: 14
hw.physicalcpu_max: 14
hw.logicalcpu: 14
hw.logicalcpu_max: 14
hw.cputype: 16777228
hw.cpusubtype: 2
hw.cpu64bit_capable: 1
hw.cpufamily: 399882554
hw.cpusubfamily: 4
hw.cacheconfig: 14 1 4 0 0 0 0 0 0 0
hw.cachesize: 3534602240 65536 4194304 0 0 0 0 0 0 0
hw.pagesize: 16384
hw.pagesize32: 16384
hw.cachelinesize: 128
hw.l1icachesize: 131072
hw.l1dcachesize: 65536
hw.l2cachesize: 4194304
hw.tbfrequency: 24000000
hw.memsize_usable: 50779242496
hw.packages: 1
hw.osenvironment:
hw.ephemeral_storage: 0
hw.use_recovery_securityd: 0
hw.use_kernelmanagerd: 1
hw.serialdebugmode: 0
hw.nperflevels: 2
hw.targettype: J773s
FEAT_AFP
や FEAT_SME
に対応しているのが見て取れます。
FEAT_AFPを試す
Binary Hacks Rebootedのサンプルコードリポジトリーの中には、ArmのFEAT_AFPを試せるプログラムが入っています。動かしてみましょう。
$ git clone https://github.com/oreilly-japan/binary-hacks-rebooted.git
$ cd binary-hacks-rebooted/ch07_data/75_floating-point-and-isa/
$ clang -o arm-altfp arm-altfp.c
$ ./arm-altfp
0x1.0000001p-1022 * 0x1.ffffffep-1, which yields 0x1p-1022, raises UNDERFLOW; underflow is detected before rounding
FPCR.AH set.
0x1.0000001p-1022 * 0x1.ffffffep-1, which yields 0x1p-1022, does not raise UNDERFLOW; underflow is detected after rounding
FPCR.AHをセットすることで、アンダーフロー例外の発生条件が変わったことが確認できました。このサンプルコードはエミュレーターも実機もない状態で書いていたので、期待通りに動くことがわかって一安心です。
FEAT_AFPについては概要を「Binary Hacks Rebooted」に書きましたが、改めて深掘りする記事を書くかもしれません。
SMEを試す
「ArmのScalable Matrix Extension (SME)を試す」のコードも動かしてみたいです。ベクトル長を取得するプログラムをコンパイルしてみます。
$ clang -o veclen -march=armv8-a+sme veclen.c
Undefined symbols for architecture arm64:
"___arm_sme_state", referenced from:
_main in veclen-3ad8e2.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
リンクエラーが出ました。LinuxだとCのシンボルがそのままアセンブリーでも使われますが、macOSはアンダースコアが先頭につくので、足りないシンボルの先頭のアンダースコアの数は3個になります。
まあ、アレですね。CランタイムがSMEに対応していないんですね。じゃあSMEを使っているであろう Accelerate.framework
はどうしているのかというと、おそらくアセンブリーを直接書いているのだと思われます。Apple M4でSMEを使っている既存の文献も、アセンブリーを直で書いています。
- tzakharko/m4-sme-exploration: Exploring the scalable matrix extension of the Apple M4 processor
- Overview | Hello SME documentation
というわけで、現在のAppleの開発環境でSMEを使うには、アセンブリーを直で書く必要がありそうです。これについてはまたそのうち記事を書くかもしれません。
Wake on LAN
新しいMac miniは電源ボタンの位置が変わったことも話題になりました。そこで気になるのが、Wake on LANに対応しているか、ということです。
試した感じだと、対応してなさそうです。これはM1 Mac miniも同様(非対応)でした。本当は裏設定とかがあるのかもしれませんが、私は知りません。「設定」アプリの「エネルギー」の項目は次の状態です:
冒険は始まったばかりだ
4年前に初めてMac miniを買った時は「思ったよりは大きいな」と感じました。しかし、今回出た新しいMac miniは「mini」の名前に相応しいものになっていると思います。電源ボタンの位置やWake on LANはちょっと残念ですが、私は普段電源を入れっぱなしにするので、そんなに困らないでしょう。
新しいMac miniで、Haskell開発やら何やらを頑張っていきたいと思います。