1

プログラムのCPUサイクルを測定するために、rdtscおよびcpuid命令(揮発性インラインアセンブリ命令を使用)を使用しています。rdtsc命令は、Linux(速度最適化-o2 -fomit-frame-pointerを使用)およびWindows(MS Visual Studio 2008用の速度最適化オプションCコンパイラー(VC 9.0)を使用)でのプログラムに現実的な結果をもたらします。

最近、私は新しいプログラムを実装しました。これは、多くのテーブルルックアップなどを使用します。ただし、Linuxでのgcc最適化を使用したこのプログラムのrdtsc測定では、予想よりも常に誤った測定値(CPUサイクル数が非常に少ない)が発生します。Windowsで実行しているときの同じプログラムのrdtsc測定(前述の最適化とコンパイラーでコンパイルされたもの)は現実的であり、期待に応えます。

私の質問は、gcc最適化が揮発性アセンブリ命令を上記の動作を生成する場所に移動する方法はありますか?

タイマーの私のコードを以下に示します。

#define TIMER_VARS                                                 \
  uint32 start_lo, start_hi;                                       \
  uint32 ticks_lo, ticks_hi

#define TIMER_START()                                              \
  __asm__ __volatile__                                             \
     ("rdtsc"                                                      \
     : "=a" (start_lo), "=d" (start_hi) /* a = eax, d = edx*/      \
     : /* no input parameters*/                                    \
     : "%ebx", "%ecx", "memory")

#define TIMER_STOP()                                               \
  __asm__ __volatile__                                             \
     ("rdtsc"                                                      \
     "\n        subl %2, %%eax"                                    \
     "\n        sbbl %3, %%edx"                                    \
     : "=&a" (ticks_lo), "=&d" (ticks_hi)                          \
     : "g" (start_lo), "g" (start_hi)                              \
     : "%ebx", "%ecx", "memory")

誰かがこれについていくつかのアイデアを提案することができれば、私は非常にありがたいです。

ありがとう、

4

2 に答える 2

3

インラインrdtsc関数がロード/ストア/その他の操作間で移動されないようにするには、asm を asm として記述し、clobber リストに__asm__ __volatile__含める必要があります。"memory"後者を行わないと、GCC は asm を削除したり、asm の結果を必要とする (または入力を変更する) 必要がある命令にまたがって移動したりすることはできなくなりますが、関連のない操作に関しては移動できます。クロバーとは、GCC がメモリの内容 (アドレスが漏えいした可能性のある変数) が asm 全体で同じままであると想定できないことを意味し、その"memory"ため、メモリの移動がはるかに困難になります。ただし、GCC は、アドレスが取得されたことのないローカル変数のみを変更する命令間で asm を移動できる場合があります (それらは取得されていないため)。"memory")。

ああ、wildplasser がコメントで言ったように、これに多くの時間を無駄にする前に、asm 出力を確認してください。

于 2012-05-09T16:02:21.580 に答える
1

それが正しいかどうかはわかりませんが、私がかつて使用したコードは次のとおりです。

#define rdtscll(val) \
      __asm__ __volatile__("rdtsc" : "=A" (val))

typedef unsigned unsigned long long Ull;

static inline Ull myget_cycles (void)
{
Ull ret;

rdtscll(ret);
return ret; 
}

AMDよりもIntelの方が「遅かった」ことを覚えています。YMMV。

于 2012-05-10T17:09:39.723 に答える