[インデックス 13212] ファイルの概要
このコミットは、Go言語のベンチマークスイートに、浮動小数点演算の性能を測定するための新しいベンチマークとしてマンデルブロ集合の計算を追加するものです。具体的には、test/bench/go1/mandel_test.go
という新しいファイルが追加され、マンデルブロ集合を計算するmandelbrot
関数と、その性能を測定するためのベンチマーク関数BenchmarkMandelbrot200
が実装されています。
コミット
commit cb9759d067289fef850251c9425b56446086e24c
Author: Russ Cox <rsc@golang.org>
Date: Wed May 30 10:26:59 2012 -0400
test/bench/go1: add mandelbrot for floating point
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6244063
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/cb9759d067289fef850251c9425b56446086e24c
元コミット内容
test/bench/go1: add mandelbrot for floating point
このコミットは、Go言語のベンチマークスイートに、浮動小数点演算の性能を評価するためのマンデルブロ集合計算ベンチマークを追加します。
変更の背景
Go言語の進化において、様々な側面での性能最適化は継続的な課題です。特に浮動小数点演算は、科学技術計算、グラフィックス、機械学習など、多くの分野で重要な役割を果たします。Goのランタイムやコンパイラが浮動小数点演算をどれだけ効率的に処理できるかを正確に測定するためには、代表的なワークロードを用いたベンチマークが必要です。
マンデルブロ集合の計算は、その性質上、大量の浮動小数点演算(加算、乗算、比較など)を必要とします。そのため、CPUの浮動小数点演算ユニット(FPU)の性能や、コンパイラによる浮動小数点演算の最適化能力を評価するのに適したベンチマークとして広く利用されています。このベンチマークの追加は、Go言語が浮動小数点演算を伴うアプリケーションにおいて、競合他言語と比較してどの程度の性能を発揮できるかを把握し、将来的な最適化の方向性を定めるための重要な一歩となります。
前提知識の解説
ベンチマーク (Benchmark)
ベンチマークとは、ソフトウェアやハードウェアの性能を測定し、評価するためのテストのことです。特定のタスクを実行するのにかかる時間やリソース消費量を測定し、異なるシステムや設定間での比較を可能にします。Go言語では、標準のtesting
パッケージにベンチマーク機能が組み込まれており、BenchmarkXxx
という命名規則に従う関数を記述することで、簡単に性能測定を行うことができます。
浮動小数点演算 (Floating Point Arithmetic)
浮動小数点演算は、非常に大きい数や小さい数を近似的に表現し、計算するための方法です。コンピュータでは、IEEE 754などの標準に基づいて実装されており、科学技術計算やグラフィックス処理など、実数を扱う多くのアプリケーションで不可欠です。浮動小数点演算の性能は、CPUのFPUの設計、コンパイラの最適化、メモリのアクセスパターンなど、様々な要因に影響されます。
マンデルブロ集合 (Mandelbrot Set)
マンデルブロ集合は、複素平面上の点c
のうち、漸化式 z_{n+1} = z_n^2 + c
(ただし z_0 = 0
)で定義される数列 z_n
が無限大に発散しないような点の集合です。この集合はフラクタル図形の一種であり、その境界は非常に複雑で美しいパターンを示します。
マンデルブロ集合の計算は、各点c
に対して、数列z_n
が発散するかどうかを判定するために、一定の繰り返し回数(イテレーション)内で|z_n|
が特定の閾値(通常は2.0)を超えるかどうかをチェックします。このプロセスは、複素数の乗算と加算を繰り返し行うため、大量の浮動小数点演算を伴います。
具体的には、複素数 z = Zr + Zi*i
と c = Cr + Ci*i
に対して、z^2
は (Zr + Zi*i)^2 = Zr^2 - Zi^2 + 2*Zr*Zi*i
となります。したがって、漸化式は実部と虚部に分解すると以下のようになります。
Zr_{n+1} = Zr_n^2 - Zi_n^2 + Cr
Zi_{n+1} = 2*Zr_n*Zi_n + Ci
そして、|z_n|^2 = Zr_n^2 + Zi_n^2
が閾値の二乗(Limit*Limit
)を超えるかどうかを判定します。
Go言語のtesting
パッケージとベンチマーク
Go言語のtesting
パッケージは、ユニットテストだけでなく、ベンチマークテストもサポートしています。ベンチマーク関数はfunc BenchmarkXxx(b *testing.B)
というシグネチャを持ち、b.N
回ループを実行することで、テスト対象のコードの平均実行時間を測定します。b.N
の値は、ベンチマーク実行時にgo test
コマンドによって自動的に調整され、統計的に有意な結果が得られるようにします。
技術的詳細
このコミットで追加されたmandel_test.go
ファイルは、Go言語のベンチマークフレームワークを利用して、マンデルブロ集合の計算性能を測定します。
mandelbrot
関数
mandelbrot(n int) int
関数は、n x n
のグリッド上でマンデルブロ集合の計算を行います。
Iter
定数(50)は、各点におけるイテレーションの最大回数を定義します。この回数を超えても発散しない場合は、集合に属するとみなされます。Limit
定数(2.0)は、発散を判定するための閾値です。|z_n|
がこの値を超えると発散とみなされます。- 二重ループで
n x n
のグリッド上の各点(x, y)
を走査します。 - 各点
(x, y)
は、複素平面上の点Cr
とCi
にマッピングされます。Cr = (2*float64(x)/float64(n) - 1.5)
Ci = (2*float64(y)/float64(n) - 1.0)
このマッピングにより、マンデルブロ集合の典型的な表示範囲(実部が-2.0から1.0、虚部が-1.5から1.5程度)がカバーされます。
- 内部ループでは、マンデルブロ集合の漸化式
z_{n+1} = z_n^2 + c
をIter
回まで繰り返します。Zr
,Zi
は現在のz
の実部と虚部。Tr
,Ti
はそれぞれZr*Zr
とZi*Zi
を保持し、Zr^2 - Zi^2
やZr^2 + Zi^2
の計算を効率化します。Zi = 2*Zr*Zi + Ci
Zr = Tr - Ti + Cr
Tr = Zr * Zr
Ti = Zi * Zi
これらの計算はすべてfloat64
型で行われ、大量の浮動小数点演算を発生させます。
Tr+Ti <= Limit*Limit
という条件は、|z_n|^2 <= Limit^2
と同等であり、z_n
が発散していないかをチェックします。- イテレーションが終了した後、
Tr+Ti <= Limit*Limit
であれば、その点はマンデルブロ集合に属するとみなし、ok
カウンターをインクリメントします。 - 最終的に、集合に属すると判定された点の総数
ok
を返します。
BenchmarkMandelbrot200
関数
BenchmarkMandelbrot200(b *testing.B)
関数は、mandelbrot
関数をベンチマークするためのGoの標準ベンチマーク関数です。
for i := 0; i < b.N; i++
ループ内でmandelbrot(200)
を呼び出します。b.N
はtesting
パッケージによって動的に決定され、mandelbrot(200)
の実行時間を統計的に有意な精度で測定するために必要な回数だけ関数が実行されます。mandelbrot(200)
は、200x200のグリッドでマンデルブロ集合を計算することを意味し、これにより十分な量の浮動小数点演算が実行され、ベンチマークとして機能します。
このベンチマークは、Go言語の浮動小数点演算の性能、特にfloat64
型の計算効率、コンパイラによる最適化、そしてCPUのFPUの利用効率を評価するのに役立ちます。
コアとなるコードの変更箇所
このコミットでは、test/bench/go1/mandel_test.go
という新しいファイルが追加されています。
--- /dev/null
+++ b/test/bench/go1/mandel_test.go
@@ -0,0 +1,41 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This benchmark, taken from the shootuot, tests floating point performance.
+
+package go1
+
+import "testing"
+
+func mandelbrot(n int) int {
+ const Iter = 50
+ const Zero float64 = 0
+ const Limit = 2.0
+ ok := 0
+ for y := 0; y < n; y++ {
+ for x := 0; x < n; x++ {
+ Zr, Zi, Tr, Ti := Zero, Zero, Zero, Zero
+ Cr := (2*float64(x)/float64(n) - 1.5)
+ Ci := (2*float64(y)/float64(n) - 1.0)
+
+ for i := 0; i < Iter && (Tr+Ti <= Limit*Limit); i++ {
+ Zi = 2*Zr*Zi + Ci
+ Zr = Tr - Ti + Cr
+ Tr = Zr * Zr
+ Ti = Zi * Zi
+ }
+
+ if Tr+Ti <= Limit*Limit {
+ ok++
+ }
+ }
+ }
+ return ok
+}
+
+func BenchmarkMandelbrot200(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ mandelbrot(200)
+ }
+}
コアとなるコードの解説
追加されたmandel_test.go
ファイルは、Goのベンチマークテストの慣例に従ってgo1
パッケージ内に配置されています。
-
パッケージ宣言とインポート:
package go1
: このファイルがgo1
パッケージの一部であることを示します。Goのベンチマークは通常、テスト対象のパッケージと同じか、専用のベンチマークパッケージに配置されます。import "testing"
: Goの標準テストおよびベンチマークフレームワークであるtesting
パッケージをインポートします。
-
mandelbrot
関数:- この関数は、マンデルブロ集合の計算ロジックをカプセル化しています。
n
はグリッドのサイズ(n x n
)を決定します。Iter
は各点の計算における最大イテレーション回数です。Limit
は発散判定の閾値です。Zr
,Zi
は複素数z
の実部と虚部を表します。Tr
,Ti
はZr*Zr
とZi*Zi
を保持し、計算を最適化します。Cr
,Ci
は複素数c
の実部と虚部を表し、グリッド上の点から導出されます。- 内側のループは、マンデルブロ集合の漸化式を繰り返し適用し、
z
が発散するかどうかをチェックします。 Tr+Ti <= Limit*Limit
は、|z|^2 <= Limit^2
、つまりz
がまだ発散していないことを意味します。ok
変数は、マンデルブロ集合に属すると判定された点の数をカウントします。
-
BenchmarkMandelbrot200
関数:func BenchmarkMandelbrot200(b *testing.B)
というシグネチャは、Goのベンチマーク関数であることを示します。b *testing.B
はベンチマークコンテキストを提供します。for i := 0; i < b.N; i++
ループは、ベンチマークの核となる部分です。b.N
はgo test
コマンドによって自動的に調整され、mandelbrot(200)
関数が統計的に有意な回数だけ実行されるようにします。mandelbrot(200)
は、200x200のグリッドでマンデルブロ集合を計算し、浮動小数点演算の負荷をかけます。
このコードは、Goのベンチマークのベストプラクティスに従っており、浮動小数点演算の性能を効率的かつ正確に測定するための堅牢な基盤を提供します。
関連リンク
- Go言語の
testing
パッケージドキュメント: https://pkg.go.dev/testing - Go言語のベンチマークに関する公式ブログ記事 (例: "Go's work-stealing scheduler"): https://go.dev/blog/go1.1bench (これは一般的なベンチマークに関する記事の例であり、このコミットに直接関連するものではありませんが、Goのベンチマークの文脈を理解するのに役立ちます。)
- マンデルブロ集合 - Wikipedia: https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%B3%E3%83%87%E3%83%AB%E3%83%96%E3%83%AD%E9%9B%86%E5%90%88
参考にした情報源リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/6244063 (コミットメッセージに記載されているChange-IDのリンク)
- The Computer Language Benchmarks Game (Shootout): マンデルブロ集合のベンチマークは、しばしばこのサイトのような言語間の性能比較ベンチマークスイートから採用されます。
- https://benchmarksgame-team.pages.debian.net/benchmarksgame/ (一般的な情報源であり、このコミットが直接ここから取られたことを示すものではありませんが、文脈を理解するのに役立ちます。)
- IEEE 754 (浮動小数点数): https://ja.wikipedia.org/wiki/IEEE_754