4

3 つの異なる周波数を使用して、3 台の異なるコンピューターでコードをプロファイリングしています。GFLOPs/s を測定するには周波数が必要です。これを行うコードがいくつかありますが、Turboboost を考慮していません。たとえば、私の 2600k CPU では 3.4 GHz と報告されますが、CPUz を実行すると、すべてのコアを使用するコードで CPU が 4.3 GHz (オーバークロック) で実行されていることがわかります。

#include "stdint.h"
#include "stdio.h"
#include "omp.h"
int main() {
    int64_t cycles = rdtsc(); double dtime = omp_get_wtime();
    //run some code which uses all cores for a while (few ms)   
    dtime = omp_get_wtime() - dtime;
    cycles = rdtsc() - cycles;
    double freq = (double)cycles/dtime*1E-9;
    printf("freq %.2f GHz\n", freq);
}
__int64 rdtsc() {
#ifdef _WIN32
    return __rdtsc();
#else
  uint64_t t;
  asm volatile ("rdtsc" : "=A"(t));
  return t;
#endif
}  

この質問はさまざまな回答で何度も尋ねられていることは知っていますが、これが可能かどうかはまだわかりません。タイマーを変更しようとするハッカーは気にしません。このコードは自分専用です。コードで実際の周波数を取得することは可能ですか? これは Linux でどのように行われますか? Linuxで見つけたすべての例は、基本周波数(またはおそらく最大)を示していますが、CPUzのように負荷がかかった状態での動作周波数は示していません。

編集:実際の動作周波数を示しているように見える Linux 用のプログラム、Powertop を見つけました。ソースコードが利用可能であるため、自分のコードで実際の周波数を取得する方法を理解できるかもしれません。

4

1 に答える 1

0

私はついにこの問題を解決しました。デバイス ドライバや特別なカウンタの読み取りを必要とせずに、コードで実際の動作周波数を測定することができます。

基本的に、常に同じレイテンシーを取る実行ループ依存関係を持つ操作のループの時間を計ります。例えば

for(int i=0; i<spinCount; i++) {
    x = _mm_add_ps(x,_mm_set1_ps(1.0f));
}

このループは、各物理コア (論理コアではない) にバインドされたスレッドで実行します。システム内に他のスレッドがなく、これらのスレッドがかなりの CPU 時間を消費する必要がないため、このメソッドが常に正しい答えを返すとは限りませんが、私の場合は非常にうまく機能します。シングル ソケット システムとマルチソケット システムの Nahalem、Ivy Bridge、および Haswell の 1 つのスレッドと多数のスレッドで、正しいターボ周波数からの偏差が 0.5% 未満の結果が得られます。この詳細については、how-can-i-programmatically-find-the-cpu-frequency-with-c で説明したので、ここではすべての詳細を繰り返しません。

于 2014-08-21T08:20:50.003 に答える