Вы хотите, чтобы lfence;rdtsc
- запустили часы, и rdtscp;lfence
остановили часы, поэтому барьеры находятся за пределами временного интервала.
(Или иногда вы хотите lfence;rdtsc;lfence
для запуска часов, для дополнительной повторяемости за счет дополнительных накладных расходов.)
MFENCE - неправильная инструкция для этого;не гарантируется сериализация потока команд (но на практике это происходит в Skylake с современным микрокодом, чтобы исправить ошибку).LFENCE сериализует поток команд, не дожидаясь, пока буфер хранилища опустеет, только для ROB.Это всегда верно для Intel, но на AMD только с включенным смягчением Spectre, что делает lfence
не просто NOP.(Полагаю, AMD не переупорядочивает movntdqa
загрузки из памяти WC, поэтому lfence
не имеет смысла в качестве барьера памяти, а только полезен в качестве барьера выполнения против спекулятивного выполнения или для RDTSC.)
См. Также Получить счетчик циклов ЦП? , в котором есть раздел о сериализации rdtsc
.Но вам также не нужен встроенный ассемблер для этого;используйте __rdtsc()
и _mm_lfence()
.(Но, как обычно, с микробенчмарками, неплохая идея проверить вывод asm компилятора, чтобы убедиться, что он сделал то, что вы хотите.)
Вы не можете избежать накладных расходов, это всегда будетбыть значительным по сравнению со стоимостью пары инструкций.
Также clflush для аннулирования строки кэша с помощью функции C для примера вычитания накладных расходов на измерения.
Но также обратите внимание, что обычно более полезно помещать тестируемый код в цикл, потому что задержка выполнения до того, как результат будет готов, является более значимой, чем ожидание, пока инструкция (ы) фактически не удалится из ROB.См. RDTSCP в NASM всегда возвращает одно и то же значение для примера (в asm) измерения одного insn для пропускной способности / задержки.