ほとんどのC/C++コンパイラには、コンパイラに渡すことができるフラグ-march=native
があります。これは、ホストCPUのマイクロアーキテクチャおよびISA拡張用に生成されたコードを調整するようコンパイラに指示します。同じ名前でなくても、通常rustc
やswiftc
のようなLLVMベースのコンパイラーには同等のオプションがあります。
私自身の経験では、このフラグは数値集中型コードの大幅な高速化を実現し、sounds自分のマシン用にコンパイルしているコードの妥協がないようになります。そうは言っても、デフォルトで有効にするビルドシステムや静的コンパイラを見たことはないと思います。
明らかに、コマンドラインコンパイラの実行可能ファイルでは、渡す必要があるため、デフォルトでは使用されません。
デフォルトでこれを有効にするIDEは考えられません。
使用した一般的なビルドシステム(cmake
、automake
、cargo
、spm
など)を有効にすることは考えられません。デフォルトでは、最適化されたビルドでも。
これにはいくつかの理由が考えられますが、実際に満足できるものはありません。
-march=native
の使用は、他のマシンに配布されるバイナリには不適切です。とは言うものの、私は自分自身のソースを他のマシンよりも頻繁にコンパイルしていることに気付きます。これは、配布の意図がないデバッグビルドでの使用の欠如を説明しません。
少なくともIntel x86 CPUでは、AVXユニットが使用されていないときは電源がオフになり、使用するには電源を入れる必要があるため、AVX命令を頻繁に使用するとパフォーマンスや電力効率が低下することがあると理解していますダウンクロックしてAVX命令を実行します。それでも、AVXが有効にならない理由を説明するだけであり、特定のマイクロアーキテクチャの通常の命令の処理に合わせてコードが調整されない理由は説明しません。
ほとんどのx86 CPUは、レジスタの名前を変更した派手なアウトオブオーダースーパースカラーパイプラインを使用するため、特定のマイクロアーキテクチャ用のコードのチューニングは、おそらく特に重要ではありません。それでも、それがcouldヘルプなら、なぜそれを使用しないのですか?
リストの中で最も古いgccのデフォルトを詳しく見ると、非常に保守的であることがわかります。
-Wall
および-Wextra
のフラグのセットは何年も変わっていません。新しい便利な警告がありますが、-Wall
や-Wextra
には追加されません。どうして?壊れるからです!
これらの便利なデフォルトに依存する開発チェーン全体が存在し、変更すると、それらを壊したり、ターゲットで実行されないバイナリを生成したりするリスクが生じます。
ユーザーが多いほど脅威は大きくなるため、gccの開発者は世界規模の破損を避けるために非常に保守的です。そして、コンパイラの次のバッチの開発者は、長老たちの足跡をたどります。それが機能することが証明されています。
注:rustc
はデフォルトで静的リンクになり、バイナリをコピーして別のマシンにドロップできることを誇っています。明らかに-march=native
が障害になります。
そして実際には、おそらくそれは問題ではありません。実際に自分で認識しました:
私自身の経験では、このフラグは数値集中型コードの大幅な高速化を実現できます
ほとんどのコードは仮想コールとブランチでいっぱいであり(通常OOコード)、数値集約型ではありません。したがって、コードの大部分では、SSE多くの場合、2で十分です。
パフォーマンスが本当に重要な少数のコードベースでは、コードレベルとコンパイラレベルの両方で、パフォーマンスチューニングにかなりの時間を費やす必要があります。また、ベクトル化が重要な場合、コンパイラの気まぐれに任せることはありません。開発者は組み込みの組み込み関数を使用し、ベクトル化されたコードを自分で記述します。 。
また、数値が集中するコードであっても、ホストマシンとターゲットマシンはわずかに異なる場合があります。コンパイルは、より低い周波数でも多くのコアから恩恵を受けますが、実行が容易に並列化できない限り、実行は高周波数から、場合によってはより少ないコアから恩恵を受けます。
デフォルトで-march=native
をアクティブにしないと、ユーザーが簡単に開始できます。パフォーマンスを求める人でさえあまり気にかけないかもしれないので、これは利益よりも失うものの方が多いことを意味します。
デフォルトが最初から-march=native
であった代替履歴では、ユーザーはターゲットアーキテクチャを指定するために使用され、この議論は行いません。
-march=native
は破壊的なフラグです。これにより、バイナリは多くのハードウェア(基本的にはコンパイルに使用されるCPUの直接の子孫ではないすべてのCPU)で互換性がなくなります。デフォルトでこれを有効にするには、単に危険すぎます。
考慮すべきもう1つの重要なことは、-march=native
の主な用途は最適化です。デフォルトの最適化フラグは-O0
(最適化なし)。この観点からも、デフォルトで有効にすることは意味がありません。
パワーユーザーの観点から考えていますが、コンパイラツールチェーンの主な対象者はパワーユーザーではなく、開発者です。
ほとんどの開発者は、個別の開発マシンとターゲットの本番システムを持っています。消費者向けアプリケーションの場合、このターゲットシステムは他の人のマシンであり、すべての違いがあります。最も一般的な分母のためのビルドは、開発者自身のマシンの外部でのみ発生するバグの可能性を減らすため、安全なデフォルトです。
もちろん、既知のアーキテクチャを持つ単一のターゲットマシン用のアプリケーションを開発することを開発者が知っている場合があります。ただし、この場合でも、ほとんどのアプリケーションはパフォーマンスに敏感ではないため、デフォルトとして安全なオプションで十分に機能しますが、パフォーマンスに敏感なアプリケーションを使用している開発者は、通常、ビルド構成の調整に時間を費やします。