6

できるだけ高速にする必要がある関数があり、整数演算のみを使用しています。これは AMD64 アーキテクチャで動作し、十分な数のレジスタを操作するには、いくつかのプッシュ/ポップを実行する必要があります。x64 ABI では、最初の 4 つの浮動小数点レジスタ (XMM0、XMM1、XMM2、および XMM3) は揮発性であり、関数呼び出し間で保持する必要はないと述べています。

そこで、スタックを使用する代わりに、movq (MMX または SSE 命令セット) を介してこれらのレジスタ (つまり、MM0、MM1、...) の下位 64 ビットに保存する必要がある 64 ビット レジスタを格納して、自分自身を節約できると考えました。いくつかのメモリのロード/ストア。さらに、EMMS を使用して FPU の状態を保存する必要はありません。これは目的に反します。浮動小数点レジスタを実際に操作するのではなく、ストレージとしてのみ使用するためです (とにかく、x87 ユニットはほとんど使用されません)。 x64 (基本的に SSE に取って代わられるため)

私は変更を行い、それは機能します (クラッシュはなく、パフォーマンスが 4% 向上しています)。しかし、この「ハック」が本当に機能するのか、それとも見逃した可能性のある特定の副作用 (FPU 状態など) が導入されるのか疑問に思っています。使ってないのに腐敗とか、そういうものです)。また、FPU レジスタへのロード/ストアは、現在のアーキテクチャのメモリ ロード/ストアよりも常に高速ですか?

そして、はい、この最適化は本当に必要です。公平を期すために、これはコードのメンテナンス コストを大幅に低下させるものではなく、1 行のコメントでそのトリックを説明するのに十分です。したがって、意図しない結果なしに無料でバイトあたりのクロック数を2、3減らすことができれば、喜んで受け取ります:)

ありがとう。

4

1 に答える 1

3

EMMS 命令は、MMX 操作後の状態をクリアするためにのみ必要です。SSE 命令では必要ありません。したがって、それは確かに競合しません。

もちろん、異なるコンパイラや OS では異なる呼び出し規則が使用され、これら 4 つのレジスタの扱いが異なる場合があることに注意してください。

ただし、それを念頭に置いている限り、このアプローチに問題はないと思います。ABIに従って使用されるはずの方法ですべてのレジスタを使用しています。

これがアセンブリで記述されていると仮定すると、これがコンパイラの最適化を妨げるかどうかを考慮する必要はありません (ASM に飛び込んで特定のレジスタについて話し始める C/C++ 関数は、コンパイラがコードを最適化することをはるかに困難にします)。

于 2012-07-14T16:00:50.023 に答える