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

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

このコミットは、Go言語のランタイムにおけるappendCrossover定数の値をARMアーキテクチャ向けに調整するものです。具体的には、src/pkg/runtime/arch_arm.hファイル内のappendCrossoverの値を16から8に変更しています。この変更は、特にCortex-A9システム(Pandaboardなど)でのappend操作のパフォーマンスを最適化することを目的としています。

コミット

commit d09f34cc555e60dbd57ab7c9f268daf895922225
Author: Dave Cheney <dave@cheney.net>
Date:   Sun Apr 28 00:18:11 2013 +1000

    runtime: tune appendCrossover for arm
    
    Turns out the optimal value is 8 on cortex-A9 systems (pandaboard)
    
    benchmark                     old ns/op    new ns/op    delta
    BenchmarkAppend                     907          908   +0.11%
    BenchmarkAppend1Byte                101          101   +0.00%
    BenchmarkAppend4Bytes               116          116   +0.00%
    BenchmarkAppend8Bytes               139          138   -0.72%
    BenchmarkAppend16Bytes              185          158  -14.59%
    BenchmarkAppend32Bytes              131          131   +0.00%
    BenchmarkAppendStr1Byte              72           72   +0.00%
    BenchmarkAppendStr4Bytes             93           93   -0.21%
    BenchmarkAppendStr8Bytes            116          116   +0.00%
    BenchmarkAppendStr16Bytes           161          125  -22.36%
    BenchmarkAppendStr32Bytes           102          102   +0.00%
    BenchmarkAppendSpecialCase          613          613   +0.00%
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/8863045

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

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

元コミット内容

このコミットは、GoランタイムのappendCrossover定数をARMアーキテクチャ向けに調整するものです。Cortex-A9システム(Pandaboard)において、最適な値が8であることが判明したため、この変更が行われました。

コミットメッセージには、変更前後のベンチマーク結果が示されており、特にBenchmarkAppend16BytesBenchmarkAppendStr16Bytesで顕著なパフォーマンス改善(それぞれ-14.59%と-22.36%)が見られます。

変更の背景

Go言語の組み込み関数であるappendは、スライスに要素を追加する際に使用されます。この操作は、内部的にメモリの再割り当てやコピーを伴うことがあり、その効率は基盤となるアーキテクチャに大きく依存します。

appendCrossoverは、append操作の内部実装において、特定のサイズを超えるデータが追加される場合に、より効率的な(しかしオーバーヘッドが大きい可能性のある)コピーメカニズムに切り替えるための閾値を定義していると考えられます。この閾値は、異なるCPUアーキテクチャやキャッシュラインサイズ、メモリレイアウトの特性に合わせて調整されることで、パフォーマンスを最大化できます。

このコミットの背景には、ARM Cortex-A9プロセッサを搭載したPandaboardのような組み込みシステム上でGoアプリケーションを実行する際のパフォーマンス最適化の必要性がありました。開発者は、特定のハードウェア環境でappend操作のベンチマークを実行し、appendCrossoverの既存の値(16)が最適ではないことを発見しました。より小さな値(8)に調整することで、特に16バイト程度のデータ追加において、より効率的なコードパスが選択されるようになり、パフォーマンスが向上したと考えられます。

前提知識の解説

Go言語のスライスとappend関数

Go言語のスライスは、可変長シーケンスを表現するための強力なデータ構造です。スライスは、内部的に配列へのポインタ、長さ(len)、容量(cap)の3つの要素で構成されます。

append関数は、スライスに新しい要素を追加するために使用されます。appendの動作は以下のようになります。

  1. 容量の確認: スライスの現在の容量に新しい要素を追加するのに十分なスペースがあるかを確認します。
  2. 再割り当て: スペースが不足している場合、Goランタイムはより大きな新しい基盤配列を割り当て、既存の要素を新しい配列にコピーし、新しい要素を追加します。この再割り当ての際に、将来の追加に備えて、必要量よりも多くの容量を確保することが一般的です(容量の倍増など)。
  3. 要素の追加: 新しい要素をスライスの末尾に追加します。

この再割り当てとコピーのプロセスは、特に頻繁に発生する場合や、大量のデータがコピーされる場合に、パフォーマンスのボトルネックとなる可能性があります。

ARMアーキテクチャとCortex-A9

ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。RISC(Reduced Instruction Set Computer)の原則に基づいて設計されており、電力効率と性能のバランスが優れています。

Cortex-A9は、ARMv7-Aアーキテクチャに基づくARMプロセッサコアの一つです。スマートフォン、タブレット、セットトップボックス、組み込みシステムなど、幅広いデバイスに採用されました。Cortex-A9は、アウトオブオーダー実行、投機的実行、マルチコア構成(最大4コア)をサポートし、当時の高性能ARMプロセッサとして位置づけられていました。

プロセッサのキャッシュラインサイズやメモリ階層の特性は、データコピー操作の効率に大きな影響を与えます。appendのような操作では、データがキャッシュラインにどのようにフィットするか、そしてメモリからキャッシュへの転送がどれだけ効率的に行われるかが、全体のパフォーマンスを左右します。

appendCrossoverの概念

Goランタイムの内部では、append操作の最適化のために、いくつかのヒューリスティックが用いられています。appendCrossoverは、追加されるデータのサイズがこの閾値を超える場合に、異なる(おそらくより複雑で、しかし大規模なコピーには適した)コピーアルゴリズムや最適化されたアセンブリルーチンに切り替えるための「クロスオーバー」ポイントとして機能します。

例えば、非常に小さなデータ(数バイト)の追加であれば、シンプルなバイト単位のコピーが最も効率的かもしれません。しかし、ある程度の大きさ(例えばキャッシュラインサイズを超えるような)のデータを追加する場合、より高度なメモリ操作(例えば、一度に複数のワードをコピーする、SIMD命令を利用するなど)が有効になることがあります。appendCrossoverは、この切り替えの判断基準となる値です。

この値が適切でない場合、例えば、小さなデータ追加に対して過度に複雑なルーチンが使われたり、大きなデータ追加に対して非効率なルーチンが使われたりして、パフォーマンスが低下する可能性があります。

技術的詳細

このコミットは、GoランタイムのARMアーキテクチャ固有のヘッダーファイルであるsrc/pkg/runtime/arch_arm.h内のappendCrossover定数を変更しています。

変更前:

enum {
	thechar = '5',
	BigEndian = 0,
	CacheLineSize = 32,
	appendCrossover = 16
};

変更後:

enum {
	thechar = '5',
	BigEndian = 0,
	CacheLineSize = 32,
	appendCrossover = 8
};

この変更により、append操作において、追加されるデータのサイズが8バイトを超える場合に、Goランタイムが異なる(より最適化された)コピー戦略を採用するようになります。以前は16バイトが閾値でした。

ベンチマーク結果は、この変更が特に16バイトのデータ追加(BenchmarkAppend16BytesBenchmarkAppendStr16Bytes)に対して大きな効果をもたらしたことを示しています。

  • BenchmarkAppend16Bytes: 185 ns/op -> 158 ns/op (-14.59%)
  • BenchmarkAppendStr16Bytes: 161 ns/op -> 125 ns/op (-22.36%)

これは、16バイトのデータ追加が、新しいappendCrossover = 8の閾値によって、より効率的なコードパス(例えば、8バイト単位のコピーを2回行う、あるいは特定の最適化されたルーチン)を利用できるようになったことを示唆しています。以前のappendCrossover = 16では、16バイトの追加は「クロスオーバー」の対象外であったか、あるいは対象であっても現在の最適化が適用されていなかった可能性があります。

Cortex-A9のような特定のARMプロセッサでは、8バイト(64ビット)のアラインメントやレジスタ幅が効率的なデータ操作の鍵となることがあります。この調整は、Cortex-A9のメモリサブシステムやキャッシュの特性に合わせたチューニングの結果と考えられます。

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

変更は、src/pkg/runtime/arch_arm.hファイルの一箇所のみです。

--- a/src/pkg/runtime/arch_arm.h
+++ b/src/pkg/runtime/arch_arm.h
@@ -6,5 +6,5 @@ enum {
 	thechar = '5',
 	BigEndian = 0,
 	CacheLineSize = 32,
-	appendCrossover = 16
+	appendCrossover = 8
 };

コアとなるコードの解説

src/pkg/runtime/arch_arm.hは、GoランタイムがARMアーキテクチャ向けにコンパイルされる際に使用されるヘッダーファイルです。このファイルには、アーキテクチャ固有の定数や設定が定義されています。

  • thechar = '5': これはGoの内部的なアーキテクチャ識別子の一部で、ARMv5またはARMv7(Goの初期のARMサポートはv5/v7が混在していた)を示唆している可能性があります。
  • BigEndian = 0: ARMは通常リトルエンディアンで動作するため、これはリトルエンディアンであることを示します。
  • CacheLineSize = 32: ARM Cortex-A9プロセッサのデータキャッシュラインサイズが32バイトであることを示しています。これは、メモリ操作の最適化において非常に重要な情報です。データがキャッシュラインにアラインされているか、あるいはキャッシュラインの倍数であるかによって、メモリ転送の効率が大きく変わるためです。
  • appendCrossover = 8: このコミットで変更された値です。前述の通り、append操作における内部的なコピー戦略の切り替え閾値を定義します。この値を32バイトのキャッシュラインサイズの半分である8バイトに設定することで、16バイトのデータ追加が、より効率的な8バイト単位の操作の組み合わせで処理されるようになったと考えられます。

この変更は、Goランタイムが特定のハードウェア特性(この場合はARM Cortex-A9のキャッシュとメモリ操作の効率)を考慮して、appendのような基本的な操作のパフォーマンスをきめ細かくチューニングしていることを示しています。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴と関連するコードレビュー: https://golang.org/cl/8863045 (コミットメッセージに記載されているChangeListへのリンク)
  • Go言語のappend実装に関する議論や最適化に関する記事(一般的な情報源)
  • ARMアーキテクチャのメモリモデルとキャッシュに関する技術文書(一般的な情報源)
  • Pandaboardに関する情報(一般的な情報源)