LINUX.ORG.RU

как соотносится pthread_clockgettime(thread) и rdtsc?

 ,


0

1

я чиню диспетчер задач в ЯОС. В ЯОС есть процедура для замера времени выполнения треда. В юникс-версии она была сломана и вызывала, по сути, rdtsc,

проц -ДайКвоТактовПроцессораСМоментаПерезапуска* (): цел64;
машКод
  XOR RAX, RAX
  RDTSC  ; set EDX:EAX
  SHL RDX, 32
  OR RAX, RDX
кон ДайКвоТактовПроцессораСМоментаПерезапуска;

Поэтому в местном диспетчере задач у всех тредов было одинаковое CPU. Я поправил процедуру, которая лежит в основе замера, и теперь она выглядит так:

	проц GetCpuCycles*( process : Process; перем cpuCycles: CpuCyclesArray; all: булево );
	перем temp : цел64;
	перем t: Unix.Timespec;
	перем кодЧасов: Unix.ClockId_t;
	перем успехТочногоЗамера: булево;

	нач
		утв(process # НУЛЬ);
		если Unix.pthread_getcpuclockid(process.threadId, адресВПамяти из кодЧасов) = 0 то
			если Unix.clock_gettime(кодЧасов, адресВПамяти из t) = 0 то
				(* Вот здесь что надо сделать??? *)
				cpuCycles[0] := цел64(t.tv_sec)*1000000000 + цел64(t.tv_nsec);
				успехТочногоЗамера := истина всё всё;
		если ~успехТочногоЗамера то
			cpuCycles[0] := ЭВМ.ДайКвоТактовПроцессораСМоментаПерезапуска() всё;

		если ~all то
			temp := process.lastThreadTimes;
			process.lastThreadTimes := cpuCycles[0];
			cpuCycles[0] := cpuCycles[0] - temp;
		всё;
	кон GetCpuCycles;

Т.е. я пытаюсь воспользоваться clock_gettime, и если у меня всё получается, то считаю, что 1 цикл = 1 наносекунда. Если не получается, то использую старое решение. В результате всё вызвалось нормально и я увидел, какие треды работают, а какие спят. Но единицы измерения вряд ли правильные. Как пересчитать, чтобы было похоже на те циклы, которые считает rdtsc?

Иными словами, как узнать частоту, с которой тикают часы, показания которых возвращает rdtsc?

★★★★★

Последнее исправление: den73 (всего исправлений: 2)

как узнать частоту, с которой тикают часы, показания которых возвращает rdtsc?

Это называется частота процессора. Раньше она была написана на чипе, сейчас из-за всяких динамических энергосбережений она постоянно меняется (если их не отключить). Если не меняется то её можно измерить в начале работы и использовать полученное значение.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Я вроде почитал про частоту rdtsc - и вроде (не точно) это некая фиксированная частота, условно говоря, рекламная. Она якобы не плавает. А что, кроме замера никак что ли?

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Нет, это именно счётчик реальных тактов ядра процессора (у каждого ядра - свой). Даже когда она не плавала, у проца с номинальной 3ГГц там могло быть что-то типа 2999956245 или 3000123456 в секунду + всё равно немного плавает из-за температурных колебаний и прочих факторов.

Если хочешь считать такты на поток - надо вызывать rdtsc в моменты переключения потоков таймером и инкрементировать соответствующий счётчик в описании потока. Делаться это может только драйвером вытесняющей многозадачности ядра ОС.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

У меня сейчас «ОС внутри ОС». Я, наверное, могу отловить моменты, когда ЯОС внутри себя переключает задачи, но я вряд ли смогу отловить моменты, когда линукс отбирает ядра у ЯОС. Во всяком случае, мне лень в этом разбираться.

Я посмотрел, данная процедура GetCpuCycles используется только в диспетчере задач и разного рода профайлерах. Поэтому даже если замер времени идёт долго, то на жизнеспособность ЯОСа в целом это не должно повлиять, и сверхточность тут не нужна.

Мне просто надо, чтобы единица измерения была та же, т.е. чтобы оно меряла не «колво циклов * 100000» и не «колво циклов / 100000», а то же самое по порядку величины.

Так-то если я заменил гигагерцы на наносекунды, то вроде получается коэффициент порядка 0.5 или 2.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от den73

Гигагерцы это частота, а наносекунды это время.

то на жизнеспособность ЯОСа в целом это не должно повлиять

Это точно. Просто возвращай везде 0, тоже не повлияет.

Но если тебе нужно количество тактов процессора в единственном его полезном хоть для чего-то виде - то надо отлавливать все переключения задач. Если тебе нужно потраченное время то бери thread time и не парься по поводу порядка величин, он тут всё равно смысла не имеет. Только не надо называть это «cpu cycles», а то вдруг кто-то таки вздумает это всё использовать и окажется обманутым. Cpu cycles меряется только rdtsc + хуки на приём/отдачу ядра у потока и никак иначе.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

Да, наверное, название будет не очень. Плохо то, что во всех вариантах, кроме линукса, кво тактов процессора для треда получить можно. В Windows-версии есть QueryThreadCycleTime, в режиме настоящей ОС на железе делается при переключении rdtsc и хранится в объекте процесса последнее значение. И только линукс оказывается исключением, когда получить именно кво циклов нельзя. Поэтому неясно, как назвать. Видимо всё же буду замерять коэффициент пересчёта. Всё равно, как я понял, rdtsc неточен вплоть до обращения времени вспять.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от firkax

Нет, это именно счётчик реальных тактов ядра процессора (у каждого ядра - свой). Даже когда она не плавала, у проца с номинальной 3ГГц там могло быть что-то типа 2999956245 или 3000123456 в секунду + всё равно немного плавает из-за температурных колебаний и прочих факторов.

В Википедии другое пишут:

В современных процессорах Intel (Nehalem и более новых) и AMD (предположительно, начиная с K10 Barcelona/Phenom) счётчик TSC не зависит от использования технологий энергосбережения и увеличивается с постоянной частотой вне зависимости от того, на какой частоте работает процессор, и работал ли он или находился в состоянии сна. Такой счётчик называется инвариантным (invariant TSC).

den73 ★★★★★
() автор топика
Ответ на: комментарий от den73

Всё равно, как я понял, rdtsc неточен вплоть до обращения времени вспять.

Нет, rdtsc как раз максимально точен. Просто не надо от него ожидать того, чем он не является. А именно, это не часы, а счётчик тактов процессорного ядра. На разных ядрах значения могут отличаться, потому что на них прошло разное количество тактов, и это не «неточность».

invariant TSC

Посмотрел - там как-то всё сложно первый взгляд. Походу главную суть этого счётчика испортили и теперь с помощью него нельзя считать расход тактов на процессорные инструкции. Однако это всё так же не часы. Частота внешнего тактового генератора всё равно плавает, вместе с ней плавает и частота этого счётчика.

Видимо всё же буду замерять коэффициент пересчёта

Зачем тебе какие-то пересчёты? Что ты хочешь то? Повторю - если тебе нужен таймер то бери таймер и не пытайся из него изображать что-то другое. Если нужен счётчик тактов то никакие пересчёты не помогут, от такого фейка больше вреда чем пользы будет.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Ну как, в ЯОС как бы слой совместимости и абстракции. До сих пор единицы измерения были одинаковы во всех системах, а теперь расщепление. Это меня печалит, т.к. абстракция начинает потдекать.

Практические следствия, видимо, будут в том, что CPU треда в диспетчере задач будет показываться 50%, а оно на самом деле 25% или 100%, даже в ситуации, когда TSC считает реальные циклы процессора. Поэтому и хочется пересчитать, чтобы было единообразно.

Но ладно, в целом задача решена, всем спасибо.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)

Иными словами, как узнать частоту, с которой тикают часы, показания которых возвращает rdtsc?

https://stackoverflow.com/questions/35123379/getting-tsc-rate-from-x86-kernel

Качественный ответ с перечислением множества способов. Я для себя остановился на использовании подхода как в DPDK (последний вариант в ответе)

blex ★★★
()

Главное убедись что разогрев кэша не меряешь и погоду на Марсе :) когда самописные бенчмарки пишут, это распространенные грабли

https://www.ccsl.carleton.ca/~jamuir/rdtscpm1.pdf

http://faculty.cs.niu.edu/~winans/notes/patmc.pdf

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 2)
Ответ на: комментарий от slackwarrior

Спасибо, но я в данном случае ничего не меряю. У меня была одна задача - чтобы в диспетчере процессов было более-менее осмысленное число, а не во всех процессах одинаковое. Для этого нужно было хотя бы относительное, но потребление процессоров тредом. Это уже сделано. Теперь хочу, чтобы единицы измерения были более-менее платформонезависимые. А что там будут дальше этими часами мерять - мне на данный момент неважно.

den73 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.