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

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

このコミットは、Go言語のベンチマークスイートであるtest/bench/shootout内のpidigitsベンチマークのパフォーマンス改善と、関連するスクリプトのバグ修正に関するものです。特に、package bigにおけるアセンブラ最適化がpidigitsベンチマークの実行速度を大幅に向上させたことが報告されています。

コミット

commit d199c34cf0b9c536ffd0167159fa50be2261935c
Author: Rob Pike <r@golang.org>
Date:   Tue Aug 28 15:33:05 2012 -0700

    test/bench/shootout: pidigits is much faster
    Also fix a bug in the script (s/runonly/run/)
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/6501051

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

https://github.com/golang/go/commit/d199c34cf0b9c536ffd0167159fa50be2261935c

元コミット内容

test/bench/shootout: pidigits is much faster
Also fix a bug in the script (s/runonly/run/)

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6501051

変更の背景

このコミットの背景には、Go言語の標準ライブラリであるpackage bigにおける性能改善があります。package bigは、任意精度の整数、有理数、浮動小数点数を扱うためのパッケージであり、数値計算を多用するアプリケーションにおいてその性能は非常に重要です。pidigitsベンチマークは、円周率の桁数を計算するもので、このような任意精度演算の性能を測るのに適しています。

コミットメッセージにある「After some assembler work in package big.」という記述から、package bigの内部でアセンブラレベルの最適化が行われたことが示唆されます。これは、Go言語のランタイムや標準ライブラリにおいて、特定のクリティカルなパスの性能を最大限に引き出すために、Goのアセンブラ(Plan 9アセンブラの派生)を用いて手書きのアセンブリコードが導入されたことを意味します。このような低レベルの最適化は、特に大規模な数値計算において顕著な性能向上をもたらす可能性があります。

また、ベンチマークスクリプト自体のバグ修正も行われています。これは、性能改善が正しく測定・報告されるようにするための、ベンチマーク環境の健全性を保つための変更です。

前提知識の解説

  • Go言語のpackage big: Go言語の標準ライブラリの一つで、任意精度の数値(整数、有理数、浮動小数点数)を扱うためのパッケージです。通常のGoの組み込み型(int, float64など)では表現できない、非常に大きな数値や高い精度が求められる計算に使用されます。例えば、暗号通貨、科学技術計算、金融アプリケーションなどで利用されます。
  • ベンチマーク (Benchmark): ソフトウェアやシステムの性能を測定するためのテストです。特定のタスクを実行し、その完了にかかる時間やリソース消費量を計測することで、性能のボトルネックを特定したり、最適化の効果を評価したりします。
  • Shootoutベンチマーク: The Computer Language Benchmarks Game (旧称: The Great Computer Language Shootout) のベンチマークスイートを指します。これは、様々なプログラミング言語間で共通のアルゴリズムを実装し、その性能を比較するためのものです。pidigitsはその中の一つのベンチマークであり、円周率の桁数を計算することで、主に任意精度演算や文字列操作の性能を評価します。
  • アセンブラ (Assembler): アセンブリ言語で書かれたプログラムを機械語に変換するプログラムです。アセンブリ言語は、CPUの命令セットに直接対応する低レベルのプログラミング言語であり、特定の処理を非常に高速に実行するために手書きで記述されることがあります。Go言語では、Plan 9アセンブラの派生が使用されます。
  • timing.log: ベンチマークの実行結果(実行時間など)が記録されるログファイルです。このファイルに新しいエントリが追加されることで、性能改善が数値として示されます。
  • timing.sh: ベンチマークを実行するためのシェルスクリプトです。このスクリプト内で、各ベンチマークの実行コマンドが定義されています。
  • runonlyrun: ベンチマークスクリプト内で使用される関数またはコマンドのプレフィックスと考えられます。runonlyは特定のベンチマークのみを実行する、あるいは特定の条件でのみ実行するといった意味合いで使われていた可能性がありますが、このコミットではrunに修正されており、常に実行されるように変更されたことを示唆しています。

技術的詳細

このコミットの主要な技術的ポイントは、package bigにおけるアセンブラ最適化がpidigitsベンチマークの性能に与えた影響です。

pidigitsベンチマークは、Spigotアルゴリズムなどを用いて円周率の桁数を計算します。このアルゴリズムは、大きな数値を扱う多倍長整数演算を頻繁に実行します。Go言語のpackage bigは、これらの多倍長整数演算をソフトウェアで実装していますが、特にパフォーマンスが要求される部分では、手書きのアセンブリコードを導入することで、CPUの特定の命令(例:乗算、除算、加算、減算におけるキャリーやボローの処理)を直接利用し、Goのコンパイラが生成するコードよりも効率的な実行パスを実現できます。

コミットメッセージの「After some assembler work in package big.」は、まさにこのアセンブラによる最適化が完了し、その効果がpidigitsベンチマークに現れたことを示しています。アセンブラによる最適化は、通常、以下のような効果をもたらします。

  1. 命令レベルの最適化: CPUの特定の命令を最大限に活用し、より少ないクロックサイクルで処理を完了させます。
  2. レジスタ割り当ての最適化: 頻繁に使用される値をCPUのレジスタに保持することで、メモリへのアクセス回数を減らし、高速化を図ります。
  3. パイプラインの最適化: CPUの命令パイプラインを効率的に利用し、並列性を高めます。

timing.logの変更を見ると、pidigits 10000の実行時間が大幅に短縮されていることがわかります。

  • 変更前: gc pidigits 3.51u 0.00s 3.52r # -6%
  • 変更後: gc pidigits 2.85u 0.02s 2.88r # -22%

3.52rから2.88rへの短縮は、実時間(real time)で約18%の高速化に相当します。コメントにある-22%-21%は、おそらく以前のベースラインからの相対的な改善率を示していると考えられます。これは、package bigのアセンブラ最適化が、pidigitsのような数値計算ベンチマークにおいて非常に効果的であったことを明確に示しています。

また、timing.shの修正は、pidigitsベンチマークの実行方法に関するものです。runonlyからrunへの変更は、特定の条件でのみ実行されていたベンチマークが、常に実行されるように変更されたことを意味します。これは、ベンチマークの網羅性を高め、性能変化を継続的に追跡できるようにするための修正です。

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

このコミットでは、以下の2つのファイルが変更されています。

  1. test/bench/shootout/timing.log
  2. test/bench/shootout/timing.sh

test/bench/shootout/timing.logの変更

--- a/test/bench/shootout/timing.log
+++ b/test/bench/shootout/timing.log
@@ -1063,3 +1063,9 @@ pidigits 10000
 	gc pidigits	3.51u 0.00s 3.52r # -6%
 	gc_B pidigits	3.51u 0.01s 3.52r # -6%
 
+# Aug 28, 2012
+# After some assembler work in package big.
+pidigits 10000
+	gc pidigits	2.85u 0.02s 2.88r # -22%
+	gc_B pidigits	2.88u 0.01s 2.90r # -21%
+

この変更は、pidigits 10000ベンチマークの新しい実行結果をtiming.logに追加しています。新しい結果は、gc pidigitsgc_B pidigitsの両方で、以前の結果よりも大幅に高速化されていることを示しています。特に、gc pidigitsの実時間(real time)が3.52rから2.88rに短縮され、コメントで-22%の改善が示されています。これは、package bigにおけるアセンブラ最適化の直接的な効果を反映したものです。

test/bench/shootout/timing.shの変更

--- a/test/bench/shootout/timing.sh
+++ b/test/bench/shootout/timing.sh
@@ -176,7 +176,7 @@ meteor() {\
 
 pidigits() {\
 	runonly echo 'pidigits 10000'
-	runonly 'gcc -O2 pidigits.c -lgmp' a.out 10000
+	run 'gcc -O2 pidigits.c -lgmp' a.out 10000
 	run 'gccgo -O2 pidigits.go' a.out -n 10000
 	run 'gc pidigits' $O.out -n 10000
 	run 'gc_B  pidigits' $O.out -n 10000

この変更は、pidigits関数内のgccでコンパイルされたC言語版のpidigitsベンチマークの実行コマンドを修正しています。具体的には、runonlyというプレフィックスがrunに変更されています。これにより、この特定のベンチマークが常に実行されるようになり、ベンチマークスイート全体の実行時にその性能が適切に測定されるようになります。

コアとなるコードの解説

このコミット自体は、Go言語のコアライブラリのコード変更(package bigのアセンブラコード)を直接含んでいません。代わりに、そのコアライブラリの変更によってもたらされた性能向上を記録し、ベンチマークスクリプトのバグを修正しています。

timing.logの変更は、単にベンチマーク結果の記録であり、コードの振る舞いを変更するものではありません。しかし、このログエントリは、package bigにおけるアセンブラ最適化が成功し、Go言語の数値計算性能が実際に向上したという重要な証拠となります。

timing.shの変更は、ベンチマークの実行ロジックを修正しています。runonlyからrunへの変更は、pidigitsベンチマークのC言語実装が、ベンチマークスイートの実行時に常に含まれるようにすることを意味します。これにより、Go言語の実装との比較がより正確かつ継続的に行えるようになります。この修正は、ベンチマークの信頼性と網羅性を向上させるためのものです。

このコミットの真の「コアとなるコードの変更」は、このコミットの前にpackage bigに対して行われたアセンブラレベルの最適化であり、このコミットはその最適化の効果を測定し、報告する役割を担っています。

関連リンク

参考にした情報源リンク

  • コミットメッセージと差分情報:
  • Go言語の公式ドキュメント(package big、アセンブリなど)
  • The Computer Language Benchmarks Gameのウェブサイト
  • 一般的なプログラミング言語のベンチマークと最適化に関する知識
  • 多倍長整数演算アルゴリズムに関する情報(例:Spigotアルゴリズム)
  • Go言語の内部実装に関するコミュニティの議論やブログ記事(具体的なURLは特定できないが、一般的な知識として参照)