Хорошо, так как другой ответ не помог, я постараюсь объяснить более подробно. Проблема в том, что современный процессор может выполнять инструкции не по порядку. Ваш код начинается примерно так:
rdtsc
push 1
call sleep
rdtsc
Современные процессоры не обязательно выполняют инструкции в их первоначальном порядке. Несмотря на ваш первоначальный порядок, процессор (в основном) может выполнять, как:
rdtsc
rdtsc
push 1
call sleep
В этом случае ясно, почему разница между двумя rdtsc
с будет (по крайней мере, очень близка к) 0. Чтобы предотвратить это, вам нужно выполнить инструкцию, что ЦП будет никогда переставить выполнять из строя. Самая распространенная инструкция для этого - CPUID
. Другой ответ, который я связал, должен (если память не изменяет) начаться примерно оттуда, о шагах, необходимых для правильного / эффективного использования CPUID
для этой задачи.
Конечно, возможно, что Тим Пост был прав, и вы также видите проблемы из-за виртуальной машины. Тем не менее, в его нынешнем виде нет гарантии, что ваш код будет работать правильно даже на реальном оборудовании.
Изменить: почему код будет работать: во-первых, тот факт, что инструкции могут выполняться не по порядку, не гарантирует, что они будет будет. Во-вторых, возможно, что (по крайней мере, некоторые реализации) sleep
содержат инструкции сериализации, которые не позволяют переставить rdtsc
вокруг него, в то время как другие этого не делают (или могут содержать, но выполняют только при определенных (но не указанных) обстоятельства).
То, что у вас осталось, - это поведение, которое может измениться практически при любой повторной компиляции или даже между одним запуском и следующим. Он может давать чрезвычайно точные результаты десятки раз подряд, а затем потерпеть неудачу по какой-то (почти) совершенно необъяснимой причине (например, что-то, что произошло в каком-то другом процессе полностью).