[インデックス 11073] ファイルの概要
コミット
このコミットは、Go言語のランタイムにNumCPU
関数を追加するものです。この関数は、ローカルマシン上のCPUコア数を返します。
- コミットハッシュ:
6dfdd4c1e34c753fb9c897eee355ee6ca3f007a8
- 作者: Russ Cox rsc@golang.org
- コミット日時: 2012年1月9日 月曜日 18:45:59 -0800
- 変更ファイル:
src/pkg/runtime/extern.go
src/pkg/runtime/runtime1.goc
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6dfdd4c1e34c753fb9c897eee355ee6ca3f007a8
元コミット内容
runtime: add NumCPU
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5528061
変更の背景
このコミットの背景には、Go言語の並行処理モデルと、それが利用可能なCPUリソースをどのように活用するかという設計思想があります。Go言語はゴルーチン(goroutine)と呼ばれる軽量なスレッドと、それらを効率的にCPUコアにマッピングするスケジューラを備えています。
初期のGoランタイムでは、GOMAXPROCS
という環境変数や関数を通じて、同時に実行可能なOSスレッドの最大数を制御していました。このGOMAXPROCS
のデフォルト値は、Go 1.5より前は1に設定されており、ユーザーが明示的に設定しない限り、Goプログラムは単一のCPUコアしか利用しませんでした。これは、Goプログラムがデフォルトで並行性を最大限に活用しないことを意味していました。
NumCPU
関数の追加は、プログラムが実行されているマシンの物理的または論理的なCPUコア数をプログラム的に取得できるようにすることを目的としています。これにより、開発者はGOMAXPROCS
の値を動的に設定する際に、システムのCPU数を考慮に入れることができるようになります。例えば、runtime.GOMAXPROCS(runtime.NumCPU())
とすることで、利用可能なすべてのCPUコアをGoスケジューラが利用するように設定することが可能になります。これは、Goプログラムがデフォルトでシステムの並行処理能力を最大限に引き出すための重要なステップでした。
前提知識の解説
Go言語のランタイム
Go言語のランタイムは、Goプログラムの実行を管理するシステムです。これには、ガベージコレクション、スケジューラ、メモリ管理、プリミティブな同期メカニズムなどが含まれます。Goのランタイムは、GoプログラムがOSとどのように相互作用するかを抽象化し、ゴルーチンのスケジューリングやメモリ割り当てといった低レベルのタスクを効率的に処理します。
ゴルーチン (Goroutine)
ゴルーチンはGo言語における並行処理の基本単位です。OSスレッドよりもはるかに軽量であり、数百万のゴルーチンを同時に実行することも可能です。ゴルーチンはGoランタイムによって管理され、複数のOSスレッド(M: Machine)に多重化されて実行されます。
GOMAXPROCS
GOMAXPROCS
は、Goランタイムが同時に実行できるOSスレッドの最大数を制御する環境変数、またはruntime
パッケージの関数です。この値は、Goスケジューラがゴルーチンをどの程度の並行度で実行するかを決定します。
GOMAXPROCS=1
の場合、Goプログラムは単一のOSスレッド上でゴルーチンを多重化して実行します。GOMAXPROCS > 1
の場合、Goプログラムは指定された数のOSスレッドを起動し、それらのスレッド間でゴルーチンを並行して実行します。
Go 1.5以降では、GOMAXPROCS
のデフォルト値は利用可能なCPUコア数に設定されるようになりました。しかし、このコミットが行われた2012年時点では、デフォルト値は1でした。
CPUコア数と並行処理
マルチコアプロセッサの普及により、ソフトウェアは複数のCPUコアを同時に利用することで、処理能力を向上させることができます。Go言語のような並行処理を重視する言語では、利用可能なCPUコア数を正確に把握し、それに応じてスケジューラを調整することが、プログラムのパフォーマンスを最大化するために重要です。NumCPU
関数は、この目的のためにシステムのCPUコア数を取得する手段を提供します。
技術的詳細
NumCPU
関数の実装は、Goランタイムの内部変数runtime·ncpu
の値を返すというシンプルなものです。このruntime·ncpu
は、ランタイムの初期化時にシステムから取得されたCPUコア数で設定されます。
コミットでは、以下の2つのファイルが変更されています。
-
src/pkg/runtime/extern.go
: このファイルは、Goランタイムの外部から呼び出される関数や、Goコードからランタイムの内部関数を呼び出すための宣言が含まれています。ここにNumCPU
関数の宣言が追加されました。// NumCPU returns the number of CPUs on the local machine. func NumCPU() int
この宣言は、
NumCPU
が引数を取らず、int
型の値を返すことを示しています。 -
src/pkg/runtime/runtime1.goc
: このファイルは、GoランタイムのC言語で書かれた部分(Go 1.x系ではC言語とGo言語のハイブリッドでランタイムが実装されていました)であり、extern.go
で宣言された関数の実際の定義が含まれています。ここにNumCPU
関数の実装が追加されました。func NumCPU() (ret int32) { ret = runtime·ncpu; }
ここで、
runtime·ncpu
というランタイム内部の変数の値がret
(戻り値)に代入されています。runtime·ncpu
は、ランタイムが起動する際にOSから取得したCPUコア数を保持しています。
この変更により、Goプログラムはruntime.NumCPU()
を呼び出すことで、実行環境のCPUコア数を簡単に取得できるようになりました。これは、GOMAXPROCS
の値を動的に設定する際の重要な情報源となります。
コアとなるコードの変更箇所
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index ea36355e66..e86da01732 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -107,6 +107,9 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
// mid returns the current os thread (m) id.
func mid() uint32
+// NumCPU returns the number of CPUs on the local machine.
+func NumCPU() int
+
// Semacquire waits until *s > 0 and then atomically decrements it.
// It is intended as a simple sleep primitive for use by the synchronization
// library and should not be used directly.
diff --git a/src/pkg/runtime/runtime1.goc b/src/pkg/runtime/runtime1.goc
index da2d0c5720..667131c1ee 100644
--- a/src/pkg/runtime/runtime1.goc
+++ b/src/pkg/runtime/runtime1.goc
@@ -8,3 +8,7 @@ package runtime
func GOMAXPROCS(n int32) (ret int32) {
ret = runtime·gomaxprocsfunc(n);
}
+
+func NumCPU() (ret int32) {
+ ret = runtime·ncpu;
+}
コアとなるコードの解説
src/pkg/runtime/extern.go
の変更
// NumCPU returns the number of CPUs on the local machine.
NumCPU
関数の目的を説明するコメントが追加されています。
func NumCPU() int
runtime
パッケージにNumCPU
という新しい関数が宣言されています。この宣言は、Go言語のコードからこの関数を呼び出すためのインターフェースを提供します。戻り値の型はint
です。
src/pkg/runtime/runtime1.goc
の変更
func NumCPU() (ret int32) {
NumCPU
関数の実際の定義が追加されています。この関数はint32
型の戻り値ret
を持ちます。
ret = runtime·ncpu;
- Goランタイムの内部変数である
runtime·ncpu
の値がret
に代入されます。runtime·ncpu
は、ランタイムが初期化される際にオペレーティングシステムから取得される、システムのCPUコア数を格納しています。
- Goランタイムの内部変数である
}
- 関数の定義の終わり。
この2つの変更により、Goプログラムはruntime.NumCPU()
を呼び出すことで、実行環境のCPUコア数を取得できるようになりました。これは、Goの並行処理をシステムのハードウェアリソースに合わせて最適化するための重要な機能です。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/
- Go 1.5
GOMAXPROCS
の変更に関するブログ記事 (このコミットより後の変更ですが、関連性が高いです): https://go.dev/blog/go15gc
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Go言語のランタイムに関する一般的な情報 (Goのドキュメントやブログ記事)
- Go言語の
GOMAXPROCS
に関する情報 (Goのドキュメントやブログ記事) - Go言語のコミット履歴 (GitHub)
- Go言語のコードレビューシステム (Gerrit): https://golang.org/cl/5528061 (元コミット内容に記載されているリンク)