Войти
ПрограммированиеФорумОбщее

Delphi: Точный таймер (Win API) (комментарии) (6 стр)

Страницы: 1 2 3 4 5 6
#75
(Правка: 1:52) 1:45, 28 апр. 2020

exchg
> Подкину еще дегтя в твой метод
Я когда первый раз gettickcount использовал, он мне выдавал время обновляемое ровно 1/60 секунды. И так получилось что с Vsync давал выполняться этому методу тоже через 1/60 секунды. В результате эти микро сдвиги добавляли +-1/60. То есть интервал был либо 0 либо 2/60. И это давало заметные прыжки при анимации. Но вот чтобы таким заморачиваться с RTDC или QPC это надо быть Флешем. Ну это же +-1/1000000 и меньше.

#76
(Правка: 2:42) 2:22, 28 апр. 2020

foxes
> Но вот чтобы таким заморачиваться с RTDC или QPC это надо быть Флешем. Ну это
> же +-1/1000000 и меньше.
А откуда ты знаешь сколько там погрешность получится в итоге? Может там погрешность превысит точность? Проблема в том, что в том же gettickcount ты знал ширину ступеньки и у тебя была известна погрешность, а тут такова нету, сколько там получится в дельте от разных счетчиков - неизвестно. Где то от нуля до максимального значения счетчика.

А самое забавное тут то, что оно будет работать правильно в +90% случаев и выстрелит в самый неожиданный момент. Например жизнерадостный Delfigamer считает, что проскочит с пачкой семплов, а погрешность поймает статистикой, он так всегда делал. Но сегодня его процесс слегка отогнули на обочину и частота смены ядра критически выросла. В итоге он намерил херни и ломает голову что пошло не так свято веря в реальность цифирей.

#77
3:25, 28 апр. 2020

exchg
> Например жизнерадостный Delfigamer считает, что проскочит с пачкой семплов, а
> погрешность поймает статистикой, он так всегда делал. Но сегодня его процесс
> слегка отогнули на обочину и частота смены ядра критически выросла. В итоге он
> намерил херни и ломает голову что пошло не так свято веря в реальность цифирей.
Ну открою диспетчер задач и поставлю максимальный приоритет. Вместо замера Trace буду замерять каждый IntersectRayWithPlane по отдельности.
В этом, кстати, и заключается преимущество tsc - он достаточно детализированный, чтобы измерять интервалы в тысячи и сотни тактов процессора; в то время как QPC, по вашим же статьям, может гранулироваться по тысячам (и разницу между 4900 и 5500 не увидит); а GetTickCount, вон, у Фоксеса вообще тикает раз в 10^8.

exchg
> Если мы допустим что оно так, то т.к.:
> ты не можешь знать размер сэмпла наперед, ты его как раз измеряешь.
> размер слайса тоже не константа (даже близко). Даже больше эта величина вне
> твоей системы вообще. На нее закладываться вообще нельзя.
> То возникает законный вопрос (если откинем послезнание) на основании чего
> сделан вывод, что семпл будет меньше слайса? )))
А зачем ты откидываешь послезнание? Не надо его откидывать.
На основании того и делаем, что засекаем по таймеру и видим результат.

И у тебя какое-то неправильное представление о том, зачем мне нужен tsc. Прежде всего - это инструмент отладки, а никак не таймер для основной логики приложения. Подобно тому, как никто в здравом уме не выкладывает дебаг-билды в релиз - точно так же и tsc предназначен именно для разработчика, а не для пользователя.
Соответственно, если какие-то требования не выполняются - например, видеоплеер кванты отжирает, или измеряемый интервал в 10 раз длиннее слайса - то совершенно естественно будет не оборачивать таймер свистелками на все случаи жизни, а закрыть плеер, переместить timer.start/timer.stop внутрь цикла и запустить рендерер на сцене попроще.

И вообще, изначально, главная мысль звучала именно так:
> Если только нас не интересует, сколько времени тратит ОС на переключение
> контекстов.
То есть - если посреди сэмпла переключение всё-таки произошло, то мы считаем его неправильным. Без разницы, как мы это определяем - по увеличению времени в 100 раз, по запросу на номер текущего ядра или как-нибудь ещё, если было переключение - сэмпл отбрасывается. Это условие задачи.
Тогда совершенно без разницы, пользуемся ли мы стабильным QPC или переключаемся между десятью разными tsc - по самой формулировке задачи, после фильтрации, среди правильных сэмплов останутся только те, у которых t1 и t2 посчитаны на одних часах.
И именно в такой задаче, стабильность QPC оказывается бесполезной, в то время как большее разрешение tsc вместе с меньшими затратами на измерение - остаются преимуществами.

Если же тебя вдруг интересует, что это за задача, вот тебе пример - мы можем хранить матрицы в row-major или в column-major, у нас есть использующий их Trace и мы хотим выбрать вариант, с которым Trace будет работать быстрее.

#78
9:06, 28 апр. 2020

на самом деле трюки с RDTSC не сильно много дают профита имхо. ими можно очень быстро сравнивать выполнение двух вариантов кода, там достаточно и попугаев для оценки.

я часто, если оптимизирую функцию то сравниваю на сколько есть выигрыш с старым вариантом и стоит ли игра свеч. тот же ассемблер нужно минимизировать по возможности. и тут даже не столько мультиплатформенность беспокоит, сколько вероятность возникновения трудноуловимых ошибок. в том числе если компиллятор переиграет свое поведение с переменными.

с другой стороны, если я провожу такой тест, то функции катаю по миллиону циклов. там даже GTK начинает показывать чето приближенное к реальности. а стоимость QPC на миллион вызовов уже не считается и там результаты уже идентичные от теста к тесту.
тут тоже кстати есть одна тонкость. почему то всегда у функции которая прогоняется по циклу первой всегда выигрышь на определенный процент меньше, а если поменять местами то она может наоборот "победить") интересно чем вызвана эта погрешность. я понимаю что когда обсчитваешь массив то он должен еще в кеш свалиться а тут вроде переменные небольшие, на стеке.

#79
10:52, 28 апр. 2020

Delfigamer
> А зачем ты откидываешь послезнание?
Потому, что оно на то и послезнание его нету на момент измерения. На момент измерения у тебя есть предположение, что оно так должно быть.

> Ну открою диспетчер задач и поставлю максимальный приоритет
...
> Соответственно, если какие-то требования не выполняются - например
Да и вот ты все это проделал, но случился реордеринг. И твои вызовы немного не в том порядке выполнились и вся точность ушла в никуда.

> И вообще, изначально, главная мысль звучала именно так:
> Без разницы, как мы это определяем - по увеличению времени в 100 раз, по
> запросу на номер текущего ядра или как-нибудь ещё, если было переключение -
> сэмпл отбрасывается.
Меня заинтересовал вопрос о сборе статистики. А об отбрасывании вообще я говорил в самом начале - берешь rdscp и отбрасываешь все измерения где сменилось ядро (возвращается значение в регистре). Но и у него проблема с реордерингом тоже остается.

> И именно в такой задаче, стабильность QPC оказывается бесполезной, в то время
> как большее разрешение tsc вместе с меньшими затратами на измерение - остаются
> преимуществами.
А кстати, какая разница между QPC и rdtsc у тебя получается на практике?

#80
11:04, 28 апр. 2020

Mira
> на самом деле трюки с RDTSC не сильно много дают профита имхо.
Просто для каждой задачи свой инструмент.

Для анализа производительности ~10 инструкций железные методы не подходят, нужен эмулятор вроде Intel IACA.
Для работы с сотнями-тысячами инструкций — rdtsc без вариантов, как и говорит Delfigamer.
Для миллисекундных интервалов и больше уже нужны системные средства.

Кстати, советую не использовать непереносимые вещи вроде QPC/GTC/timeGetTime, вполне достаточно стандартных кроссплатформенных инструментов (я обычно использую clock()).

#81
14:26, 28 апр. 2020

Я в 2017 году это исследовал

Тест таймеров, сорец
Тест таймеров, виндовый екзешник

QPC - огрубляет до 410 наносекунд на вызов, длительность вызова такая же, как у RDTSC (~65 миллионов в секунду или около 15нс)
RDTSC - шумная, даёт в среднем 15 нс - что равно длительности вызова ея.

Вывод? Я был не прав, надо использовать QPC везде, кроме Windows 98/Me. Там использовать RDTSC либо вообще отключать профайлинг.

Microsoft Windows [Version 6.1.7601]
(c) Корпорация Майкрософт (Microsoft Corp.), 2009. Все права защищены.

d:\tmp>test_timers qpc
Testing the mighty RDTSC instruction, directly from the CPU! // гы, ашипка
  Measuring frequency... 2435898
  0ms: 57812425
  1ms: 2
  2ms: 2
  Total changes: 57812429, cycles: 57812430
  The milisecond grid is too coarse! Measuring microseconds...
  0us: 57468526
  1us: 1712
  7us: 2469
  Total changes: 57473977, cycles: 57473978
  The microsecond grid is too coarse! Measuring nanoseconds...
  411ns: 2273422
  821ns: 1051
  1000ns: 5002
  Total changes: 2279475, cycles: 65566345
press Enter to close


d:\tmp>test_timers rdtsc
Testing the mighty RDTSC instruction, directly from the CPU!
  Measuring frequency...  2.4950999010000000E+009
  0ms: 63399634
  1ms: 4
  2ms: 1
  3ms: 1
  Total changes: 63399640, cycles: 63399641
  The milisecond grid is too coarse! Measuring microseconds...
  0us: 64350913
  1us: 1811
  7us: 3029
  Total changes: 64357388, cycles: 64357389
  The microsecond grid is too coarse! Measuring nanoseconds...
  7ns: 1007
  8ns: 269317
  10ns: 5241901
  11ns: 7740186
  12ns: 8309189
  13ns: 5512086
  14ns: 7727709
  15ns: 2781930
  16ns: 8816960
  17ns: 6951703
  18ns: 3940313
  19ns: 38220
  20ns: 3433102
  21ns: 2438963
  22ns: 1504266
  23ns: 192456
  24ns: 46580
  25ns: 1192
  26ns: 26474
  27ns: 14334
  28ns: 8357
  29ns: 5296
  30ns: 3267
  32ns: 2463
  33ns: 2102
  34ns: 1618
  35ns: 3148
  36ns: 1615
  38ns: 13493
  39ns: 4429
  40ns: 12101
  41ns: 4653
  42ns: 1749
  Total changes: 65065766, cycles: 65069655
press Enter to close
#82
14:31, 28 апр. 2020

З.Ы. Вон те взбрыки в несколько микросекунд или даже милисекунд - это как раз случаи, где система упихивала тред в долгий ящик. 5 тысяч на 65 миллионов, или 0.007% всех измерений.

#83
9:19, 29 апр. 2020

Вот мои результаты по rdtsc.

+ Релевантный код

Кратко - это простейший прямой пат-трейсер, камера пускает обратный фотон, он гуляет по сцене и собирает свет с поверхностей-источников, пока не поглотится по альбедо.
Один IteratePixel содержит в себе произвольное дискретное число Trace, время дочерних функций из родительских не вычитается.
Результаты:
Изображение
Обратите внимание - графики логарифмические.

#84
21:59, 29 апр. 2020

Delfigamer
> Результаты:
Ты бы хоть оси подписал. Мне лично с этих картинок пока мало что понятно.

#85
(Правка: 23:36) 23:35, 29 апр. 2020

MrShoor
Это график частот.
В xxxperf.csv сохраняется весь std::map как есть.
sp импортируется как массив точек {показание_таймера, количество_сэмплов}.
Соответственно, Total[Last /@ sp] - что в более развёрнутом виде выглядит как Total[Map[Function[{p}, Last[p]], sp]] - посчитает суммарное количество сэмплов.
Для sp число сэмплов должно насчитать целое количество проходов по фреймбуферу 800*600 - поэтому у Total[Last /@ sp] четыре нуля справа, он пропорционален 480000.
ListPlot[sp] выводит sp как массив точек на плоскости - по x оказывается показание дельты таймера, по y - количество сэмплов с совпадающим показанием. ListLogLogPlot делает то же, и затем преобразует картинку под логарифмические оси.
Я бы назвал его "график распределения", но настоящая плотность распределения при переходе к логарифмическому икс должна масштабироваться на \(\frac{d x}{d \log x}\), а тут такого не происходит.

#86
12:16, 3 мая 2020

}:+()___ [Smile]
> Для анализа производительности ~10 инструкций железные методы не подходят, нужен эмулятор вроде Intel IACA.
Зависит как и что считать. Agner Fog же меряет.
Ну и сейчас осмысленнее MCA ( https://llvm.org/docs/CommandGuide/llvm-mca.html ).
> Для работы с сотнями-тысячами инструкций — rdtsc без вариантов, как и говорит Delfigamer.
Ну оговорки про стабильность частоты в силе. Бывает нужно реальное количество тактов.
> Кстати, советую не использовать непереносимые вещи вроде QPC/GTC/timeGetTime, вполне достаточно стандартных кроссплатформенных инструментов (я обычно использую clock()).
Если бы clock() под windows имел разрешение выше пары миллисекунд (MinGW), я бы может и согласился. А так - грубо. Сама по себе CPU time - хорошая вещь.

#87
15:59, 3 мая 2020

FordPerfect
> Зависит как и что считать. Agner Fog же меряет.
Он меряет 100500 одинаковых инструкций в цикле, это немного не то.
Я, кстати, тоже так делал: прямо в ассемблерном коде крутил цикл на 10^9 итераций и снаружи замерял время.

Обнаружил, что хранение констант в памяти, а не регистрах (это был xmm), не влияет на производительность при определенных условиях.

> Ну и сейчас осмысленнее MCA
О! Я помнил, что был опенсорсный аналог, но когда писал пост его не нашел.

> Если бы clock() под windows имел разрешение выше пары миллисекунд (MinGW), я бы может и согласился.
Я циклы бенчмарков гоняю в районе секунд каждый, мне точности хватает, особенно на моем линуксе :)
Но, думаю, и под винды есть какой-нибудь стандартный способ с нормальным разрешением.

Страницы: 1 2 3 4 5 6
ПрограммированиеФорумОбщее