Возвращаемое значение rdtsc: _always_ mod 10 == 0 для Atom N450.

На моем устройстве E8200 этого не происходит, но на моем нетбуке Atom N450 (оба работают под управлением OpenSuse 11.2) всякий раз, когда я читаю 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

Как легко увидеть, дельта колеблется в разумных количествах. Но бросается в глаза (не сказать, сговор;-) в том, что наименее значимая десятичная цифра всегда 0.

Я наблюдаю это явление уже более двух лет, и переполнение стека - не первый адрес, где я публикую эту проблему. Но нигде не получил разумного ответа. Идеи, которые мы (я и другие люди там) пришли в том, что

  • TSC увеличивается только каждый 10-й цикл, но затем на 10 или
  • TSC корректно обновляется внутри, но отображается только снаружи каждые 10-й цикл, или
  • TSC увеличивается на 10 за каждый цикл.

Однако ни один из этих пунктов не имеет смысла. На самом деле мне следовало запустить такую ​​программу на E8200 (которая в данный момент вышла из строя), чтобы увидеть, является ли порядок величин дельт такой же или только одна десятая из приведенных выше. (Есть добровольцы?)

Поиск в Google не помог, руководства Intel тоже не помогли.

При обсуждении с другими людьми никто не испытывал такого же поведения. Если это было связано с ядром, то пострадали как минимум 3 версии, но тогда... какое отношение ядро ​​имеет к нему?

У меня также был нетбук в эксплуатации, и он вернулся с новой материнской платой - подразумевал новый процессор, так что должны быть затронуты как минимум два отдельных объекта N450.

Я также принял меры против изменений тактовой частоты (и независимо от того, на какую частоту я установил тактовую частоту, значения менялись только в ожидаемом диапазоне (как показано на рисунке)) и отключил 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, которая показывает, что третий пункт в приведенном выше списке неверен. Но все же я понятия не имею, почему я не получаю полную точность. /Обновить]

2 ответа

Том 3B Руководства по разработке программного обеспечения гласит:

... для процессоров Intel Atom... счетчик меток времени увеличивается с постоянной скоростью. Эта частота может быть установлена ​​максимальным отношением частоты ядра к частоте шины процессора или может быть установлена ​​максимальной разрешенной частотой, с которой загружается процессор. Максимальная разрешенная частота может отличаться от максимально допустимой частоты процессора,...

Это не полностью отвечает, почему вы видите именно шаги 10, но это указывает на то, что конкретная реализация может увеличиваться на что-то отличное от 1. Я подозреваю, что вам придется взглянуть немного ближе к конкретной спецификации оборудования вашей машины и реализации BIOS, чтобы понять, почему именно 10.

BIOS вашего компьютера не поддерживает разгон процессора.

Таким образом, ваш PLL работает в постоянном соотношении.

Соотношение не может быть разным, потому что коэффициент частоты вашего Atom N450 равен 10.

Другие вопросы по тегам