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

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

このコミットは、Go言語のベンチマークスイートであるtest/bench/shootout/timing.logファイルを更新するものです。このログファイルは、Goコンパイラやランタイムの変更が各種ベンチマークのパフォーマンスに与える影響を記録するために使用されます。

コミット

commit 90d59c586197a2300188206e4bbe99bb714e1833
Author: Rob Pike <r@golang.org>
Date:   Tue May 29 11:01:50 2012 -0700

    test/bench/shootout/timing.log: update after recent compiler changes
    Moving panic out of line speeds up fannkuch almost a factor of two.
    Changes to bitwhacking code affect mandelbrot badly.
    
    R=golang-dev, bradfitz, rsc, r
    CC=golang-dev
    https://golang.org/cl/6258056

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

https://github.com/golang/go/commit/90d59c586197a2300188206e4bbe99bb714e1833

元コミット内容

このコミットの元々の内容は、test/bench/shootout/timing.logファイルを更新し、最近のコンパイラ変更によるベンチマーク結果を反映させることです。特に、以下の2つの主要な変更がパフォーマンスに与える影響が言及されています。

  1. panicのインライン化解除(out of line化): panic呼び出しをインライン化しないようにしたことで、fannkuchベンチマークが約2倍高速化しました。これは、コードの実行パスを単純化し、ループ内のオーバーヘッドを削減したためと考えられます。
  2. ビット操作コードの変更: ビット操作(bitwhacking)コードへの変更が、mandelbrotベンチマークに悪影響を与えました。これは、特定の最適化が逆効果になったか、あるいは新しいコードが以前のバージョンよりも効率的でなくなったことを示唆しています。

コミットメッセージには、関連するコードレビューへのリンク(https://golang.org/cl/6258056)も含まれており、これはこのコミットが反映しているコンパイラ変更の具体的な内容を示しています。

変更の背景

このコミットの背景には、Go言語のコンパイラとランタイムの継続的なパフォーマンス最適化の取り組みがあります。Go言語の開発チームは、言語の実行速度を向上させるために、様々なコンパイラ最適化やランタイムの改善を常に行っています。

具体的には、このコミットは以下の2つの主要なコンパイラ変更の結果を反映しています。

  1. panicindex呼び出しのインライン化解除: panicindexは、Goのランタイムが配列のインデックスが範囲外であるかなどをチェックするために使用する内部関数です。このようなチェックは、安全なコード実行のために不可欠ですが、頻繁に呼び出されるとパフォーマンスのボトルネックになる可能性があります。コンパイラがこれらの呼び出しを「out of line」(インライン化しない)にすることで、ホットパス(頻繁に実行されるコードパス)からこれらのチェックを外し、メインの実行フローをより高速に保つことができます。特にループ内でこれらのチェックが頻繁に行われる場合、この変更は大きな性能向上をもたらす可能性があります。コミットメッセージで参照されているhttp://codereview.appspot.com/6248049は、この変更に関するものです。
  2. ビット操作コードの変更: mandelbrotベンチマークは、複素数演算やビット操作を多用する計算集約的なタスクです。コンパイラがビット操作に関する最適化を変更した場合、それが特定のアルゴリズムのパフォーマンスに直接影響を与えることがあります。このコミットでは、その変更がmandelbrotのパフォーマンスを悪化させたことが示されています。コミットメッセージで参照されているhttp://codereview.appspot.com/6209077は、このビット操作コードの変更に関するものです。

これらの変更は、Goコンパイラの内部的な動作と最適化戦略の進化を示しており、その結果がベンチマークの数値として現れています。timing.logの更新は、これらの変更が実際のアプリケーションのパフォーマンスにどのように影響するかを追跡し、評価するための重要なステップです。

前提知識の解説

このコミットを理解するためには、以下の前提知識が役立ちます。

  • Go言語: Googleによって開発された静的型付けのコンパイル型言語。並行処理に強みを持つ。
  • コンパイラ最適化: コンパイラがソースコードを機械語に変換する際に、プログラムの実行速度を向上させたり、メモリ使用量を削減したりするために行う様々な変換。
  • インライン化 (Inlining): 関数呼び出しのオーバーヘッドを削減するために、呼び出し元のコードに関数の本体を直接埋め込むコンパイラ最適化手法。これにより、関数呼び出しのコスト(スタックフレームの作成、引数の渡しなど)がなくなるため、特に小さな関数や頻繁に呼び出される関数で性能向上が期待できる。
  • アウトオブライン化 (Out-of-line): インライン化の逆で、関数呼び出しを通常の関数呼び出しとして扱うこと。特定の条件下(例えば、関数が非常に大きい、またはエラーパスなど頻繁に実行されないパスにある場合)では、インライン化しない方がコードサイズやキャッシュ効率の観点から有利な場合がある。
  • panic: Go言語におけるランタイムエラーのメカニズム。プログラムの異常終了を引き起こす。panicは通常、予期せぬエラーや回復不可能なエラーが発生した場合に利用される。
  • ベンチマーク (Benchmark): プログラムやシステムの性能を測定するためのテスト。特定のタスクを実行し、その完了にかかる時間やリソース使用量を測定する。
  • Shootout Benchmarks: コンピュータ言語の性能を比較するために設計された一連のベンチマークプログラム。Go言語のベンチマークスイートには、これらのShootoutベンチマークが含まれていることが多い。
  • timing.log: ベンチマークの実行結果(実行時間など)を記録するログファイル。Go言語のプロジェクトでは、コンパイラやランタイムの変更がパフォーマンスに与える影響を追跡するためにこのようなログが用いられる。
  • u, s, r (user, system, real time): ベンチマーク結果でよく見られる時間測定の単位。
    • u (user time): プロセスがユーザーモードでCPUを実行した時間。
    • s (system time): プロセスがカーネルモードでCPUを実行した時間(システムコールなど)。
    • r (real time): プロセスが開始されてから終了するまでの実時間(壁時計時間)。これには、CPU実行時間だけでなく、I/O待ちや他のプロセスの実行時間も含まれる。
  • ビット操作 (Bitwhacking): ビット単位でのデータ操作。低レベルのプログラミングや、特定のアルゴリズム(例: マンデルブロ集合の計算)でパフォーマンスを最適化するために使用されることが多い。

技術的詳細

このコミットが反映している技術的変更は、Goコンパイラのコード生成と最適化戦略に深く関わっています。

panicindex呼び出しのアウトオブライン化

Go言語では、配列のインデックスアクセスなど、特定の操作でランタイムチェックが行われます。例えば、a[i]のようなアクセスでは、iが配列aの有効な範囲内にあるかどうかがチェックされます。このチェックが失敗すると、panicが発生します。

以前のコンパイラでは、これらのチェックに関連するpanicindexのような内部関数呼び出しがインライン化されることがありました。インライン化は通常、パフォーマンスを向上させますが、panicのような例外的なパスでは逆効果になることがあります。

  • インライン化のデメリット: panicパスがインライン化されると、コンパイラはエラーが発生しない「通常の」パスと、エラーが発生する「異常な」パスの両方を考慮してコードを生成する必要があります。これにより、生成されるコードのサイズが増加し、命令キャッシュの効率が低下する可能性があります。また、分岐予測器が誤ってエラーパスを予測してしまうと、パイプラインストールが発生し、パフォーマンスが低下します。
  • アウトオブライン化のメリット: panicindex呼び出しをアウトオブライン化することで、コンパイラは通常の実行パスをよりシンプルに、より効率的に最適化できます。エラーパスは別の場所に分離され、通常の実行フローには影響を与えません。これにより、特にループ内で頻繁にインデックスチェックが行われる場合、ループのホットパスがより高速になり、命令キャッシュの効率も向上します。

この変更がfannkuchベンチマークに大きな影響を与えたのは、fannkuchが多くの配列アクセスとループを含む計算集約的なアルゴリズムであるためと考えられます。インデックスチェックが頻繁に行われるため、その最適化が全体的な実行時間に大きく寄与したのでしょう。コミットメッセージにある「Moving panic out of line speeds up fannkuch almost a factor of two」という記述は、この最適化が非常に効果的であったことを示しています。

ビット操作コードの変更とmandelbrotへの影響

mandelbrotベンチマークは、マンデルブロ集合の計算を行います。これは、複素数演算と、その結果をピクセルにマッピングするためのビット操作を多用するタスクです。

コミットメッセージでは、「Changes to bitwhacking code affect mandelbrot badly」と述べられており、さらに「mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)」と具体的なコードレビューが参照されています。このコードレビュー(http://codereview.appspot.com/6209077)は、Goコンパイラの内部的なビット操作に関する最適化やコード生成の変更を示唆しています。

考えられる原因としては、以下のようなものがあります。

  • 特定の最適化の削除または変更: 以前はmandelbrotの計算に有利に働いていた特定のビット操作に関するコンパイラ最適化が、何らかの理由で削除されたか、あるいは変更された可能性があります。
  • コード生成の非効率化: 新しいコンパイラのコード生成戦略が、mandelbrotが使用する特定のビット操作パターンに対して、以前よりも非効率な機械語を生成するようになった可能性があります。
  • レジスタ割り当ての変更: ビット操作はレジスタを効率的に使用することが重要です。コンパイラのレジスタ割り当てアルゴリズムの変更が、mandelbrotのパフォーマンスに悪影響を与えた可能性も考えられます。

この変更がmandelbrotのパフォーマンスを大幅に悪化させたことは、コンパイラ最適化の複雑さを示しています。ある種のコードパターンに有利な変更が、別のコードパターンには不利に働くことがあるため、コンパイラ開発者は常にトレードオフを考慮する必要があります。

timing.logの構造とベンチマーク結果の解釈

timing.logファイルは、各ベンチマークの実行時間と、使用されたコンパイラ(gcはGoコンパイラ、gccgoはGCCベースのGoコンパイラ)を記録しています。

ログの各行は通常、以下の形式でベンチマーク結果を示します。

<ベンチマーク名> <引数>
    <コンパイラ> <ベンチマークプログラム>    <ユーザー時間>u <システム時間>s <実時間>r # <変化率>%
  • u: ユーザーCPU時間。プログラムがユーザーモードで実行された時間。
  • s: システムCPU時間。プログラムがカーネルモードで実行された時間(システムコールなど)。
  • r: 実時間(経過時間)。プログラムの開始から終了までの実際の時間。I/O待ちや他のプロセスの実行時間も含む。

変化率(# <変化率>%)は、以前の実行結果と比較して、現在の実行結果がどれだけ変化したかを示します。負の値は高速化、正の値は低速化を意味します。

このコミットで追加されたログエントリは、以下のベンチマークの結果を更新しています。

  • nbody: N体シミュレーション。gcコンパイラで約12%高速化。
  • binary-tree: バイナリツリーの操作。gcコンパイラで約19%高速化。
  • fannkuch: ファンクッチ数列の計算。gcコンパイラで約41%高速化。これは、panicindexのアウトオブライン化による大きな恩恵を示しています。
  • k-nucleotide: DNA配列のk-mer頻度計算。gcコンパイラで約6%低速化。
  • mandelbrot: マンデルブロ集合の計算。gcコンパイラで約65%低速化。これは、ビット操作コードの変更による悪影響を明確に示しています。
  • meteor: メテオコンテスト(パズル)。gcコンパイラで約13%高速化。

これらの数値は、Goコンパイラの内部的な変更が、様々な種類の計算負荷を持つプログラムに異なる影響を与えることを示しています。

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

このコミット自体は、Go言語のコンパイラやランタイムのソースコードを変更していません。 変更されているのは、ベンチマーク結果を記録するtest/bench/shootout/timing.logファイルのみです。

具体的には、timing.logファイルの末尾に、新しいベンチマーク結果のセクションが追加されています。このセクションは、http://codereview.appspot.com/6248049で導入されたpanicindex呼び出しのアウトオブライン化と、http://codereview.appspot.com/6209077で導入されたビット操作コードの変更が、各種ベンチマークに与える影響を記録しています。

追加された内容は以下の通りです。

--- a/test/bench/shootout/timing.log
+++ b/test/bench/shootout/timing.log
@@ -993,3 +993,32 @@ chameneos 6000000
  	gccgo -O2 chameneosredux.go	7.73u 7.53s 15.30r
  	gc chameneosredux	6.51u 0.00s 6.53r # - 14%
  
+# After http://codereview.appspot.com/6248049, moving panicindex
+# calls out of line (putting the likely code into a single path and shortening
+# loops). Significant changes since the last run (note: some are slower for
+# unrelated and as yet undiagnosed reasons):
+
+nbody -n 50000000
+	gc nbody	19.10u 0.01s 19.19r # -12%
+	gc_B nbody	19.19u 0.00s 19.23r # -12%
+
+binary-tree 15 # too slow to use 20
+	gc binary-tree	1.49u 0.01s 1.51r # -19%
+	
+fannkuch 12
+	gc fannkuch	60.79u 0.00s 60.92r # -41%
+	gc fannkuch-parallel	183.51u 0.01s 51.75r # -14%
+	gc_B fannkuch	51.68u 0.00s 51.79r # -3%
+
+k-nucleotide 1000000
+	gc k-nucleotide	9.74u 0.04s 9.80r # +6%
+	gc k-nucleotide-parallel	9.89u 0.05s 3.59r # +1%
+	gc_B k-nucleotide	9.39u 0.02s 9.43r # +2%
+
+mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)
+	gc mandelbrot	100.98u 0.00s 101.20r # +65%
+	gc_B mandelbrot	100.90u 0.01s 101.17r # +65%
+
+meteor 2098
+	gc meteor-contest	0.13u 0.00s 0.13r # -13%
+	gc_B meteor-contest	0.13u 0.00s 0.13r # -7%

この変更は、Goコンパイラのパフォーマンス改善の進捗を追跡するためのデータ更新であり、実際の機能変更ではありません。

コアとなるコードの解説

このコミット自体には、Go言語のコンパイラやランタイムの「コアとなるコード」の変更は含まれていません。このコミットは、既存のGoコンパイラとランタイムの変更によって生じたパフォーマンスの変化を記録するためのものです。

したがって、ここで解説すべき「コアとなるコード」は、このコミットが参照している以下のコードレビューで実際に行われた変更です。

  1. http://codereview.appspot.com/6248049: このコードレビューは、Goコンパイラがpanicindexなどのランタイムチェック呼び出しをどのように扱うかを変更するものです。具体的には、これらの呼び出しを「アウトオブライン」にすることで、通常の実行パスのコードサイズを削減し、命令キャッシュの効率を向上させ、分岐予測の精度を高めることを目的としています。これにより、特にループ内で頻繁にインデックスチェックが行われるようなコード(例: fannkuchベンチマーク)のパフォーマンスが大幅に向上します。

  2. http://codereview.appspot.com/6209077: このコードレビューは、Goコンパイラのビット操作に関するコード生成や最適化に影響を与える変更です。mandelbrotベンチマークは、複素数演算とビット操作を多用するため、この種の変更の影響を強く受けます。このコミットのログでは、この変更がmandelbrotのパフォーマンスを悪化させたことが示されており、コンパイラの最適化が特定のアルゴリズムに対して意図しない副作用をもたらす可能性があることを示しています。

これらのコードレビューで行われた変更は、Goコンパイラのバックエンド、特にコード生成フェーズや最適化フェーズにおける内部的なロジックに深く関わっています。コンパイラは、ソースコードの抽象構文木(AST)や中間表現(IR)を操作し、最終的にターゲットアーキテクチャの機械語を生成します。この過程で、インライン化、レジスタ割り当て、命令スケジューリング、ループ最適化など、様々な最適化が適用されます。

このコミットは、これらの複雑なコンパイラ最適化が実際のベンチマーク結果にどのように反映されるかを示す「結果報告」のような役割を果たしています。

関連リンク

  • Go言語の公式ウェブサイト: https://golang.org/
  • Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
  • Go言語のベンチマークに関するドキュメント: Go言語の公式ドキュメントやブログには、ベンチマークの実行方法や結果の解釈に関する情報が掲載されている場合があります。

参考にした情報源リンク

  • Go Code Review 6258056: このコミットが参照している主要なコードレビュー。 https://golang.org/cl/6258056
  • Go Code Review 6248049: panicindexのアウトオブライン化に関するコードレビュー。 http://codereview.appspot.com/6248049
  • Go Code Review 6209077: ビット操作コードの変更に関するコードレビュー。 http://codereview.appspot.com/6209077
  • The Computer Language Benchmarks Game: Shootoutベンチマークの元々の情報源。 https://benchmarksgame-team.pages.debian.net/benchmarksgame/
  • Go言語のコンパイラ最適化に関する一般的な情報: Go言語のブログ記事やカンファレンスの発表などで、コンパイラ最適化の具体的な手法やその効果について解説されていることがあります。
    • 例: "Go's work-stealing scheduler" や "Go's runtime and garbage collection" などのトピックに関連する記事。
  • CPU時間 (User, System, Real) の概念: オペレーティングシステムやプログラミングに関する一般的な知識。
    • 例: timeコマンドの出力に関するドキュメントなど。# [インデックス 13192] ファイルの概要

このコミットは、Go言語のベンチマークスイートであるtest/bench/shootout/timing.logファイルを更新するものです。このログファイルは、Goコンパイラやランタイムの変更が各種ベンチマークのパフォーマンスに与える影響を記録するために使用されます。

コミット

commit 90d59c586197a2300188206e4bbe99bb714e1833
Author: Rob Pike <r@golang.org>
Date:   Tue May 29 11:01:50 2012 -0700

    test/bench/shootout/timing.log: update after recent compiler changes
    Moving panic out of line speeds up fannkuch almost a factor of two.
    Changes to bitwhacking code affect mandelbrot badly.
    
    R=golang-dev, bradfitz, rsc, r
    CC=golang-dev
    https://golang.org/cl/6258056

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

https://github.com/golang/go/commit/90d59c586197a2300188206e4bbe99bb714e1833

元コミット内容

このコミットの元々の内容は、test/bench/shootout/timing.logファイルを更新し、最近のコンパイラ変更によるベンチマーク結果を反映させることです。特に、以下の2つの主要な変更がパフォーマンスに与える影響が言及されています。

  1. panicのインライン化解除(out of line化): panic呼び出しをインライン化しないようにしたことで、fannkuchベンチマークが約2倍高速化しました。これは、コードの実行パスを単純化し、ループ内のオーバーヘッドを削減したためと考えられます。
  2. ビット操作コードの変更: ビット操作(bitwhacking)コードへの変更が、mandelbrotベンチマークに悪影響を与えました。これは、特定の最適化が逆効果になったか、あるいは新しいコードが以前のバージョンよりも効率的でなくなったことを示唆しています。

コミットメッセージには、関連するコードレビューへのリンク(https://golang.org/cl/6258056)も含まれており、これはこのコミットが反映しているコンパイラ変更の具体的な内容を示しています。

変更の背景

このコミットの背景には、Go言語のコンパイラとランタイムの継続的なパフォーマンス最適化の取り組みがあります。Go言語の開発チームは、言語の実行速度を向上させるために、様々なコンパイラ最適化やランタイムの改善を常に行っています。

具体的には、このコミットは以下の2つの主要なコンパイラ変更の結果を反映しています。

  1. panicindex呼び出しのインライン化解除: panicindexは、Goのランタイムが配列のインデックスが範囲外であるかなどをチェックするために使用する内部関数です。このようなチェックは、安全なコード実行のために不可欠ですが、頻繁に呼び出されるとパフォーマンスのボトルネックになる可能性があります。コンパイラがこれらの呼び出しを「out of line」(インライン化しない)にすることで、ホットパス(頻繁に実行されるコードパス)からこれらのチェックを外し、メインの実行フローをより高速に保つことができます。特にループ内でこれらのチェックが頻繁に行われる場合、この変更は大きな性能向上をもたらす可能性があります。コミットメッセージで参照されているhttp://codereview.appspot.com/6248049は、この変更に関するものです。
  2. ビット操作コードの変更: mandelbrotベンチマークは、複素数演算やビット操作を多用する計算集約的なタスクです。コンパイラがビット操作に関する最適化を変更した場合、それが特定のアルゴリズムのパフォーマンスに直接影響を与えることがあります。このコミットでは、その変更がmandelbrotのパフォーマンスを悪化させたことが示されています。コミットメッセージで参照されているhttp://codereview.appspot.com/6209077は、このビット操作コードの変更に関するものです。

これらの変更は、Goコンパイラの内部的な動作と最適化戦略の進化を示しており、その結果がベンチマークの数値として現れています。timing.logの更新は、これらの変更が実際のアプリケーションのパフォーマンスにどのように影響するかを追跡し、評価するための重要なステップです。

前提知識の解説

このコミットを理解するためには、以下の前提知識が役立ちます。

  • Go言語: Googleによって開発された静的型付けのコンパイル型言語。並行処理に強みを持つ。
  • コンパイラ最適化: コンパイラがソースコードを機械語に変換する際に、プログラムの実行速度を向上させたり、メモリ使用量を削減したりするために行う様々な変換。
  • インライン化 (Inlining): 関数呼び出しのオーバーヘッドを削減するために、呼び出し元のコードに関数の本体を直接埋め込むコンパイラ最適化手法。これにより、関数呼び出しのコスト(スタックフレームの作成、引数の渡しなど)がなくなるため、特に小さな関数や頻繁に呼び出される関数で性能向上が期待できる。
  • アウトオブライン化 (Out-of-line): インライン化の逆で、関数呼び出しを通常の関数呼び出しとして扱うこと。特定の条件下(例えば、関数が非常に大きい、またはエラーパスなど頻繁に実行されないパスにある場合)では、インライン化しない方がコードサイズやキャッシュ効率の観点から有利な場合がある。
  • panic: Go言語におけるランタイムエラーのメカニズム。プログラムの異常終了を引き起こす。panicは通常、予期せぬエラーや回復不可能なエラーが発生した場合に利用される。
  • ベンチマーク (Benchmark): プログラムやシステムの性能を測定するためのテスト。特定のタスクを実行し、その完了にかかる時間やリソース使用量を測定する。
  • Shootout Benchmarks: コンピュータ言語の性能を比較するために設計された一連のベンチマークプログラム。Go言語のベンチマークスイートには、これらのShootoutベンチマークが含まれていることが多い。
  • timing.log: ベンチマークの実行結果(実行時間など)を記録するログファイル。Go言語のプロジェクトでは、コンパイラやランタイムの変更がパフォーマンスに与える影響を追跡するためにこのようなログが用いられる。
  • u, s, r (user, system, real time): ベンチマーク結果でよく見られる時間測定の単位。
    • u (user time): プロセスがユーザーモードでCPUを実行した時間。
    • s (system time): プロセスがカーネルモードでCPUを実行した時間(システムコールなど)。
    • r (real time): プロセスが開始されてから終了するまでの実時間(壁時計時間)。これには、CPU実行時間だけでなく、I/O待ちや他のプロセスの実行時間も含まれる。
  • ビット操作 (Bitwhacking): ビット単位でのデータ操作。低レベルのプログラミングや、特定のアルゴリズム(例: マンデルブロ集合の計算)でパフォーマンスを最適化するために使用されることが多い。

技術的詳細

このコミットが反映している技術的変更は、Goコンパイラのコード生成と最適化戦略に深く関わっています。

panicindex呼び出しのアウトオブライン化

Go言語では、配列のインデックスアクセスなど、特定の操作でランタイムチェックが行われます。例えば、a[i]のようなアクセスでは、iが配列aの有効な範囲内にあるかどうかがチェックされます。このチェックが失敗すると、panicが発生します。

以前のコンパイラでは、これらのチェックに関連するpanicindexのような内部関数呼び出しがインライン化されることがありました。インライン化は通常、パフォーマンスを向上させますが、panicのような例外的なパスでは逆効果になることがあります。

  • インライン化のデメリット: panicパスがインライン化されると、コンパイラはエラーが発生しない「通常の」パスと、エラーが発生する「異常な」パスの両方を考慮してコードを生成する必要があります。これにより、生成されるコードのサイズが増加し、命令キャッシュの効率が低下する可能性があります。また、分岐予測器が誤ってエラーパスを予測してしまうと、パイプラインストールが発生し、パフォーマンスが低下します。
  • アウトオブライン化のメリット: panicindex呼び出しをアウトオブライン化することで、コンパイラは通常の実行パスをよりシンプルに、より効率的に最適化できます。エラーパスは別の場所に分離され、通常の実行フローには影響を与えません。これにより、特にループ内で頻繁にインデックスチェックが行われる場合、ループのホットパスがより高速になり、命令キャッシュの効率も向上します。

この変更がfannkuchベンチマークに大きな影響を与えたのは、fannkuchが多くの配列アクセスとループを含む計算集約的なアルゴリズムであるためと考えられます。インデックスチェックが頻繁に行われるため、その最適化が全体的な実行時間に大きく寄与したのでしょう。コミットメッセージにある「Moving panic out of line speeds up fannkuch almost a factor of two」という記述は、この最適化が非常に効果的であったことを示しています。

ビット操作コードの変更とmandelbrotへの影響

mandelbrotベンチマークは、マンデルブロ集合の計算を行います。これは、複素数演算と、その結果をピクセルにマッピングするためのビット操作を多用するタスクです。

コミットメッセージでは、「Changes to bitwhacking code affect mandelbrot badly」と述べられており、さらに「mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)」と具体的なコードレビューが参照されています。このコードレビュー(http://codereview.appspot.com/6209077)は、Goコンパイラの内部的なビット操作に関する最適化やコード生成の変更を示唆しています。

考えられる原因としては、以下のようなものがあります。

  • 特定の最適化の削除または変更: 以前はmandelbrotの計算に有利に働いていた特定のビット操作に関するコンパイラ最適化が、何らかの理由で削除されたか、あるいは変更された可能性があります。
  • コード生成の非効率化: 新しいコンパイラのコード生成戦略が、mandelbrotが使用する特定のビット操作パターンに対して、以前よりも非効率な機械語を生成するようになった可能性があります。
  • レジスタ割り当ての変更: ビット操作はレジスタを効率的に使用することが重要です。コンパイラのレジスタ割り当てアルゴリズムの変更が、mandelbrotのパフォーマンスに悪影響を与えた可能性も考えられます。

この変更がmandelbrotのパフォーマンスを大幅に悪化させたことは、コンパイラ最適化の複雑さを示しています。ある種のコードパターンに有利な変更が、別のコードパターンには不利に働くことがあるため、コンパイラ開発者は常にトレードオフを考慮する必要があります。

timing.logの構造とベンチマーク結果の解釈

timing.logファイルは、各ベンチマークの実行時間と、使用されたコンパイラ(gcはGoコンパイラ、gccgoはGCCベースのGoコンパイラ)を記録しています。

ログの各行は通常、以下の形式でベンチマーク結果を示します。

<ベンチマーク名> <引数>
    <コンパイラ> <ベンチマークプログラム>    <ユーザー時間>u <システム時間>s <実時間>r # <変化率>%
  • u: ユーザーCPU時間。プログラムがユーザーモードで実行された時間。
  • s: システムCPU時間。プログラムがカーネルモードで実行された時間(システムコールなど)。
  • r: 実時間(経過時間)。プログラムの開始から終了までの実際の時間。I/O待ちや他のプロセスの実行時間も含む。

変化率(# <変化率>%)は、以前の実行結果と比較して、現在の実行結果がどれだけ変化したかを示します。負の値は高速化、正の値は低速化を意味します。

このコミットで追加されたログエントリは、以下のベンチマークの結果を更新しています。

  • nbody: N体シミュレーション。gcコンパイラで約12%高速化。
  • binary-tree: バイナリツリーの操作。gcコンパイラで約19%高速化。
  • fannkuch: ファンクッチ数列の計算。gcコンパイラで約41%高速化。これは、panicindexのアウトオブライン化による大きな恩恵を示しています。
  • k-nucleotide: DNA配列のk-mer頻度計算。gcコンパイラで約6%低速化。
  • mandelbrot: マンデルブロ集合の計算。gcコンパイラで約65%低速化。これは、ビット操作コードの変更による悪影響を明確に示しています。
  • meteor: メテオコンテスト(パズル)。gcコンパイラで約13%高速化。

これらの数値は、Goコンパイラの内部的な変更が、様々な種類の計算負荷を持つプログラムに異なる影響を与えることを示しています。

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

このコミット自体は、Go言語のコンパイラやランタイムのソースコードを変更していません。 変更されているのは、ベンチマーク結果を記録するtest/bench/shootout/timing.logファイルのみです。

具体的には、timing.logファイルの末尾に、新しいベンチマーク結果のセクションが追加されています。このセクションは、http://codereview.appspot.com/6248049で導入されたpanicindex呼び出しのアウトオブライン化と、http://codereview.appspot.com/6209077で導入されたビット操作コードの変更が、各種ベンチマークに与える影響を記録しています。

追加された内容は以下の通りです。

--- a/test/bench/shootout/timing.log
+++ b/test/bench/shootout/timing.log
@@ -993,3 +993,32 @@ chameneos 6000000
  	gccgo -O2 chameneosredux.go	7.73u 7.53s 15.30r
  	gc chameneosredux	6.51u 0.00s 6.53r # - 14%
  
+# After http://codereview.appspot.com/6248049, moving panicindex
+# calls out of line (putting the likely code into a single path and shortening
+# loops). Significant changes since the last run (note: some are slower for
+# unrelated and as yet undiagnosed reasons):
+
+nbody -n 50000000
+	gc nbody	19.10u 0.01s 19.19r # -12%
+	gc_B nbody	19.19u 0.00s 19.23r # -12%
+
+binary-tree 15 # too slow to use 20
+	gc binary-tree	1.49u 0.01s 1.51r # -19%
+	
+fannkuch 12
+	gc fannkuch	60.79u 0.00s 60.92r # -41%
+	gc fannkuch-parallel	183.51u 0.01s 51.75r # -14%
+	gc_B fannkuch	51.68u 0.00s 51.79r # -3%
+
+k-nucleotide 1000000
+	gc k-nucleotide	9.74u 0.04s 9.80r # +6%
+	gc k-nucleotide-parallel	9.89u 0.05s 3.59r # +1%
+	gc_B k-nucleotide	9.39u 0.02s 9.43r # +2%
+
+mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)
+	gc mandelbrot	100.98u 0.00s 101.20r # +65%
+	gc_B mandelbrot	100.90u 0.01s 101.17r # +65%
+
+meteor 2098
+	gc meteor-contest	0.13u 0.00s 0.13r # -13%
+	gc_B meteor-contest	0.13u 0.00s 0.13r # -7%

この変更は、Goコンパイラのパフォーマンス改善の進捗を追跡するためのデータ更新であり、実際の機能変更ではありません。

コアとなるコードの解説

このコミット自体には、Go言語のコンパイラやランタイムの「コアとなるコード」の変更は含まれていません。このコミットは、既存のGoコンパイラとランタイムの変更によって生じたパフォーマンスの変化を記録するためのものです。

したがって、ここで解説すべき「コアとなるコード」は、このコミットが参照している以下のコードレビューで実際に行われた変更です。

  1. http://codereview.appspot.com/6248049: このコードレビューは、Goコンパイラがpanicindexなどのランタイムチェック呼び出しをどのように扱うかを変更するものです。具体的には、これらの呼び出しを「アウトオブライン」にすることで、通常の実行パスのコードサイズを削減し、命令キャッシュの効率を向上させ、分岐予測の精度を高めることを目的としています。これにより、特にループ内で頻繁にインデックスチェックが行われるようなコード(例: fannkuchベンチマーク)のパフォーマンスが大幅に向上します。

  2. http://codereview.appspot.com/6209077: このコードレビューは、Goコンパイラのビット操作に関するコード生成や最適化に影響を与える変更です。mandelbrotベンチマークは、複素数演算とビット操作を多用するため、この種の変更の影響を強く受けます。このコミットのログでは、この変更がmandelbrotのパフォーマンスを悪化させたことが示されており、コンパイラの最適化が特定のアルゴリズムに対して意図しない副作用をもたらす可能性があることを示しています。

これらのコードレビューで行われた変更は、Goコンパイラのバックエンド、特にコード生成フェーズや最適化フェーズにおける内部的なロジックに深く関わっています。コンパイラは、ソースコードの抽象構文木(AST)や中間表現(IR)を操作し、最終的にターゲットアーキテクチャの機械語を生成します。この過程で、インライン化、レジスタ割り当て、命令スケジューリング、ループ最適化など、様々な最適化が適用されます。

このコミットは、これらの複雑なコンパイラ最適化が実際のベンチマーク結果にどのように反映されるかを示す「結果報告」のような役割を果たしています。

関連リンク

  • Go言語の公式ウェブサイト: https://golang.org/
  • Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
  • Go言語のベンチマークに関するドキュメント: Go言語の公式ドキュメントやブログには、ベンチマークの実行方法や結果の解釈に関する情報が掲載されている場合があります。

参考にした情報源リンク

  • Go Code Review 6258056: このコミットが参照している主要なコードレビュー。 https://golang.org/cl/6258056
  • Go Code Review 6248049: panicindexのアウトオブライン化に関するコードレビュー。 http://codereview.appspot.com/6248049
  • Go Code Review 6209077: ビット操作コードの変更に関するコードレビュー。 http://codereview.appspot.com/6209077
  • The Computer Language Benchmarks Game: Shootoutベンチマークの元々の情報源。 https://benchmarksgame-team.pages.debian.net/benchmarksgame/
  • Go言語のコンパイラ最適化に関する一般的な情報: Go言語のブログ記事やカンファレンスの発表などで、コンパイラ最適化の具体的な手法やその効果について解説されていることがあります。
    • 例: "Go's work-stealing scheduler" や "Go's runtime and garbage collection" などのトピックに関連する記事。
  • CPU時間 (User, System, Real) の概念: オペレーティングシステムやプログラミングに関する一般的な知識。
    • 例: timeコマンドの出力に関するドキュメントなど。