この配列アクセス マイクロベンチマーク (GCC と比較) では、Go は 4 倍のパフォーマンス低下を被っています。これは何が原因でしょうか?この問題には、Go 言語のランタイム メカニズムやコンパイラの最適化など、多くの側面が関係します。まず、Go 言語は配列にアクセスするときに境界チェック メカニズムを使用します。つまり、配列要素にアクセスするたびに境界チェックが実行されるため、パフォーマンスがある程度低下します。次に、Go 言語コンパイラは最適化が比較的弱く、配列アクセスをうまく最適化できません。さらに、Go 言語のガベージ コレクション メカニズムもパフォーマンスに一定の影響を与えます。これらの要因が組み合わさって、Go はアレイ アクセス マイクロベンチマークで 4 倍のパフォーマンス低下を被ることになりました。
このマイクロベンチマークは、go のパフォーマンス特性をよりよく理解し、いつ使用するかについて十分な情報に基づいた選択ができるようにするために作成しました。
パフォーマンスのオーバーヘッドの観点から、これが Go にとって理想的なシナリオだと思います:
それにもかかわらず、amd64 の gcc -o3
と比較して 4 倍の速度差が見られました。何故ですか?
(シェルタイミングを使用します。毎回数秒かかるため、起動は無視できます)
リーリーc バージョン:
リーリー更新:
range
を使用すると、移動速度が 2 倍になります。 -march=native
を使用すると、私のテストでは c が 2 倍高速になりました。 (そして -mno-sse
はコンパイル エラーを引き起こします。どうやら -o3
と互換性がありません) range
は必要ありません) 少なくとも私が使用している Go および GCC のバージョン (1.19.6 および 12.2.0) で、C プログラムと Go プログラムのアセンブラー出力を確認してください。それぞれ)、最も直接的で明白な違いは、GCC は C プログラムを自動的にベクトル化するのに対し、Go コンパイラーはこれを行うことができないようです。
これは、特定のアーキテクチャをターゲットにしていない場合、GCC は AVX ではなく SSE を使用するため、パフォーマンスが 4 倍向上する理由もよく説明しています。これは、32 ビット スカラー命令幅が動作幅の 4 倍であることを意味します。実際、-march=native
を追加すると、GCC が CPU 上で AVX コードを出力するようになるため、パフォーマンスが 2 倍向上しました。
私は Go コンパイラーが本質的に自動ベクトル化を実行できないのか、それともこの特定のプログラムだけが何らかの理由でエラーを引き起こしているのかを説明できるほど Go に詳しくありませんが、それが根本的な原因のようです。
以上がこの配列アクセス マイクロベンチマークで (GCC と比較して) Go の 4 倍のパフォーマンス低下の原因は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。