Я работаю на стандартном шестиядерном SMP-компьютере с архитектурой x86, тактовой частотой 3,6 ГГц, в обычном коде C.
У меня есть многопоточная схема «производитель / потребитель», в которой мой поток «производителя» читает файлсо скоростью примерно 1 000 000 строк в секунду и передачей данных, которые они считывают, двум или четырем «потребительским» потокам, которые выполняют над ним небольшую работу, а затем помещают их в базу данных. Пока они потребляют, он занят чтением следующей строки.
Таким образом, и у производителя, и у потребителя должны быть какие-то средства синхронизации, которые работают на частоте ниже микросекунды, для которой я использую цикл "ожидания ожидания при вращении",потому что все обычные механизмы синхронизации, которые я могу найти, слишком медленные. В терминах псевдокода:
Поток производителя
While(something in file)
{
read a line
populate 1/2 of data double buffer
wait for consumers to idle
set some key data
set memory fence
swap buffers
}
И потоки потребителя также
while(not told to die)
{
wait for key data change event
consume data
}
С обеих сторон закодирован цикл ожидания:
while(waiting)
{
_mm_pause(); /* Intel say this is a good hint to processor that this is a spin wait */
if(#iterations > 1000) yield_thread(); /* Sleep(0) on Windows, pthread_yield() on Linux */
}
Это все работает, и я получаю довольно неплохие ускорения по сравнению с эквивалентным последовательным кодом, но мой профилировщик (Intel VTune Amplifier) показывает, что я трачу ужасное количество времени в своих занятых циклах ожидания,и отношение «спина» к «полезной работе» удручающе велико. Учитывая то, как профилировщик концентрирует свою обратную связь на самых загруженных разделах, это также означает, что строки кода, выполняющие полезную работу, как правило, не сообщаются, поскольку (условно говоря) их% общего возраста процессора снижается на уровне шума ... илипо крайней мере, так говорит профилировщик. Должно быть, они делают что-то в противном случае я бы не увидел ускорения!
Я могу и делаю время, но трудно различить задержки, вызванные задержкой диска в потоке производителяи задержки, затрачиваемые на синхронизацию потоков.
Так есть ли лучший способ измерить то, что на самом деле происходит? Под этим я подразумеваю, сколько времени эти потоки действительно тратят на ожидание друг друга? Точное измерение времени очень трудно при разрешении менее микросекунды, мне кажется, что профилировщик мне не очень помогает, и я изо всех сил пытаюсь оптимизировать схему.
Или, может быть, моя схема ожидания при вращении - мусор, но яне могу найти лучшего решения для субмикросекундной синхронизации.
Любые подсказки будут действительно приветствоваться: -)