33

古い PPC RISC システムや x86-64 の場合でも、この要件は理解できますが、実証済みの古い x86 の場合は? この場合、スタックは 4 バイト境界のみで整列する必要があります。はい、一部の MMX/SSE 命令では 16 バイトのアラインメントが必要ですが、それが呼び出し先の要件である場合は、アラインメントが正しいことを確認する必要があります。この追加の要件をすべての発信者に負担させるのはなぜですか? すべての呼び出しサイトがこの要件を管理する必要があるため、実際にはパフォーマンスが低下する可能性があります。何か不足していますか?

更新:これについてさらに調査し、社内の同僚と相談した結果、私はこれについていくつかの仮説を立てました。

  1. OS の PPC、x86、および x64 バージョン間の一貫性
  2. GCC codegen は、単純に「プッシュ」命令を実行するのではなく、sub esp,xxx を一貫して実行し、データをスタックに「移動」するようになりました。これは、一部のハードウェアでは実際に高速になる可能性があります。
  3. これは呼び出しサイトを少し複雑にしますが、呼び出し元がスタックをクリーンアップするデフォルトの "cdecl" 規則を使用する場合、余分なオーバーヘッドはほとんどありません。

最後の項目で私が抱えている問題は、呼び出し先がスタックをクリーニングすることに依存する呼び出し規則の場合、上記の要件がコード生成を実際に「醜く」することです。たとえば、一部のコンパイラが内部使用 (つまり、他の言語やソースからの呼び出しを意図していないコード) のために、より高速なレジスタ ベースの呼び出しスタイルを実装することを決定したものは何ですか? このスタックアライメントの問題は、いくつかのパラメーターをレジスターに渡すことによって達成されるパフォーマンスの向上の一部を無効にする可能性があります。

更新:これまでのところ、唯一の本当の答えは一貫性でしたが、私にはそれは少し簡単すぎる答えです。私は x86 アーキテクチャに関して 20 年以上の経験がありますが、パフォーマンスやその他の具体的なものではなく、一貫性が本当に理由である場合、開発者がそれを必要とするのは少しナイーブであることを丁重に提案します。彼らは、30 年近くにわたるツールとサポートを無視しています。特に、ツール ベンダーがツールを自社のプラットフォームにすばやく簡単に適応させることを期待している場合 (おそらくそうではないかもしれません... それApple です...)

このトピックは別の日かそこらにあげて、閉じます...

関連している

4

10 に答える 10

30

「Intel®64 and IA-32 Architectures Optimization Reference Manual」のセクション 4.4.2 から:

「最高のパフォーマンスを得るために、ストリーミング SIMD 拡張命令とストリーミング SIMD 拡張命令 2 では、メモリ オペランドを 16 バイト境界に整列する必要があります。整列されていないデータは、整列されたデータと比較して、パフォーマンスが大幅に低下する可能性があります。」

付録 D から:

「関数呼び出し全体でローカル __m128 データ、パラメーター、および XMM レジスタのスピル位置を整列させるために、スタック フレームが関数エントリ時に 16 バイト境界に整列されていることを確認することが重要です。」

http://www.intel.com/Assets/PDF/manual/248966.pdf

于 2009-05-22T16:28:30.630 に答える
6

直接の証拠がないのでわかりませんが、理由はSSEだと思います。バッファーが既に 16 バイト境界 (movps と movups) に配置されていて、x86 に mac os x 用の少なくとも sse2 がある場合、SSE ははるかに高速です。アプリケーションのユーザーが処理できますが、コストがかなりかかります。ABI で必須にするための全体的なコストがそれほど大きくない場合は、それだけの価値があるかもしれません。SSE は mac os X で非常に広く使用されています: フレームワークの加速など...

于 2009-05-07T02:26:29.883 に答える
5

x86-64 ABI とインラインに保つためだと思います。

于 2009-03-07T01:12:44.843 に答える
3

まず、16 バイト アラインメントは、Apple が System V IA-32 ABI に導入した例外であることに注意してください。

多くのシステム ライブラリは 16 バイトのアラインメントを必要とする SSE または Altivec 拡張機能を使用しているため、スタック アラインメントはシステム関数を呼び出す場合にのみ必要です。libgmalloc MAN pageで明示的な参照を見つけました。

スタック フレームは思い通りに完全に処理できますが、位置合わせされていないスタックでシステム関数を呼び出そうとすると、misaligned_stack_errorメッセージが表示されます。

編集:記録として、 mstack-realignオプション を使用して GCC でコンパイルするときのアライメントの問題を取り除くことができます。

于 2010-01-15T12:06:01.840 に答える
2

私の推測では、Apple は、誰もがスタックを調整する XCode (gcc) を使用しているだけだと考えています。したがって、スタックを整列させてカーネルを整列させる必要がないようにすることは、単なるマイクロ最適化です。

于 2010-01-25T07:06:37.993 に答える
2

これは効率の問題です。

新しい SSE 命令を使用するすべての関数でスタックが 16 バイトにアラインされていることを確認すると、これらの命令を使用するためのオーバーヘッドが大きくなり、パフォーマンスが実質的に低下します。

一方、スタックを常に 16 バイトに揃えておくと、パフォーマンスを犠牲にすることなく、SSE 命令を自由に使用できます。これにはコストはかかりません (少なくとも命令で測定されるコスト)。関数のプロローグで定数を変更するだけです。

スタック スペースを浪費するのは安く、おそらくキャッシュの最もホットな部分です。

于 2010-01-08T11:34:18.863 に答える
1

うーん、OS X ABI もレジスタで小さな構造体を渡すような面白い RISC を行いませんでしたか?

つまり、他のプラットフォームの理論との一貫性を示しています。

そういえば、FreeBSD の syscall api も 64 ビットの値を揃えています。(lseek や mmap など)

于 2009-05-22T16:12:05.293 に答える
1

WHY に関するご質問にはお答えできませんが、次のサイトのマニュアルが役立つ場合があります。

http://www.agner.org/optimize/

ABI に関しては、特に以下をご覧ください。

http://www.agner.org/optimize/calling_conventions.pdf

それが役に立つことを願っています。

于 2009-05-22T17:07:45.470 に答える
0

レガシーPowerPCベースのプラットフォームからの簡単な移植の可能性を誰も考えていない理由がわかりませんか?

これを読む:

http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/100-32-bit_PowerPC_Function_Calling_Conventions/32bitPowerPC.html#//apple_ref/doc/uid/TP40002438-SW20

そして、「32ビットPowerPC関数呼び出し規約」にズームインし、最後にこれを実行します。

「これらは、32ビットPowerPC環境で使用可能な埋め込みアライメントモードです。

電力調整モードは、AIXオペレーティング・システム用のIBMXLCコンパイラーによって使用される調整規則から派生します。これは、AIXおよびMac OS Xで使用されるPowerPCアーキテクチャーバージョンのGCCのデフォルトのアライメントモードです。このモードは、異なるベンダーのPowerPCアーキテクチャーコンパイラー間で互換性がある可能性が高いため、通常、間で共有されるデータ構造で使用されます。さまざまなプログラム。」

OSXのレガシーPowerPCベースのバックグラウンドを考慮すると、移植性は主要な考慮事項です。これは、AIXのXLCコンパイラーに至るまでの規則に従うことを指示します。すべてのツールとアプリケーションが最小限の手直しで連携することを確認する必要性について考えるとき、可能な限り同じレガシーABIに固執することが重要だと思います。

それは哲学を与えます、そしてさらに読むことは明示的に言及された規則です(「プロローグとエピローグ」):

呼び出された関数は、独自のスタックフレームを割り当て、スタック内で16バイトのアライメントを維持するようにします。この操作は、コンパイラーがサブルーチンの本体の前に配置するプロローグと呼ばれるコードのセクションによって実行されます。サブルーチンの本体の後に、コンパイラーはエピローグを配置して、プロセッサーをサブルーチン呼び出し前の状態に復元します。

于 2011-07-12T02:38:02.603 に答える