追記 R6.6.30:このページの情報は古くなったので他所を参照して下さい。参考までに以下のページを挙げておきます。
天皇陛下のお誕生日を祝して M1 mac 購入
M1 mac を購入したので、Fortran をインストールしてみました。私は mac は生まれて初めてで右も左も分からぬ状態なので、話半分で読んでください。買ったのは一番安い macbook air 8G/256G/7GPU ので色は給食のアルマイトの食器の様なねずみ色のやつです。名前は Air ですが、ずっしり重くてどちらかというと Heavy Metal という感じです。
約1.29 kg~
約634g~
三種の Fortran
Arm 用 gfortran, Rosetta エミュレータで intel 用 gfortran および oneAPI の intel fortran の三種が動くことを確かめました。インストールはいずれもインストーラを動かすだけでできました。
簡単なプログラムで見たところ intel fortran の場合、エミュレーションで動いているにもかかわらず、第四世代 Haswell i7 の4倍くらいのスピードが出ています。同じプログラムでみると ARM 版 gfortran は x86_64 版 gfortran の 1.5 倍くらいの速さで、intel fortran と比較するとプログラムによって速かったり遅かったりします。
ARM ネイティブ gfortran が Rosetta のエミュレーションの intel fortran より遅いのは意外ですが、ネットを流れているベンチマークを見ると、ARM 版 gcc は clang より平均2倍くらい遅いようなので、 GNU コンパイラの問題なのかもしれません。また元々 gfortran は intel fortran より遅く5割増し位な感じなので、合わせるとそんなところかもしれません。
なお、Apple 版 intel fortran は昔から coarray をサポートせず oneAPI 版でもサポートされません。
インストール・メモ
intel fortran
Jacob Williams さんのツイートで intel fortran が動くことが分かっていました。
Testing #oneAPI #Fortran compiler on a new Apple Silicon Mac. Compilation is slow but it seems to work. Even beats my old i7 in this bspline-fortran benchmark. (and it isn't even native code since it's using Rosetta 2 to emulate the intel instructions). pic.twitter.com/pNP8r4G9L2
— Jacob Williams (@DegenerateConic) 2020年12月30日
以下のページから HPC Tool kit 用のオンライン版インストーラを取ってこれます。登録が必要ですが無料です。 fortran コンパイラだけでいいなら oneAPI base kit の方は要りません。ただ Intel MKL は base kit の方に入っているので、これも入れるならば base kit 用のインストーラも必要になります。
Mac 版は MPI その他が無く(多分そのせいで coarray もない... MPI 上に実装されているので)、選択できるのは C++ と Fortran のコンパイラだけです。Fortran コンパイラだけインストールしました。
コマンドライン用 Xcode というものが必要になるのですが、ifort でコンパイルしようとすると警告が出て自動でインストールしてくれます。
メモ コンパイラにパスを通すスクリプトを先に動かす必要があります。
. /opt/intel/oneapi/setvars.sh
ただライブラリへのパスが通っておらず、ネットを検索すると手動でライブラリ位置を指定せよと出てきました。Xcode の前に intel fortran をインストールしたせいかもしれません。
ifort -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib xxxx.f90
めんどくさいので .zshrc に alias を書いてみました。
alias ifort='ifort -L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib'
gfortran
奥村先生のページを参考にしました。 https://oku.edu.mie-u.ac.jp/~okumura/macosx/m1.htmloku.edu.mie-u.ac.jp
Homebrew というドブロク造りをイメージしたパッケージマネージャーを x86_64 用と arm64 用それぞれに、ページ画面に表示されたコマンド1行をターミナルにコピペ&実行でインストールして、その後それぞれで brew install gfortran を行えば gfortran がインストールされます。
ARM 版を優先したい場合、実行パスの優先順序を工夫する必要があります。
visual studio code
insider という所に行くと ARM 版が落とせます。
よく分からない形式の圧縮ファイルをクリックすると、実行ファイルらしきものが出てくるので、ええいままよとそれをアプリケーションのフォルダーにコピーしてみました。これでいいのかよく分かりません。クリックすると vs code が起動します。
visual studio code 起動後は Modern Fortran と Fortran IntelliSense の拡張機能を入れました。何か言われるままにクリックして、文法解釈用の fortls も別途インストールした気がします。漫然とクリックしたのでよく覚えていません。とりあえず問題なく動いています。
実行例
とりあえず昔のプログラムを動かしてみました。
module m_stamp ! use portlib ! MS-FPS4.0 implicit none logical :: first = .true. real(kind(0.0d0)) :: t0, t1 contains subroutine stamp(text) ! print time stamp character(len = *), intent(in) :: text character(len = 8) :: date character(len = 10) :: time if (first) then first = .false. call cpu_time(t0) ! t0 = timef() ! MS-FPS4.0 end if call cpu_time(t1) ! t1 = timef() ! MS-FPS4.0 call date_and_time(date, time) print '(6a, 6a, a, g15.3, 2a)', & date(1:4), '-', date(5:6), '-', date(7:8), ' ', & time(1:2), ':', time(3:4), ':', time(5:8), ' ', & ' cpu_time =', t1 - t0, '(sec) ::', text end subroutine stamp end module m_stamp module m_cg implicit none integer, parameter :: kd = kind(0.0d0) !double precision contains subroutine cg(a, b, x) ! conjugate gradient method real(kd), intent(in) :: a(:, :), b(:) real(kd), intent(in out) :: x(:) real(kd) :: alpha, beta, r2n, r2d, eb2, p(size(b)), q(size(b)), r(size(b)) integer :: i r = b - matmul(a, x) p = r r2n = dot_product(r, r) eb2 = epsilon(b) * dot_product(b, b) do i = 1, size(b) if ( r2n < eb2 ) exit r2d = r2n q = matmul(a, p) alpha = dot_product(p, r) / dot_product(p, q) x = x + alpha * p r = r - alpha * q r2n = dot_product(r, r) beta = r2n / r2d p = r + beta * p end do end subroutine cg end module m_cg program cg_main use m_cg use m_stamp implicit none integer, parameter :: ns = 2000 real(kd) :: a(ns, ns), b(ns), x(ns) integer :: i, j call stamp('make matrix') do i = 1, ns b(i) = 1.0_kd do j = i, ns ! givens matrix, x = (1, 0, 0, ... , 0)t a(i, j) = real( 2 * min(i, j) - 1, kd ) a(j, i) = a(i, j) end do end do call stamp('solve Ax = b') ! call random_seed() call random_number(x) ! starting vector call cg(a, b, x) x = matmul(a, x) - b print *, 'difference (rms) =', sqrt( dot_product(x, x) ) call stamp('normal end') end program cg_main
M1 Mac
gfortran (ARM64)
gfortran (Rosetta2)
[a] M1:~/fortran% ifort -O2 cg.f90 [a] M1:~/fortran% ./a.out 2021-02-24 02:07:14.7 cpu_time = 0.500E-05(sec) ::make matrix 2021-02-24 02:07:14.7 cpu_time = 0.182E-01(sec) ::solve Ax = b difference (rms) = 4.684681968851512E-007 2021-02-24 02:07:15.6 cpu_time = 0.945 (sec) ::normal end [a] M1:~/fortran% gfortran -O2 cg.f90 [a] M1:~/fortran% ./a.out 2021-02-24 02:07:24.3 cpu_time = 0.700E-05(sec) ::make matrix 2021-02-24 02:07:24.3 cpu_time = 0.137E-01(sec) ::solve Ax = b difference (rms) = 6.6372870430592568E-007 2021-02-24 02:07:26.1 cpu_time = 1.80 (sec) ::normal end [a] M1:~/fortran% arch -x86_64 /usr/local/bin/gfortran -O2 cg.f90 [a] M1:~/fortran% ./a.out 2021-02-24 02:07:34.2 cpu_time = 0.120E-04(sec) ::make matrix 2021-02-24 02:07:34.2 cpu_time = 0.218E-01(sec) ::solve Ax = b difference (rms) = 4.3568034320423338E-007 2021-02-24 02:07:36.4 cpu_time = 2.26 (sec) ::normal end
i7 4770
2021-02-24 02:08:36.8 cpu_time = 0.00 (sec) ::make matrix 2021-02-24 02:08:36.9 cpu_time = 0.469E-01(sec) ::solve Ax = b difference (rms) = 4.077532388488979E-007 2021-02-24 02:08:40.8 cpu_time = 3.95 (sec) ::normal end 続行するには何かキーを押してください . . .
追記: i7 4770 の計算時間が昔に比べて長くなって計算スピードが遅くなっていますが、実は MKL 付属の linpack benchmark なども遅くなっています。多分 intel chip の specter とかの対策のせいではないかと疑っているのですが面倒なので確かめていません。気のせいかもしれません。