Dmitry_Milk Что зачем. Вроде я понятно обьяснил. Зачем вообще измерять время исполнения кода =) Для не понятливых обьясню проще. Есть код. Нужно узнать сколько времени занимает его исполнение вне зависимости от внешних факторов. Причём время измерения мало(не миллиарды итераций, как обычно вы мерите своим rdtsc).
gaeprust это да. а разве нет возможности определить, что проц нырял в прерывание? вроде, вы ж и писали, что тф сбрасывается или дс восставливается, чтото такое вроде. на крайний случай, можно предположить, что прерывания происходят достаточно редко и запускать бенч после него. те, в начале определяем колво тактов на квант. потом ждем прерывания. после выхода из него, если оно произошло не под конец такта - запускаем бенч. немного сложно, немного ненадежно с прерываниями, но реализуемо (и первое, что в голову пришло)
gaeprust "Своим" rdtsc "мы", согласно учению великого Фога, как раз и измеряем малые интервалы. Чем меньше интервал относительно вел-ны кванта (в пределах разумного ес-но), тем надежнее его можно определить статистическим методом - просто провести 5-10 измерений и взять из них 2-3 наименьших значения (и таким образом отбросить возможные выбросы за счет виндовых прерываний). Если же речь идет о длительных измерениях типа обработки файлов или "перелопачивании" больших объемов памяти, то эти штуки сами по себе дают нехилый разброс по времени, и соотв-но учет\неучет виндовых прерываний тут существенной роли не играет - опять же для надеги производим несколько измерений и "на глаз" оцениваем разброс\правдоподобность рез-тов и значимость различий для разных вариантов обработки
Тогда механизм будет примерно следующим(одна итерация измерения): Код (Text): Tq = TSC() WaitNextQuantum() ; Ожидаем начало нового кванта. SetIntTrigger() ; Взводим триггер для ожидания возврата из Int. Do ; Цикл ожидания возврата из Int. Ti = TSC() Loop GetIntTrigger() ; Триггер взведён - прерывание закончено. if QuantumSignal() ; Проверяем начало нового кванта. Tq = TSC() - Tq ; Новый квант. Вычисляем длительность кванта. fi Ti = TSC - Ti ; Длительность прерывания или кванта.
задача не имеет практического смысла увы за некоторыми исключениями а некоторым исключениям такая точность не нужна и спалится сиюсекундно иначе не имею причины даже задумываться над тем что сказано и все же есть участок - поток при начале выполнения ставим метку времени с учетом частоты и учетом выполения кода определения частоты и поставки в память метки перехватываем своп потоков там обрабатываем время свопа а именно время свопа время выполнения потока1, 2, 3, n, потом ловим переключение потока на наш и вычитаем
punxer #1: юзермод. Память можно залочить в юзермоде(MmProbeAndLockPages() весьма просто используется, через RC-атаку на некоторые сервисы, либо просто частым обращением к буферу из другого треда).
Можно еще простой способ ~ замера времени GetThreadTime() вернет количество времени которое отработал поток (по мнению планировщика)
Нельзя на разных системах оно разное. Более того даже в рамкаж одной системы нестабильно. Ерунду написали. rdtsc счетчик количества тактов с момента последнего сброса процессора
Зачем ? Зачем вычленять точное время а потом вводить поправочные коэфф. если можно СРАЗУ посчитать РЕАЛЬНОЕ время. Не мучай попу как говорят .... Практического смысла в этом нет вовсе.
asmlamo Околоквантовые длительности через тск не измеряют. Обычно накапливается статистика в течении секунд или десятков секунд для получения необходимой точности(ядро при загрузке например определяет реальные MHz камня, используя большое число итераций). Например длительность исполнения какого то сервиса единичного так не измерить, нужно учесть квантование. Если измерить реальное время исполнения, то можно определить и время исполнения этого кода например с !EFlags.IF. Да и вообще хочу знать сколько времени процессор исполняет код на данном потоке, а сколько простаивает.
Фо фан можно вычесть время загрузки системы в простое(винда наверняка в состоянии предоставить метрики). Для больших замеров это не нужно, так как 5% погоды не сделают. Для маленьких тоже - оно быстрее закончится чем квант. VTune просто прогоняет серию тестов и не заморачивается. Практика показывает, что время выполнения одного и того же кода может хорошо различаться(кэш, фигеш), так что одним прогоном всё равно не обойтись и вообще это фантасмагория.
гдето такой простейший бенчик пришел в голову Код (Text): #include <stdio.h> #include <windows.h> void test_Q(){ unsigned t_h, t_l; _asm{ pusha } Init: _asm{ mov esi,0 mov edi,0 mov ebx,0 mov ecx,0 rdtsc push edx push eax } Q_wait: _asm{ pop esi pop edi xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx rdtsc push edx push eax sub eax,esi sbb edx,edi jnz Q_begin cmp eax,100 jc Q_wait } Q_begin: _asm{ mov eax,0 mov edx,0 } Q_time: _asm{ add ebx,eax adc ecx,edx pop esi pop edi xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx xchg eax,edx rdtsc push edx push eax sub eax,esi sbb edx,edi jnz Q_end cmp eax,100 jc Q_time } Q_end: _asm{ pop esi pop edi test ebx,ebx jz Init mov t_l,ebx mov t_h,ecx popa } printf("Q time = %d:%d\n", t_h, t_l); } void test_sleep0(){ unsigned t_h, t_l; _asm{ pusha } Sleep(0); _asm{ rdtsc push eax push edx } Sleep(0); _asm{ rdtsc pop ecx pop ebx sub eax,ebx sbb edx,ecx mov t_l,eax mov t_h,edx popa } printf("Sleep(0) time = %d:%d\n", t_h, t_l); } int main(){ int i; for(i = 0; i < 20; i++) test_Q(); // for(i = 0; i < 20; i++) // test_sleep0(); return 0; } показания довольно стабильные и мало зависят, например, от загрузки проца. но очень часто наблюдается задержка сразу после выхода в квант (test ebx,ebx; jz Init). с чем связана не знаю. возможно, с тем, что используется память (стек). или кэшированием кода (вряд ли). прерывания заметны тоже. особенно большая помеха от сети и таймеров. там ниже тест слипа. это больше для себя. интересно, что если убрать предварительный слип, то время тестируемого увеличивается вдвое. слип(0) ныряет в ядро и сразу же возвращается не ожидая очередного кванта (абыдна. придется переделать пару вещей). слип(1) берет время както уж очень хаотично. бывает и заметно меньше вымученного времени кванта, бывает и заметно больше. больше понятно, но почему меньше? сразу и вопрос - если слип(0) не пропускает квант, то что можно использовать чтобы остановить поток в этом, но нормально получить следующий квант? а может, я тут ошибся все. если так, то поправьте.
qqwe А зачем так все сложно? В чем смысл этих конструкций вокруг rdtsc, в двух словах плз. Свопился ли поток можно смотреть по gs, при свопе сбрасывается.