FORTRANコンパイラーの実力
科学技術の数値計算はFORTRANで書かれたコードで実施されることが多い。これは歴史的なものである。NASAの人工衛星制御などや、top500の線形代数計算などもFORTRANで書かれたコードが多いと聞く。しかし、C言語やC++とかjava、最近ではpythonに書き直されたものも増加してきて、次第にFORTRANを使っている人は少なくなっているのかもしれない。
とはいえ、NASAが公開しているFortranで書かれたコードについて調べると、(レガシーも含めて)まだまだたくさんあるようだ。ちょっと検索しただけでも、東大の地球温暖化の流体シミュレーションとか、NASAの土星磁場のシミュレーションなど、いまだにFORTRANがメインストリームの研究現場で利用されているケースが見つかる。
global-hydrodynamics.github.io
ということで、gccに含まれているFortranコンパイラであるgfortranの性能について、最後に調査してみることにした。
M1チップでの計測
まずは、Apple M1 CPUでの性能を調べてみる。AppleシリコンチップはARMベースのSoCで、その中にM1というCPUが含まれている。したがって、-marchはarm系のオプションを指定することになる(詳しくはnote記事を参照してもらいたい)。
最初から飛ばしていこう!試行錯誤の末、コンパイルオプションは-O3 -mtune=nativeで最速を記録した。 ただし、Fortranの時間計測サブルーチンはデフォルトのものを利用した。ソースコードは次のような感じである。
program benchmark_fortran .... real :: T0, T1 call cpu_time(T0) ------------------------------- 計測したい部分 ------------------------------- call cpu_time(T1) print *, T1-T0 end program benchmark_fortran
比較するために、gccでも同じオプション系列で試してみた。最速は-O3 -mtune=native -march=armv8.4-aであった(M1チップはARM系列の算術命令を利用する)。
それぞれの平均値(最速値)は次のような感じであった。
3.741003e-06 (gfortran) vs. 4.308000e-06 (gcc)
両者共にμ秒のオーダーであるが、有効数字をみると「若干」gfortranの方が速いように見える。
次は分散を見てみよう。

Xeonにおける比較
最後にXeonにおけるCとFORTRANの比較を行ってみた。ナノ秒スケールの測定になるため、RDTSCによる測定が不可欠になるが、FORTRANにはネイティブでこの関数が組み込まれておらず、工夫が必要となる。しかし、やり方はある!(ChatGPTが教えてくれた→詳細はいつものようにnote記事にて。)
ということで、不幸中の幸いというべきか、苦労したおかげで、gfortranとgccを共通のrdtsc関数で測定できることになった。とはいえ、FortranにRDTSCを組み込む際の「不自然さ」はパフォーマンスに微妙な影響を与えるかもしれないのは百も承知である。とにかく、両者共に同じようなオーダーで実行できることを期待して測定してみた。
結果は次のとおりである。

10.38029e-09 (gfortran) vs. 6.745111e-09 (gcc)
となって、gccの方が速かったのである!両者ともにナノ秒のオーダーではあるが、gccは一桁、gfortranは二桁であった。四捨五入すれば、両者共に10ns程度の平均値を持つとはいえ、分散をみるとgccの方が速いといえるだろう。
しかし、RDTSCの組み込み方がCとFORTRANで非対称だった点は気になる。
とはいえ、両者共に、CPUの種類によらず「優秀な成績」であったといえるのは確かである。CであれFORTRANであれ、真剣な数値計算をやるなら、pythonよりもコンパイラ系の言語を選ぶべきだというのが、最終的な結論である。
とはいえ、注意する点が一つある。今回のベンチマークは三角関数の呼び出しについての測定であった。ゲームの演算や量子力学など、近年の数値計算の実力は線形代数の計算、つまり行列計算やベクトル計算で判断すべきである。機会があれば、今回やったようなベンチマークを線形代数で再度やってみたいものである。