5

私のE8200ボックスではこれは発生しませんが、Atom N450ネットブック(両方ともOpenSuse 11.2を実行)では、CPUのTSCを読み取るたびに、戻り値はmod 10 == 0、つまり、余りが10で割り切れない状態です。RDTSCを使用しています興味深いコードがかかる時間を測定するための値ですが、デモンストレーションの目的で、この小さなプログラムを作成しました。

        .text
        .global _start

_start: xorl    %ebx,%ebx
        xorl    %ecx,%ecx
        xorl    %r14d,%r14d
        movb    $10,%cl
loop:   xchgq   %rcx,%r15          # save to reg
        cpuid
        rdtsc
        shlq    $32,%rdx
        xorq    %rax,%rdx          # full 64 bit of RDTSC
        movq    %r14,%r13          # save the old value
        movq    %rdx,%r14          # copy current
        movq    %r14,%rsi          #  argv[1] of printf()
        subq    %r13,%rdx          #  argv[2] (delta)
        leaq    format(%rip),%rdi  #  argv[0]
        xorl    %eax,%eax          #  no stack varargs
        call    printf
        xchgq   %rcx,%r15
        loop    loop

0:      xorl    %eax,%eax
        movb    $0x3c,%al
        syscall

        .size   _start, .-_start

        .data
format: .asciz     "rdtsc: %#018llx = %1$llu -- delta: %llu\n"

(私は通常、変換に独自のルーチンを使用しますが、読者がエラーが存在する可能性があることを示唆しないようにするために、ここではprintf()を使用しています。)

上記のコードでは、出力は(たとえば)次のようになります。

rdtsc: 0x000b88ef933ffd06 = 3246787292822790 -- delta: 3246787292822790
rdtsc: 0x000b88ef9342fcf4 = 3246787293019380 -- delta: 196590
rdtsc: 0x000b88ef93435dca = 3246787293044170 -- delta: 24790
rdtsc: 0x000b88ef9343b43c = 3246787293066300 -- delta: 22130
rdtsc: 0x000b88ef93440c34 = 3246787293088820 -- delta: 22520
rdtsc: 0x000b88ef9344604e = 3246787293110350 -- delta: 21530
rdtsc: 0x000b88ef9344b4d6 = 3246787293131990 -- delta: 21640
rdtsc: 0x000b88ef9345085a = 3246787293153370 -- delta: 21380
rdtsc: 0x000b88ef93455d96 = 3246787293175190 -- delta: 21820
rdtsc: 0x000b88ef9345b16a = 3246787293196650 -- delta: 21460

簡単にわかるように、デルタは妥当な量で変化します。しかし、目立つのは(共謀しているとは言えませんが;-)、最下位の10進数が常に0であるということです。

私はこの現象を2年以上観察してきましたが、StackOverflowはこの問題を公開する最初のアドレスではありません。しかし、私はまだどこにも合理的な答えを得ることができませんでした。私たち(私や他の人々)が思いついたアイデアは、

  • TSCは10サイクルごとにのみインクリメントされます、その後10ずつインクリメントされます。
  • TSCは内部で正しく更新されますが、10サイクルごとにのみ外部に反映されます。
  • TSCはサイクルごとに10ずつ増加します。

ただし、これらの点はどれも実際には意味がありません。E8200(現在は故障しています)でそのようなプログラムを実際に実行して、デルタの大きさのオーダーが上記の出力のオーダーと同じか、それとも10分の1にすぎないかを確認する必要があります。(ボランティアはいますか?)

グーグルは役に立たなかった、インテルのマニュアルも役に立たなかった。

他の人と話し合うとき、同じ行動を経験した人は他にいませんでした。カーネルと関係がある場合、少なくとも3つのバージョンが影響を受けましたが、カーネルはそれと何の関係がありますか?

ネットブックも稼働していて、新しいマザーボードが戻ってきました。これは、新しいCPUを意味するため、N450の少なくとも2つの個別のエンティティが影響を受ける必要があります。

また、クロック周波数の変化に対する対策を講じ(クロックを固定した周波数に関係なく、値は予想される範囲でのみ変化しました(図と同じ))、HTをオフにしましたが、これらは実際にそれらを防ぐのではなく、他のいくつかの最下位桁。しかし、念のために。

さて、誰かが自分のマシンでプログラムを実行したい場合、コマンドラインは次のとおりです(ソースをファイルに保存する場合rdtsc.s):

as rdtsc.s -o rdtsc.o
ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 rdtsc.o -L /lib64 -l c -o rdtsc

gccフロントエンドでビルドするには、つまり

gcc -l c rdtsc.s -o rdtsc

_start:ラベルを追加(またはラベルを置き換える)しmain:て、グローバルにする必要があります。

[更新(2012-09-15〜21:15 UTC):実際には以前にもこれを行うことができました:の前後にTSCを取得させるだけでsleep(1)、1,666,000,000をわずかに超えるデルタが得られます。上記のリストのポイントが間違っています。しかし、それでも私は完全な精度が得られない理由がわかりません。/アップデート]

4

2 に答える 2

2

Software Development Manual の Volume 3B には、次のように書かれています。

... Intel Atom プロセッサの場合 ... タイムスタンプ カウンターは一定の割合で増加します。そのレートは、プロセッサの最大コアクロック対バスクロック比によって設定されるか、プロセッサが起動される最大解決周波数によって設定される場合があります。解決された最大周波数は、プロセッサの最大認定周波数とは異なる場合があります...

それは、具体的に 10 のステップが表示されている理由を完全に答えているわけではありませんが、特定の実装では 1 以外の値を自由にインクリメントできることを指摘しています。マシンのハードウェア仕様と BIOS 実装を調べて、正確に 10 である理由を発見してください。

于 2012-09-12T19:34:03.413 に答える
1

お使いのコンピューターの BIOS は、CPUアンダークロックをサポートしていません。

したがって、PLLは一定の比率で実行されます。

Atom N450のクロック レート比は 10 であるため、比率が異なることはありません。

于 2012-10-04T17:25:11.240 に答える