Да, вроде, но это нетривиально и дает результаты, которые почти бессмысленны, по крайней мере, для большинства современных процессоров.
На относительно медленных процессорах (например, по сравнению с оригинальным Pentium в линейке Intel, все еще верно для большинства небольших встроенных процессоров) вы можете просто посмотреть в техническом описании процессора, и он (обычно) скажет вам, сколько тактов ожидать. Быстро, просто и легко.
На современном настольном компьютере (например, Pentium Pro или новее) жизнь не столь проста, как почти . Эти процессоры могут одновременно выполнять несколько инструкций и выполнять их не по порядку, если между ними нет никаких зависимостей. Это означает, что вся концепция времени, занимаемого одной инструкцией, становится почти бессмысленной. Время, необходимое для выполнения одной инструкции, может и будет зависеть от инструкций, которые ее окружают.
Тем не менее, да, если вы действительно хотите, вы можете (обычно - в зависимости от процессора) что-то измерить, хотя возникает вопрос, сколько именно это действительно будет значить. Даже получить такой результат, который только близок к бессмысленно, а не совершенно бессмысленно, не тривиально. Например, на чипе Intel или AMD вы можете использовать RDTSC для измерения времени. Это, к сожалению, может быть выполнено не по порядку, как описано выше. Чтобы получить значимые результаты, вам необходимо окружить его инструкцией, которая не может быть выполнена не по порядку («инструкция сериализации»). Наиболее распространенным вариантом для этого является CPUID
, поскольку это одна из немногих инструкций сериализации, которая доступна для программ в «пользовательском режиме» (т.е. кольцо 3). Это добавляет некоторые изюминки: хотя, как документировано Intel, первые несколько раз процессор выполняет CPUID, это может занять больше времени, чем последующие. Таким образом, они рекомендуют вам выполнить это три раза, прежде чем использовать его для сериализации вашего времени. Поэтому общая последовательность запускается примерно так:
.align 16
CPUID
CPUID
CPUID
RDTSC
; sequence under test
Add eax, ebx
; end of sequence under test
CPUID
RDTSC
Затем вы сравниваете это с результатом того же действия, но с удаленной тестируемой последовательностью. Конечно, это не учитывает подробностей - как минимум, вам необходимо:
- правильно настроить регистры перед каждым CPUID
- сохранить значение в EAX: EDX после первого RDTSC
- вычесть результат из второго RDTSC из первого
Также обратите внимание на директиву align, которую я вставил - выравнивание инструкций также может повлиять и на синхронизацию, особенно если задействован цикл.