Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 13223] ファイルの概要

このコミットは、Go言語のベンチマークスイートであるtest/bench/shootoutにおけるパフォーマンス改善を目的としています。特に、mandelbrotベンチマークにおいて、レジスタ間のMOVSD命令の回避による速度向上が主要な変更点ですが、他にも様々な最適化が含まれています。

コミット

  • コミットハッシュ: 6f3ffd4d799492612cd8283d5103f6db433cfca8
  • Author: Rob Pike r@golang.org
  • Date: Wed May 30 12:31:28 2012 -0700
  • コミットメッセージ:
    test/bench/shootout: more speedups
    Most significant in mandelbrot, from avoiding MOVSD between registers,
    but there are others.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/6258063
    

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/6f3ffd4d799492612cd8283d5103f6db433cfca8

元コミット内容

このコミットの主な目的は、Go言語のベンチマークスイートであるtest/bench/shootoutのパフォーマンスを向上させることです。特に、mandelbrotベンチマークにおける浮動小数点演算の最適化が強調されており、レジスタ間のMOVSD命令の不必要な使用を避けることで、顕著な速度向上が達成されました。これに加えて、他のベンチマークでも様々な速度向上が見られます。

変更の背景

この変更の背景には、Go言語のランタイムおよびコンパイラの継続的なパフォーマンス最適化の取り組みがあります。特に、数値計算や浮動小数点演算を多用するベンチマーク(例: mandelbrot)において、より効率的な機械語コードを生成することが求められていました。

以前のコミット(http://codereview.appspot.com/6261051)で浮動小数点定数に対するコード生成が元に戻された後、mandelbrotのパフォーマンスが以前の水準に戻っていましたが、このコミット(http://codereview.appspot.com/6248068に関連)では、MOVSD命令の最適化を通じて、さらなる改善を目指しました。

MOVSD命令の回避は、CPUのレジスタ間で浮動小数点値を移動させる際のオーバーヘッドを削減し、特にループ内で頻繁に実行されるような計算において、全体的な実行時間を短縮する効果があります。また、ガベージコレクションやPrintfなどの他の領域での改善も、全体的な速度向上に寄与しています。

前提知識の解説

MOVSD命令

MOVSDは、x86-64アーキテクチャにおけるSSE2(Streaming SIMD Extensions 2)命令セットの一部で、64ビットの倍精度浮動小数点数(double-precision floating-point number)を移動させるための命令です。通常、メモリとレジスタ間、またはレジスタ間でデータを移動させる際に使用されます。

このコミットで言及されている「レジスタ間のMOVSDの回避」とは、コンパイラが不必要に浮動小数点値をレジスタ間でコピーするようなコードを生成するのを防ぐことを指します。CPUのレジスタは非常に高速な記憶領域ですが、レジスタ間のデータ移動であっても、それが頻繁に発生するとオーバーヘッドとなり、パフォーマンスに影響を与える可能性があります。特に、同じ値を繰り返し使用する場合や、演算結果をすぐに次の演算に使う場合など、レジスタに値が既に存在しているにもかかわらず、不必要なMOVSD命令が挿入されると、CPUのパイプライン効率が低下し、実行速度が遅くなります。

コンパイラの最適化において、このような冗長な命令を削除したり、より効率的な命令シーケンスに置き換えたりすることは、プログラムの実行速度を向上させる上で非常に重要です。

Go言語のベンチマークとshootout

Go言語には、標準でベンチマークを記述・実行するためのフレームワークが組み込まれています。go test -bench=.コマンドなどでベンチマークを実行できます。

shootoutは、The Computer Language Benchmarks Game (旧称: The Great Computer Language Shootout) のベンチマークスイートを指します。これは、様々なプログラミング言語のパフォーマンスを比較するために設計された一連のプログラム群です。Go言語のプロジェクト内でtest/bench/shootoutディレクトリにあるファイルは、これらのベンチマークをGo言語で実装したものであり、Go言語のランタイムやコンパイラのパフォーマンスを測定・追跡するために使用されます。

gcgc_B

timing.logに記載されているgcgc_Bは、Go言語のベンチマーク実行時のコンパイラオプションまたはビルドモードを示唆しています。

  • gc: これはGo言語の標準コンパイラ(go tool compile)を指します。通常、Goプログラムをビルドする際に使用されるデフォルトのコンパイラです。
  • gc_B: これは、おそらく特定のビルドフラグや最適化レベル、あるいは異なるガベージコレクション設定など、標準のgcとは異なる設定でビルドされたバイナリを指すと考えられます。文脈から、これはベンチマークの比較対象として、あるいは特定の最適化が適用されたバージョンとして使用されている可能性があります。

timing.log

timing.logは、Go言語のベンチマーク結果を記録するためのログファイルです。このファイルには、各ベンチマークプログラムの実行時間(ユーザー時間、システム時間、実時間)が記録され、過去の実行結果との比較(パーセンテージでの改善/悪化)も示されます。これにより、コード変更がパフォーマンスに与える影響を追跡することができます。

技術的詳細

このコミットの技術的詳細の核心は、Goコンパイラが生成する機械語コードの品質向上にあります。特に、浮動小数点演算において、レジスタ間の不必要なMOVSD命令を削減することで、CPUの実行効率を高めています。

浮動小数点演算は、特に科学技術計算やグラフィックス処理など、多くのアプリケーションで重要な役割を果たします。これらの演算が頻繁に行われる場合、コンパイラが生成するアセンブリコードの効率が全体のパフォーマンスに大きく影響します。

具体的には、Goコンパイラが、ある浮動小数点値を計算し、その結果を別のレジスタに移動させる必要がある場合に、既にその値が適切なレジスタに存在しているにもかかわらず、冗長なMOVSD命令を挿入してしまうケースがあったと考えられます。このような冗長な命令は、CPUの命令デコーダや実行ユニットに余分な負荷をかけ、パイプラインストールを引き起こす可能性があります。

このコミットでは、コンパイラのバックエンド(コード生成部分)が改善され、このような不必要なMOVSD命令の生成が抑制されるようになりました。これにより、CPUはより効率的に浮動小数点演算を実行できるようになり、特にmandelbrotのような浮動小数点演算がボトルネックとなるベンチマークで顕著な速度向上が見られました。

また、コミットメッセージには「Plus some other timing changes that have crept in from other speedups, from garbage collection to Printf.」とあり、ガベージコレクション(GC)の改善やPrintf関数の最適化など、他の領域での速度向上も全体的なパフォーマンスに寄与していることが示唆されています。これらの改善は、Goランタイムの様々な側面における継続的な最適化努力の一環です。

コアとなるコードの変更箇所

このコミットで変更されたコアとなるファイルは、test/bench/shootout/timing.logです。

--- a/test/bench/shootout/timing.log
+++ b/test/bench/shootout/timing.log
@@ -1023,6 +1023,7 @@ meteor 2098
  	gc meteor-contest	0.13u 0.00s 0.13r # -13%
  	gc_B meteor-contest	0.13u 0.00s 0.13r # -7%
 
+# May 30, 2012.
 # After http://codereview.appspot.com/6261051, restoring old code generated
 # for floating-point constants. Mandelbrot is back to its previous numbers.
 
@@ -1031,3 +1032,34 @@ mandelbrot 16000
  	gccgo -O2 mandelbrot.go	41.72u 0.01s 41.90r
  	gc mandelbrot	60.62u 0.00s 60.76r
  	gc_B mandelbrot	60.68u 0.00s 60.82r
++
+# May 30, 2012.
+# After http://codereview.appspot.com/6248068, better FP code
+# by avoiding MOVSD between registers.
+# Plus some other timing changes that have crept in from other speedups,
+# from garbage collection to Printf.
++
+fasta -n 25000000
+	gc fasta	1.76u 0.00s 1.76r # -12%
+	gc_B fasta	1.71u 0.00s 1.72r # -12%
++
+nbody -n 50000000
+	gc nbody	17.56u 0.00s 17.60r # -8%
+	gc_B nbody	17.30u 0.00s 17.34r # -10%
++
+fannkuch 12
+	gc fannkuch-parallel	155.92u 0.01s 44.05r # -15%
++
+k-nucleotide 1000000
+	gc k-nucleotide	9.22u 0.01s 9.26r # -5%
+	gc k-nucleotide-parallel	9.23u 0.03s 3.26r # -9%
+	gc_B k-nucleotide	9.22u 0.03s 9.28r # -2%
++
+mandelbrot 16000
+	gc mandelbrot	44.80u 0.00s 44.90r # -27%
+	gc_B mandelbrot	44.81u 0.00s 44.92r # -26%
++
+pidigits 10000
+	gc pidigits	3.51u 0.00s 3.52r # -6%
+	gc_B pidigits	3.51u 0.00s 3.52r # -6%

このファイル自体はGoのソースコードではなく、ベンチマークの実行結果を記録したログファイルです。このコミットでは、新しいベンチマーク結果が追記されています。

コアとなるコードの解説

test/bench/shootout/timing.logへの変更は、Go言語のベンチマークスイートにおける様々なプログラムのパフォーマンス改善を数値で示しています。各エントリは以下の形式で構成されています。

<ベンチマーク名> <引数>
	<コンパイラ/ビルドモード> <ベンチマークプログラム名>	<ユーザー時間>u <システム時間>s <実時間>r # <改善/悪化率>%
  • u (user time): ユーザーモードでCPUがプログラムの実行に費やした時間。
  • s (system time): カーネルモードでCPUがプログラムの実行に費やした時間(システムコールなど)。
  • r (real time): プログラムの開始から終了までの実時間(壁時計時間)。
  • # <改善/悪化率>%: 以前のベンチマーク結果と比較したパフォーマンスの変化率。負の値は速度向上(実行時間の短縮)を示します。

このコミットで追加されたエントリは、2012年5月30日時点での最新のベンチマーク結果を示しており、特にMOVSD命令の回避による浮動小数点コードの改善や、ガベージコレクション、Printfなどの他の最適化が反映されています。

注目すべきは、mandelbrotベンチマークの改善率です。

mandelbrot 16000
	gc mandelbrot	44.80u 0.00s 44.90r # -27%
	gc_B mandelbrot	44.81u 0.00s 44.92r # -26%

これは、mandelbrotベンチマークがgcコンパイラでビルドされた場合、以前と比較して実行時間が27%短縮されたことを意味します。gc_Bビルドでも26%の改善が見られます。この大幅な改善は、コミットメッセージで述べられている「avoiding MOVSD between registers」の最適化が、mandelbrotのような浮動小数点演算が中心のプログラムに大きな影響を与えたことを裏付けています。

他にも、fastanbodyfannkuchk-nucleotidepidigitsといった他のベンチマークでも、数パーセントから十数パーセントの速度向上が記録されており、これは浮動小数点演算の最適化だけでなく、ガベージコレクションやその他のランタイム最適化が全体的なパフォーマンスに寄与していることを示しています。

関連リンク

参考にした情報源リンク