Cheb
> "как-то" - конкретно, через анус
Ты я смотрю на lkml завсегдатай. Если ты не пишешь драйверы, то нехер пользоваться ассемблером. Доверься тем людям, которые разбираются в портировании.
>Доверься тем людям, которые разбираются в портировании.
При чём здесь портирование? QPC - виндовое апи сомнительной эффективности но повышенной поддерживаемости. Кому-то его по ноздри хватит, кому-то... Может, я занимаюсь таким извращением, как оборачивание измерениями времени каждой попытки входа в каждую критическую секцию? (спойлер: я занимаюсь).
Windows ARM - интересный вопрос. Free Pascal поддерживает только Windows CE, преданье старины глубокой, а Windows 10 ARM поддерживает мега-костыль с перекомпиляцией x86 приложений на лету - и это одна из причин иметь fallback на QPC: у меня смутное подозрение, что RDTSC там вежливо упадёт.
Пока инструменты разработчика не догнали Windows 10 on ARM (а какой у этого процент рынка?) - эта платформа остаётся экзотической разновидностью x86.
А разве для QPC и RDTSC не нужно переключать ThreadAffinityMask?
exchg
Это просто аппаратный счетчик тактов. Ему ничего не нужно.
eDmk
> Это просто аппаратный счетчик тактов. Ему ничего не нужно.
Я могу уже что-то забыть, но насколько я помню при каждом обращении ты читаешь счетчик ядра на котором сейчас крутится поток. А показания этих счетчиков для каждого ядра могут различаться. А ядро на котором прямо вот сейчас проснется поток выбирает ОС. Поэтому чтобы твой таймер показывал то, что ты хочешь, а не случайные значения, нужно явно попросить ОС привязывать поток (хотя бы на момент чтения счетчика) к одному и тому же ядру.
UPD: Ну или использовать rdtscp с развязкой, он указывает номер ядра с которого считывали значение.
exchg
Вот что интел говорит про TSC:
17.14.3 Time-Stamp Counter Adjustment
Software can modify the value of the time-stamp counter (TSC) of a logical processor by using the WRMSR instruction to write to the IA32_TIME_STAMP_COUNTER MSR (address 10H). Because such a write applies only to that logical processor, software seeking to synchronize the TSC values of multiple logical processors must perform these writes on each logical processor. It may be difficult for software to do this in a way than ensures that all logical processors will have the same value for the TSC at a given point in time.
The synchronization of TSC adjustment can be simplified by using the 64-bit IA32_TSC_ADJUST MSR (address 3BH). Like the IA32_TIME_STAMP_COUNTER MSR, the IA32_TSC_ADJUST MSR is maintained separately for each logical processor. A logical processor maintains and uses the IA32_TSC_ADJUST MSR as follows:
• On RESET, the value of the IA32_TSC_ADJUST MSR is 0.
• If an execution of WRMSR to the IA32_TIME_STAMP_COUNTER MSR adds (or subtracts) value X from the TSC, the logical processor also adds (or subtracts) value X from the IA32_TSC_ADJUST MSR.
• If an execution of WRMSR to the IA32_TSC_ADJUST MSR adds (or subtracts) value X from that MSR, the logical processor also adds (or subtracts) value X from the TSC.
Unlike the TSC, the value of the IA32_TSC_ADJUST MSR changes only in response to WRMSR (either to the MSR itself, or to the IA32_TIME_STAMP_COUNTER MSR). Its value does not otherwise change as time elapses. Software seeking to adjust the TSC can do so by using WRMSR to write the same value to the IA32_TSC_ADJUST MSR on each logical processor.
eDmk
> Вот что интел говорит про TSC:
Там кто-то гарантирует, что счетчики будут синхронизированы в момент запуска твоего кода из статьи?
exchg
я никакого отношения к комментариям не имею.
Из своего опыта работы с многопоточностью могу сказать, что мне хватало 1-го таймера из главного потока. Нужды в синхронизации не возникало. В Delphi в классе TThread синхронизация производится. На каждый поток свой счетчик. Как в С++ - не знаю.
eDmk
Ты понимаешь о чем я говорил? Потому что если да, то я могу ожидать ответ типа - в современных условиях/железе эта проблема отсутствует или что-то типа того. Но не то что ты говоришь. Поэтому еще раз ниже поясню.
> Из своего опыта работы с многопоточностью могу сказать, что мне хватало 1-го
> таймера из главного потока
Твой главный (и даже единственный поток) по воле ОС меняет ядро процессора на котором он выполняется. Т.е. таймер мог стартануть на 1 ядре, а завершится на 2. Эти два ядра могут быть не синхронизированы и в результате
ты получишь диф между несвязанными значениями. Это происходит независимо от количества потоков в процессе и языка программирования.
> В Delphi в классе TThread синхронизация производится. На каждый поток свой
> счетчик.
Это не о том. Вот щас перепроверил на вики, не путаю ли я чего:
Счётчики TSC в редких случаях могут быть несинхронизированы в некоторых многоядерных или многопроцессорных системах, в частности:
*При инициализации процессоров. Возможна рассинхронизация счётчиков в ранних многоядерных системах из-за неверной инициализации процессоров некоторыми BIOS. Исправляется обновлением BIOS или обновлением операционной системы. Существуют программы для проверки на наличие этой ошибки.[9]
*Операционная система может переключать поток между разными ядрами, имеющими не синхронизированные счётчики. На прикладном уровне можно отследить факт смены ядра на многоядерных системах при помощи инструкции rdtscp, которая, работая аналогично rdtsc, дополнительно возвращает в регистре ECX номер процессорного ядра.
*Для решения многих проблем рекомендуется фиксирование потока на конкретном процессоре (cpu affinity) и отключение технологий автоматического изменения частоты (технологий энергосбережения и динамического изменения производительности).
exchg
> А разве для QPC и RDTSC не нужно переключать ThreadAffinityMask?
QPC - это посути RDTSC, который задизайнен так, чтобы как раз не делать ThreadAffinityMask.
exchg
Я считаю, что вы достаточно умный, чтобы решить свою проблему.
MrShoor
> QPC - это посути RDTSC, который задизайнен так, чтобы как раз не делать
> ThreadAffinityMask
Уже походу да, пишут в доках вот такое:
Does QPC reliably work on multi-processor systems, multi-core system, and systems with hyper-threading?
*Yes
В районе 2013+- года на msdn было вот так:
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the SetThreadAffinityMask function.
exchg
> А разве для QPC и RDTSC не нужно переключать ThreadAffinityMask?
Проще же просто выкидывать выбросы в дельтах. Если только нас не интересует, сколько времени тратит ОС на переключение контекстов.
Delfigamer
> Проще же просто выкидывать выбросы в дельтах.
Да, только дельта должна быть от одного и того же счетчика.
exchg
> Да, только дельта должна быть от одного и того же счетчика.
Так в том и суть, что дельты от разных - будут среди выбросов и потому отрежутся.
Тема в архиве.