
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[44.197.111.121] |
![]() |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Имхо замерять время выполнения всей программы наоборот не имеет смысла - если снимать профайл, то с отдельных её участков. Если вместо связки QPC/QPF использовать RDTSC/CPU.freq, то это позволит вычислять время вплоть до нано/секунд, т.е. даже единичные инструкции (например узнать, насколько в цикле лучше DEC,чем LOOP).
Сейчас-же, всё зависит от частоты таймера QPerfFrequency(), макс.значение которого всего 14 MHz (и то, если задействован HPET, а так 3). Поэтому логичней, взять за основу сразу частоту CPU 1..3 GHz, и его счётчик тактов TSC. Бонусом, не помешала-бы и сериализация на входе/выходе через инструкцию LFENCE.. т.е. учитывать спекулятивное выполнение кода процессором. А вообще, для таких случаев в составе Ntdll.dll имеется набор спец.функций NtCreateProfile(), которые в качестве метронома используют таймер локального контролёра LAPIC. Этот таймер работает на частоте шины FSB/DMI (100..200 MHz), а значит и он уступает связке RDTSC+CPUfreq. Однако эти функции точились индусами специально для профайлеров, так-что сбрасывать их со-счетов было-бы глупо. Эта тема была разделена из темы "КТЗ!" |
Сообщ.
#2
,
|
|
|
Цитата core-i7 @ Поэтому логичней, взять за основу сразу частоту CPU 1..3 GHz, и его счётчик тактов TSC. Бонусом, не помешала-бы и сериализация на входе/выходе через инструкцию LFENCE.. т.е. учитывать спекулятивное выполнение кода процессором. А можно пример кода, как это запрограммить? |
Сообщ.
#3
,
|
|
|
..что-то в этом роде:
![]() ![]() ;====== Частота процессора mov ecx,2 @@: push ecx lfence rdtsc push eax invoke Sleep,500 rdtsc pop ebx sub eax,ebx mov ebx,500000 cdq div ebx pop ecx dec ecx jnz @b mov [cpuFreq],eax ; запомнить cinvoke printf,<10,' CPU freq..: %d MHz',0>,eax ;====== Частота таймера invoke QueryPerformanceFrequency,qpf mov eax,[qpf] mov ebx,1000000 cdq div ebx cinvoke printf,<10,' Timer freq: %d.%d MHz',0>,eax,edx ;====== Погрешность = 2 инструкции: сериализация LFENCE, и чтение TSC lfence rdtsc push eax lfence rdtsc pop ebx sub eax,ebx mov [fix],eax ; запомнить ;*************************** ; Профайлер ;*************************** lfence rdtsc push eax ;<----- Сюда вставляем профилируемые инструкции lfence rdtsc pop ebx sub eax,ebx sub eax,[fix] push eax fild dword[esp] ; такты fidiv [cpuFreq] ; разделить на частоту процессора fstp [fpuBuff] ; время в нано/секундах pop eax cinvoke printf,<10,'%u Takt = %.3f Micro/sec',0>,\ eax, dword[fpuBuff], dword[fpuBuff+4] Здесь я вывел частоту таймера QPF, чтобы сравнить её с частотой процессора. Если QPF возвратит 3.5 MHz, значит система использует в качестве основного ACPI-таймер (3.579545 MHz), если больше 10 MHz - HPET (в идеале 14). В любом случае, QPF в десятки раз отстаёт от процессора. |
![]() |
Сообщ.
#4
,
|
|
core-i7, привет, Тимур
![]() Хм... я всегда думал, что QPC тоже использует использует rdtsc или rdtscp (по крайней мере, эта инструкция там есть) и сдвигает результат на 10 бит, но QPF выдал 10 млн, что наводит на размышления. Зачем же тогда там эти rdtsc? ![]() Т.к. lfence ставит барьер только на чтение и не гарантирует, что перед rdtsc влезет одна из последующих инструкций, я бы делал так всё же: ![]() ![]() mfence rdtsc mfence Вот хорошая дока по этой теме: http://www.mkurnosov.net/uploads/Main/mkur...-rdtsc-2014.pdf А есть ещё инструкция rdpmc, которая как раз для профайлинга предназначена, но она сложнее в использовании и не всегда нужна. К тому же, она привилегированная (в винде, в линуксе, видимо, тоже), нужно драйвер писать, хотя у Агнера Фога уже есть: https://www.agner.org/optimize/#testp Добавлено Можно ещё приоритет потока выставлять по максимуму, кстати. |
Сообщ.
#5
,
|
|
|
Женя, салам!
Цитата Jin X @ но QPF выдал 10 млн, что наводит на размышления. Зачем же тогда там эти rdtsc? 10 илн, это значит 10 MHz чтоли? (т.к. там в наносек блоках) У меня на буке тоже не подымается выше 10-ти, хотя это HPET и частота его 14 MHz. а rdtsc наверное там для какой-нибудь калибровки. |
Сообщ.
#6
,
|
|
|
[cut по просьбе автора]
Лично мне вот интересно, предложения core-i7 смогут ли улучшить точность С++ шного std::chrono::high_resolution_clock? И чуйка мне подсказывает "несомненно" (я всегда надеюсь на лучшее, прогрессивное и спортивное)! [cut по просьбе автора] Цитата Jin X @ Хм... я всегда думал, что QPC тоже использует использует rdtsc или rdtscp В качестве антиоффтопика ... когда я увидел код от core-i7, сразу побежал интересоваться незнакомыми мне командами ![]() |
![]() |
Сообщ.
#7
,
|
|
Цитата core-i7 @ QFP выдаёт частоту, т.е. 10 млн - это 10 МГц. При чём тут наносекунды? 10 илн, это значит 10 MHz чтоли? (т.к. там в наносек блоках) |
Сообщ.
#8
,
|
|
|
Скрытый текст Эх ... удалил такое искреннее сообщение от себя ![]() ![]() Добавлено Ну мож быть ... тебе виднее - но я заметил именно профилирование. Но спорить не хочу совсем - мне диалог дальнейший интересен. Мое мнение ... та-сяк ... слушать интереснее, особенно если собеседники плотно в теме. |
![]() |
Сообщ.
#9
,
|
|
Цитата JoeUser @ Не понимаю, о чём ты?Эх ... удалил такое искреннее сообщение от себя За два года модерства - расслабился, потерял чуйку! Если надо, можно найти сообщение (отредактированное, удалённое). Но с этим лучше в Л.С., чтобы не засорять обсуждение. Цитата JoeUser @ Не в заголовке суть, а в великих речах, глаголящих истину Ну мож быть ... тебе виднее - но я заметил именно профилирование. ![]() |
![]() |
Сообщ.
#10
,
|
|
Что любопытно, XP (виртуальная) выдаёт 3ГГц, а 7ка уже 10МГц
Добавлено core-i7, поправь-таки код. Частота путает уменьшаемое и вычитаемое, все замеры путают знаковую и беззнаковую арифметику, а целочисленную арифметику замени на 64-битную, ибо странно наблюдать отрицательные Micro/sec |
![]() |
Сообщ.
#11
,
|
|
Цитата Qraizer @ В 98 вообще 1.19 МГц Что любопытно, XP (виртуальная) выдаёт 3ГГц, а 7ка уже 10МГц ![]() Там таймер 8254 используется ![]() |
Сообщ.
#12
,
|
|
|
Подкину дровишек.
1) Для виртуализации TSC сохраняется в контексте процесса и после загружается обратно. Причем виндоус использует это всегда. 2) Цитата В давние времена да. е RDTSC+CPUfreq. Однако эти функции точились индусами специально для профайлеров, Суть в том что если делать x64 программы то там эта комбинация плавает в отрицательные области. А х32- программах индусы всё же сделали что'бы они не плавали. 3) Цитата таймер локального контролёра LAPIC. Этот таймер работает на частоте шины FSB/DMI (100..200 MHz), Там не 100 Мгц, а частота RDTSC. Только младшие биты 4-5 бит они не контролируют. 4) Для профилирования есть PerformanceCounter нужен драйвер. У интела есть IntelPerformanceCounterMonitor-PCM-V2.10 нужно только GUI или API прекрутить. |
![]() |
Сообщ.
#13
,
|
|
Цитата Qraizer @ Как вариант:core-i7, поправь-таки код Скрытый текст ![]() ![]() format PE Console 4.0 entry start include 'win32axp.inc' ;-- CODE SECTION ------------------------------------------------------------------------------------------------------- macro ReadTSC { mfence rdtsc mfence } .code start: invoke SetThreadPriority, -2, THREAD_PRIORITY_TIME_CRITICAL ;====== Частота процессора ReadTSC push eax push edx invoke Sleep,1000 ReadTSC pop ecx pop ebx sub eax,ebx sbb edx,ecx push edx push eax fild qword[esp] add esp,8 fidiv [N1M] fistp [cpuFreq] cinvoke printf,<10,' CPU freq: %d MHz',0>,[cpuFreq] ;====== Частота таймера invoke QueryPerformanceFrequency,qpf fild [qpf] fidiv [N1M] fstp [fpuBuff] cinvoke printf,<10,'Timer freq: %f MHz',0>,dword[fpuBuff],dword[fpuBuff+4] ;====== Погрешность = 2 инструкции: сериализация LFENCE, и чтение TSC ReadTSC push eax ReadTSC pop ebx sub eax,ebx mov [fix],eax ; запомнить ;*************************** ; Профайлер ;*************************** ReadTSC push eax ;<----- Сюда вставляем профилируемые инструкции ReadTSC pop ebx sub eax,ebx sub eax,[fix] push eax fild dword [esp] ; такты fidiv [cpuFreq] ; разделить на частоту процессора fstp [fpuBuff] ; время в микросекундах pop eax cinvoke printf,<10,'%i ticks = %f microsec',0>,\ eax, dword[fpuBuff], dword[fpuBuff+4] cinvoke getch invoke ExitProcess, 0 ;-- DATA SECTION ------------------------------------------------------------------------------------------------------- .data N1M dd 1000000 cpuFreq dd ? fix dd ? qpf dq ? fpuBuff dq ? ;-- IMPORT SECTION ----------------------------------------------------------------------------------------------------- section '.idata' import data readable library kernel32, 'kernel32.dll',\ msvcrt, 'msvcrt.dll' import_kernel32 all_api import msvcrt,\ printf, 'printf',\ getch, '_getch' |
Сообщ.
#14
,
|
|
|
Скрытый текст Цитата Jin X @ Не понимаю, о чём ты? Это и хорошо! 30 гратусов тов. Цельсия в тени меня сводят с ума - и я уже кидаюсь на всех аки собака Баскервили) |
![]() |
Сообщ.
#15
,
|
|
Цитата Jin X @ У меня этот код в виртуальной Win98 показывает время пустого кода минус несколько тысяч тактов, в 10-ке в районе -20 (в среднем), на домашнем около нуля (+/-). Любопытненько, однако...Как вариант И ещё на домашнем частота 3300 измеряется, на вирт. 3700. Хотя всякие там CPU-Z показывают 3700. На самом деле у меня небольшой штатный разгон: 3300 -> 3700. Это что, так Invariant TSC работает? Цитата Pavia @ А если поподробнее? 1) Для виртуализации TSC сохраняется в контексте процесса и после загружается обратно. Причем виндоус использует это всегда. |