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

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

このコミットは、Go言語のランタイムにおける浮動小数点演算の精度に関するコメントの修正です。特に、x87 FPU(浮動小数点演算ユニット)のデフォルト精度設定が、Windows環境(MinGWを含む)でどのように扱われるかについての記述をより正確にするための変更です。

コミット

runtime: デフォルトの浮動小数点精度に関するコメントを修正

Win32におけるx87の期待される精度設定は53ビットですが、MinGWは浮動小数点ユニットを64ビットにリセットします。Win32オブジェクトコードは一般的に、値を倍精度(double)に丸めることを期待しており、拡張倍精度(double extended)ではありません。

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

https://github.com/golang/go/commit/019c8fc6255c21e4b7aa556269ae51d355728ef6

元コミット内容

commit 019c8fc6255c21e4b7aa556269ae51d355728ef6
Author: Carl Shapiro <cshapiro@google.com>
Date:   Tue Apr 2 13:45:56 2013 -0700

    runtime: fix a comment regarding default floating point precision
    
    The expected precision setting for the x87 on Win32 is 53-bit
    but MinGW resets the floating point unit to 64-bit.  Win32
    object code generally expects values to be rounded to double,
    not double extended, precision.
    
    R=golang-dev, khr
    CC=golang-dev
    https://golang.org/cl/8175044
---
 src/pkg/runtime/asm_386.s | 2 +-\
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
index 805405a737..57de87b8d4 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -108,7 +108,7 @@ TEXT runtime·breakpoint(SB),7,$0
 	RET
 
 TEXT runtime·asminit(SB),7,$0
-	// Linux, Windows start the FPU in extended double precision.
+	// Linux and MinGW start the FPU in extended double precision.
 	// Other operating systems use double precision.
 	// Change to double precision to match them,
 	// and to match other hardware that only has double.

変更の背景

このコミットの背景には、Go言語のランタイムがx87浮動小数点ユニット(FPU)のデフォルト精度設定をどのように扱うかに関する、特定の環境下での誤解または不正確な記述がありました。

x87 FPUは、Intel 80386以降のx86プロセッサに搭載されている浮動小数点演算コプロセッサ、またはその機能のエミュレーションです。このFPUは、単精度(32ビット)、倍精度(64ビット)、そして拡張倍精度(80ビット)の3つの異なる精度モードをサポートしています。

Goのランタイムは、異なるオペレーティングシステムやコンパイラ環境間で一貫した浮動小数点演算の振る舞いを保証しようとします。特に、浮動小数点演算の結果が、特定の精度で丸められることを期待する場合があります。

元のコメントでは、「Linux, WindowsはFPUを拡張倍精度で開始する」と記述されていました。しかし、実際にはWindows環境、特にMinGW(Minimalist GNU for Windows)のようなツールチェーンを使用した場合、FPUのデフォルト精度設定がGoランタイムが期待するものと異なる振る舞いをすることが判明しました。

具体的には、Win32アプリケーションは通常、浮動小数点演算の結果がIEEE 754倍精度(53ビットの仮数部を持つ64ビット形式)に丸められることを期待します。しかし、MinGWはFPUを64ビット(拡張倍精度)にリセットする傾向があり、これによりWin32の標準的な期待値と不一致が生じ、潜在的に数値計算の差異やバグを引き起こす可能性がありました。

このコミットは、この特定のMinGWの振る舞いをコメントに明示的に追加することで、GoランタイムのFPU初期化ロジックの背景にある理由をより正確に反映し、将来の開発者がこの挙動を理解しやすくすることを目的としています。これはコードの機能変更ではなく、ドキュメント(コメント)の正確性を高めるための変更です。

前提知識の解説

このコミットを理解するためには、以下の技術的な概念を把握しておく必要があります。

  1. 浮動小数点ユニット (FPU):

    • FPUは、コンピュータのCPUの一部、または独立したコプロセッサで、浮動小数点数(実数)の算術演算(加算、減算、乗算、除算、平方根など)を専門的に処理します。これにより、CPUが整数演算に集中でき、実数計算のパフォーマンスが向上します。
    • 歴史的に、FPUはCPUとは別のチップとして提供されていましたが、現代のCPUではFPU機能がCPUコアに統合されています。
  2. x87 FPU:

    • Intel 80386以降のx86アーキテクチャに搭載されているFPUの命令セットアーキテクチャです。
    • x87 FPUは、内部的に80ビットの拡張倍精度形式で計算を実行し、結果をメモリに格納する際に、単精度(32ビット)、倍精度(64ビット)、または拡張倍精度(80ビット)のいずれかに丸めることができます。
    • この丸め精度は、FPUの制御ワード(Control Word)によって設定されます。
  3. 浮動小数点精度:

    • 単精度 (Single Precision): IEEE 754標準で定義される32ビットの浮動小数点形式。仮数部は23ビット(実質24ビット)。
    • 倍精度 (Double Precision): IEEE 754標準で定義される64ビットの浮動小数点形式。仮数部は52ビット(実質53ビット)。多くのプログラミング言語でdouble型として使用されます。
    • 拡張倍精度 (Extended Double Precision): x87 FPUが内部的に使用する80ビットの形式。仮数部は64ビット(実質65ビット)。この精度は、中間計算の精度を向上させるために使用されますが、最終的な結果は通常、単精度または倍精度に丸められます。
  4. Win32:

    • Microsoft Windowsの32ビットAPIセットの総称。Windowsアプリケーションは、このAPIを通じてシステムリソースや機能を操作します。
    • Win32環境でコンパイルされたアプリケーションは、特定の浮動小数点演算の振る舞いを期待することが一般的です。特に、C/C++コンパイラは通常、double型がIEEE 754倍精度(53ビット仮数)に準拠することを前提としています。
  5. MinGW:

    • "Minimalist GNU for Windows"の略。Windows上でGNU開発ツール(GCCコンパイラなど)を使用できるようにするツールチェーンです。
    • MinGWでコンパイルされたプログラムは、WindowsのネイティブAPIを呼び出すことができますが、そのコンパイラやランタイムライブラリのデフォルト設定が、標準的なMicrosoft Visual C++コンパイラとは異なる振る舞いをすることがあります。このコミットの文脈では、MinGWがFPUの精度設定をデフォルトで64ビット(拡張倍精度)にリセットする傾向があることが問題となっています。
  6. Goランタイム (runtime):

    • Go言語のプログラムが実行される際に、メモリ管理(ガベージコレクション)、スケジューリング、システムコール、そして低レベルのハードウェアインタラクション(FPUの初期化など)を処理する部分です。
    • Goはクロスプラットフォーム言語であるため、異なるOSやアーキテクチャ間で一貫した動作を保証するために、ランタイムがハードウェアの特定の側面(この場合はFPUの精度)を初期化・設定することがあります。

これらの概念を理解することで、GoランタイムがなぜFPUの精度設定に注意を払い、特定の環境での振る舞いをコメントで明記する必要があるのかが明確になります。

技術的詳細

このコミットが修正しているのは、src/pkg/runtime/asm_386.sというファイル内のコメントです。このファイルは、Go言語のランタイムにおける386(x86 32ビット)アーキテクチャ向けのアセンブリコードを含んでいます。特に、runtime·asminitという関数に関連する部分です。

runtime·asminit関数は、Goプログラムの起動時に実行される初期化ルーチンの一部であり、その役割の一つにFPUの初期設定が含まれます。FPUの精度設定は、浮動小数点演算の結果の正確性や、異なるシステム間での数値の一貫性に影響を与えるため、非常に重要です。

元のコメントは以下の通りでした。 // Linux, Windows start the FPU in extended double precision. (Linux、WindowsはFPUを拡張倍精度で開始する。)

このコメントは、LinuxとWindowsの両方でFPUがデフォルトで拡張倍精度(80ビット)モードで起動すると示唆していました。しかし、コミットメッセージが説明するように、この記述はWindows環境、特にMinGWを使用した場合の挙動に関して不正確な点がありました。

コミットメッセージの核心は以下の点です。

  • Win32の期待: Win32オブジェクトコード(つまり、Windows上で動作する一般的なアプリケーション)は、x87 FPUが倍精度(53ビット仮数、64ビット形式)で丸めを行うことを期待しています。これは、C/C++のdouble型が通常この精度で扱われるためです。
  • MinGWの挙動: MinGWツールチェーンは、FPUをデフォルトで64ビット(これはx87の拡張倍精度モードを指している可能性が高い)にリセットする傾向があります。これにより、Win32が期待する53ビット精度との間に不一致が生じます。
  • 問題点: もしGoランタイムがFPUをWin32が期待する倍精度に設定しない場合、MinGWでコンパイルされたGoプログラムが、他のWin32アプリケーションやライブラリと浮動小数点演算の結果で不整合を起こす可能性があります。これは、数値の丸め誤差が異なることで、予期せぬバグや互換性の問題につながる可能性があります。

したがって、Goランタイムは、このような環境間の差異を吸収し、一貫した浮動小数点演算の振る舞いを保証するために、FPUの精度を明示的に倍精度に設定する必要があります。

このコミットは、コードの動作を変更するものではなく、このFPU初期化ロジックの背景にある理由をより正確に説明するために、コメントを修正しています。これにより、MinGWのような特定のツールチェーンがFPUのデフォルト設定に与える影響が明確になり、GoランタイムがなぜFPUを倍精度に「変更する」必要があるのかがより理解しやすくなります。

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

変更はsrc/pkg/runtime/asm_386.sファイル内の1行のコメント修正です。

--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -108,7 +108,7 @@ TEXT runtime·breakpoint(SB),7,$0
 	RET
 
 TEXT runtime·asminit(SB),7,$0
-	// Linux, Windows start the FPU in extended double precision.
+	// Linux and MinGW start the FPU in extended double precision.
 	// Other operating systems use double precision.
 	// Change to double precision to match them,
 	// and to match other hardware that only has double.

具体的には、以下の行が変更されました。

  • 変更前: // Linux, Windows start the FPU in extended double precision.
  • 変更後: // Linux and MinGW start the FPU in extended double precision.

コアとなるコードの解説

この変更は、runtime·asminitというGoランタイムの初期化関数内にあるコメントを修正しています。この関数は、Goプログラムが起動する際に、システムレベルの初期設定を行う役割を担っており、その中には浮動小数点ユニット(FPU)の初期化も含まれます。

元のコメントは、「LinuxとWindowsはFPUを拡張倍精度で開始する」と述べていました。これは、これらのOS環境のデフォルト設定が、Goランタイムが期待する倍精度(64ビット)とは異なる、より高い精度(80ビット)であることを示唆していました。そのため、Goランタイムは、その後の行で「それらに合わせて倍精度に変更する」と記述されており、これは異なる環境間での浮動小数点演算の一貫性を保つための重要なステップです。

しかし、このコミットの変更は、Windows環境におけるFPUのデフォルト精度に関する記述をより正確にしています。特に、MinGW(Minimalist GNU for Windows)というツールチェーンが、FPUを拡張倍精度で開始する傾向があることを明示的に追加しています。

変更後のコメント: // Linux and MinGW start the FPU in extended double precision. // Other operating systems use double precision. // Change to double precision to match them, // and to match other hardware that only has double.

この修正により、以下の点が明確になります。

  1. MinGWの特殊性: Windows環境全体が拡張倍精度でFPUを開始するわけではなく、MinGWのような特定のツールチェーンがそのように振る舞うことを強調しています。これは、MinGWがGCCベースであり、そのデフォルト設定がMicrosoft Visual C++とは異なる可能性があるためです。
  2. Win32の期待との整合性: コミットメッセージで述べられているように、Win32オブジェクトコードは通常、倍精度(53ビット仮数)での丸めを期待します。MinGWがFPUを64ビット(拡張倍精度)にリセットする場合、Goランタイムが明示的に倍精度に設定し直すことで、Win32の期待との不整合を防ぎ、数値計算の互換性を確保します。
  3. コメントの正確性向上: この変更は、コードの動作自体を変更するものではなく、その動作の背景にある理由と、Goランタイムが対処している特定の環境的要因(MinGWのFPU設定)をより正確に反映させるためのドキュメンテーションの改善です。これにより、将来このコードを読んだ開発者が、なぜFPUの精度が初期化時に変更されるのかをより深く理解できるようになります。

要するに、このコメント修正は、GoランタイムがFPUの精度を調整する理由を、より詳細かつ正確に説明するためのものであり、特にMinGW環境におけるFPUのデフォルト挙動の特殊性を強調しています。

関連リンク

参考にした情報源リンク