Delfigamer
> Так в том и суть, что дельты от разных - будут среди выбросов и потому
> отрежутся.
Кем отрежутся? Что ты будешь отрезать если у тебя, скажем, половина выборки фейковая? А если большая часть? А если вся? А зачем вообще этот геморрой, если можно этого избежать?
exchg
А типа когда посреди измерения ОС выталкивает твой поток и сажает в холодильник на пару лямов, это легит статистика?
Или у тебя на работе особая версия винды, которая перекидывает поток между ядрами каждые 100 тактов?
Я исхожу из предположения, что через rdtsc мы измеряем время работы нашего кода, а не системного шедулера. И что мы измеряем каждую операцию отдельно и собираем какую-никакую статистику, а не закручиваем цикл из 100500 итераций и ищем среднее по курятнику. Это объясняет мою позицию?
Cheb
> Windows ARM - интересный вопрос. Free Pascal поддерживает только Windows CE,
> преданье старины глубокой, а Windows 10 ARM
ты просто не следишь на новостями
Оффтоп:
Delfigamer
> А типа когда посреди измерения ОС выталкивает твой поток и сажает в холодильник
> на пару лямов, это легит статистика?
И это тоже, смирись.
> Или у тебя на работе особая версия винды, которая перекидывает поток между
> ядрами каждые 100 тактов?
У меня как и у всех, SMP с пулом ядер из которого выбирается свободно ядро каждый слайс контекст свитча. А у тебя какая то версия где тебе гарантируют выполнение на одном ядре?
> Я исхожу из предположения, что через rdtsc мы измеряем время работы нашего
> кода, а не системного шедулера.
Это не верное предположение. Об этом говорит даже простой факт существования rdtscp. Ну и факт того, что такое измерение, даже будучи корректным, измеряет время твоего кода + кода ОС в том числе и шедулерра. Тем более я просто уверен что микрософт занесли прибивание треда к ядру внутрь QPC.
> И что мы измеряем каждую операцию отдельно и собираем какую-никакую статистику,
Как вы это делаете?
> Это объясняет мою позицию?
Да я ее понял сразу, я не понял как ты ее реализовывать собрался.
>Проще же просто выкидывать выбросы в дельтах.
>когда посреди измерения ОС выталкивает твой поток и сажает в холодильник
Именно. Используешь таймер - надо в любом случае быть готовым к взбрыкам и шумам, чтобы твой код был устойчив к ним. Негативные результаты отбрасываем (считаем нулём), неожиданно большие позитивные - отбрасываем, либо вообще подсистема, которая на основе этих таймингов что-то там динамически подкручивала, пропускает такт.
Потому что с любым таймером комп может улететь в гибернацию этак на месяц-другой.
Чем вас timeGetTime не устраивает?
Cheb
> Используешь таймер - надо в любом случае быть готовым к взбрыкам и шумам, чтобы
> твой код был устойчив к ним.
В данном случае с чистым rdsc ты можешь попасть в ситуацию, когда у тебя просто случайный набор дельт и весь твой поток это мусор. Ты оттуда ничего физически не выкинешь. При этом он вполне может быть похож на реальные данные. Поэтому мне почему то кажется, что лучше просто начать с того, что правильно использовать таймеры.
exchg
> Это не верное предположение.
Ты всё-таки не понял. "Мы измеряем собственное время" означает умысел, а не как-нибудь сложившийся результат. Мы не смотрим на экран и внезапно видим, что шедулера нет, а наоборот, специально проверяем сэмплы и отбрасываем те, посреди которых произошло переключение контекста, как шумовые выбросы.
exchg
> А у тебя какая то версия где тебе гарантируют выполнение на одном ядре?
У моей версии слайс измеряется в миллионах тактов, так что основная масса сэмплов оказывается целиком внутри слайса, и переключения видны как выбросы в выборке.
exchg
> Как вы это делаете?
Зависит от проблемы икс.
У себя в рейтрейсере я просто вывожу число на экран на манер fps.
Если нужно, чтобы статистика прямо собиралась - в идеале ведётся таблица частот, но если идеал не нужен, то можно обойтись классическим мин/макс/авг/стдев.
exchg
> В данном случае с чистым rdsc ты можешь попасть в ситуацию, когда у тебя просто
> случайный набор дельт и весь твой поток это мусор.
Только если размер слайса сравним с размером сэмпла.
Delfigamer
> а наоборот, специально проверяем сэмплы и отбрасываем те, посреди которых
> произошло переключение контекста, как шумовые выбросы.
Все я понял, поэтому спросил как вы находите выбросы в дельтах которые посчитаны между несвязанными/не синхронизированными часами между собой "часами"?
> У моей версии слайс измеряется в миллионах тактов, так что основная масса
> сэмплов оказывается целиком внутри слайса, и переключения видны как выбросы в
> выборке.
Это было бы справедлив только в случае, если начало таймера попадает в начало слайса. А так как это больше случайное совпадение то исходные не верны.
> > В данном случае с чистым rdsc ты можешь попасть в ситуацию, когда у тебя
> > просто
> > случайный набор дельт и весь твой поток это мусор.
> Только если размер слайса сравним с размером сэмпла.
Более правдоподобно - "только если размер слайса больше или равен", но опять же это справедливо если тебе кто-то гарантирует, что таймер старт будет вначале слайса. А так как сэмпл начинается в произвольном месте слайса, то это не выглядит верным утверждением.
exchg
> Более правдоподобно - "только если размер слайса больше или равен"
Нет, именно "сравним".
Если я замеряю стоимость пересечения луча со сценой, и на эту операцию уходит порядка 5000 тактов - то вероятность пересечь границу слайса составляет около 0.001.
> Это было бы справедлив только в случае, если начало таймера попадает в начало
> слайса.
Это не причём. ОС совершенно без разницы, чем занимается твоя программа, если только твоя программа сама не пойдёт к ОС. Следовательно, при отсутствии системных вызовов и пэйдж-фолтов, переключения контекста распределены равномерно по всему протяжению кода. А значит - и смещение таймера внутри слайса так же окажется распределено равномерно. Отсюда, доля запоротых сэмплов - это просто отношение длины сэмпла к длине слайса. В моём случае - «мы измеряем каждую операцию отдельно и собираем какую-никакую статистику, а не закручиваем цикл из 100500 итераций и ищем среднее по курятнику» - это малое число. Следовательно,
> выбросы в дельтах которые посчитаны между несвязанными/не синхронизированными
> часами между собой "часами"
- это неверное утверждение, поскольку подавляющее большинство сэмплов будет всё-таки посчитано без переключения часов.
Delfigamer
Уточню терминологию, на всякий случай.
Слайс - время работы треда меду контекст свитчами.
Сэмпл - некий набор команд ограниченный вызовами timer.start, timer.stop.
timer - rdtsc
> Если я замеряю стоимость пересечения луча со сценой, и на эту операцию уходит
> порядка 5000 тактов - то вероятность пересечь границу слайса составляет около
> 0.001.
А если семпл начался за 1 такт до конца слайса то все семплы пересекут границу слайса с вероятностью 1. Только ты никак не узнаешь когда именно начался сэмпл )))
> Следовательно, при отсутствии системных вызовов и пэйдж-фолтов, переключения
> контекста распределены равномерно по всему протяжению кода.
Да, только старт таймера не находится в начале фрагмента кода с которого "начинается" слайс, а находится где угодно. В обще случае это случайная точка.
> А значит - и смещение таймера внутри слайса так же окажется распределено
> равномерно.
Да, например равномерно за 1 такт до конца слайса. А в ообщем случае в случайном месте.
> Отсюда, доля запоротых сэмплов - это просто отношение длины сэмпла к длине
> слайса.
Нет, т.к. при константном размере слайса и сэмпла доля запоротых может быть 0%, а может быть 100% в зависимости от точки начала семпла. Причем в какую сторону - не узнать никак. Хотя наверное мы можем говорить о том, что вероятность получить запоротые семплы зависит от этого соотношения. Но это никак не меняет смысл - что дешевле правильно использовать таймеры и не городить огород.
> - это неверное утверждение, поскольку подавляющее большинство сэмплов будет
> всё-таки посчитано без переключения часов.
Получается, что не будет. Смотри получается, что даже в рассматриваемом крайнем случае нету никакой гарантии и требуется городить огород непонятно чего, только чтобы не использовать таймеры правильно. Ситуацию усугубляет то, что размер слайса не константен и разнится от системы к системе.
>А если семпл начался за 1 такт до конца слайса то все семплы пересекут границу слайса с вероятностью 1.
Нет, если использовать, как я, релятивистский таймер, основанный на запоминании предыдущего значения TSC и сравнивания с текущим.
Он не даёт "время, прошедшее с t0", он даёт "время, прошедшее с предыдущего вызова", что актуально при профайлинге.
З.Ы. Нашёл статью, где *очень* подробно всё расписано, по версиям виндовс и степеням древности проца. https://docs.microsoft.com/en-us/windows/win32/sysinfo/acquiring-… n-time-stamps
QPC использует TSC на процах, поддерживающих invariant TSC и откатывается на более кондовые механизмы, где её нет.
Можно довериться ей, или можно сделать всё самому и поиметь небольшой профит во времени вызова. Про поддержку invariant TSC можно спросить у CPUID.
exchg
> А если семпл начался за 1 такт до конца слайса то все семплы пересекут границу
> слайса с вероятностью 1.
Что? Нет же.
void Measure::Start() { this->time = ( uint64_t)_rdtsc( ); } void Measure::Stop( ) { uint64_t delta = ( uint64_t)_rdtsc - this->time; this->RecordSample( delta); } bool MeasuredTrace( TraceRequest& tr) { static Measure m; m.Start( ); bool r = Trace( tr); m.Stop( ); return r; } void RenderStep( ) { for ( auto pixel: pixels) { Photon p = EmitPhoton( pixel); while ( MeasuredTrace( p->tr)) { GatherPhoton( pixel, p); if ( !ScatterPhoton( p)) { break; } } } }
Если один сэмпл пересечёт границу - то только этот сэмпл и пересечёт, с чего это вдруг остальные должны как-то от этого поменяться?
exchg
> Тем более я просто уверен что микрософт занесли прибивание треда к ядру внутрь
> QPC.
Это как? Вот допустим происходит вызов QPC, винда сохраняет все регистры в текущем треде, ждет когда освободится нужный тред и читает там таймер? Звучит крайне не очень на мой взгляд. Я бы предположил, что винда вначале вычитывает такты со всех тредов, и знает дельту относительно друг друга. Кроме того для случаев, когда частота меняется - винда использует счетчик деленный на множитель. В этом кстати можно легко убедиться если посмотреть что возвращает QPF. Он вернет не реальные 3Ггц, а значение раз в 20 меньше этого.
Тема в архиве.