Подтвердить что ты не робот

Как измерить многопоточное время процесса в многозадачной среде?

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

Обычно измеряются два вида времени:

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

Я считаю, что мне нужно время от времени отдельных потоков, которое может отличаться от максимального времени процессора, используемого любым потоком из-за структуры зависимостей задачи между потоками. Например, в процессе с двумя потоками поток 1 загружается в первую две трети времени выполнения (для времени процессора t), тогда как поток 2 загружается в более поздние две трети времени выполнения процесса (опять же, для времени процессора t). В этом случае:

  • время настенного времени вернет время переключения 3t/2 + + время, используемое другими процессами между ними,
  • Максимальное время процессора всех потоков будет возвращать значение, близкое к t, и
  • общее время процессора близко к 2t.
  • То, что я надеюсь получить в качестве результата измерения, - это makepan, т.е. 3t/2.

Кроме того, многопоточность приносит неопределенность сама по себе. Вероятно, эту проблему можно позаботиться о проведении теста несколько раз и суммировании результатов.

Кроме того, задержка также зависит от того, как ОС планирует потоки; все становится сложнее, если некоторые потоки процесса ждут процессора, а другие работают. Но не забывайте об этом.

Существует ли эффективный способ вычисления/приближения этого времени? Для предоставления примеров кода используйте любой язык программирования, но предпочтительно C или С++ для Linux.

PS: Я понимаю, что это определение makepan отличается от того, что используется в задачах планирования. Определение, используемое в задачах планирования, аналогично времени настенных часов.

4b9b3361

Ответ 1

Реформирование вопроса

Я написал многопоточное приложение, которое занимает X секунд для выполнения на моей машине K-core.

Как оценить, сколько времени потребуется программе для работы на одноядерном компьютере?

Эмпирически

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

... О, подождите, ваш компьютер уже имеет одно ядро ​​(у него также есть другие, но нам не нужно будет их использовать).

Как это сделать, будет зависеть от операционной системы, но один из первых результатов, которые я нашел в Google, объясняет несколько подходов для Windows XP и Vista.

http://masolution.blogspot.com/2008/01/how-to-use-only-one-core-of-multi-core.html

После этого вы могли:

  • Присвойте свой процесс приложения единому ядру. (вы также можете сделать это в своем коде).
  • Начните свою операционную систему только зная об одном из ваших ядер. (а затем переключиться обратно)

Независимый Parallelism

Оценка этого аналитически требует знания вашей программы, метода parallelism и т.д.

В качестве простого примера предположим, что я пишу многопоточную программу, которая вычисляет десятимиллиардную десятичную цифру pi и десятимиллиардную десятичную цифру e.

Мой код выглядит так:

public static int main()
{
    Task t1 = new Task( calculatePiDigit );
    Task t2 = new Task( calculateEDigit );
    t1.Start();
    t2.Start();
    Task.waitall( t1, t2 );
}

И так бывает, когда граф выглядит так:

enter image description here

Очевидно, что они независимы.

В этом случае

  • Вычисляет времяPayDigit() самостоятельно.
  • Вычисляет время calcEDigit().
  • Добавьте время вместе.

2-этапный трубопровод

Когда задачи не являются независимыми, вы не сможете просто добавить отдельные моменты вместе.

В следующем примере я создаю многопоточное приложение: сделайте 10 изображений, преобразуйте их в оттенки серого, а затем запустите алгоритм определения линии. По какой-то внешней причине каждое изображение не может быть обработано не в порядке. Из-за этого я создаю шаблон конвейера.

Мой код выглядит примерно так:

ConcurrentQueue<Image> originalImages = new ConcurrentQueue<Image>();
ConcurrentQueue<Image> grayscaledImages = new ConcurrentQueue<Image>();
ConcurrentQueue<Image> completedImages = new ConcurrentQueue<Image>();

public static int main()
{
     PipeLineStage p1 = new PipeLineStage(originalImages, grayScale, grayscaledImages);
     PipeLineStage p2 = new PipeLineStage(grayscaledImages, lineDetect, completedImages);

     p1.Start();
     p2.Start();

     originalImages.add( image1 );
     originalImages.add( image2 );
     //... 
     originalImages.add( image10 );

     originalImages.add( CancellationToken );

     Task.WaitAll( p1, p2 );
}

Выполняется центрирование данных перед графиком:

enter image description here

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

В любом случае, мы знаем, что GrayScale() будет вызван 10 раз, а LineDetection() будет вызван 10 раз, поэтому мы можем просто провести время каждый раз, а затем умножить их на 10.

Но как насчет затрат на толкание/выскакивание/опрос ConcurrentQueues?

Предполагая, что изображения большие, это время будет незначительным.

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

Затраты контекстного переключения?

Взгляните на этот вопрос:

Как оценить затраты на переключение контекста потока?

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

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

Опасность состоит в том, что кеш полностью прерывается между коммутаторами контекста.

Например, в идеале:

  • image1 загружается в кеш в результате выполнения GrayScale
  • LineDetection будет работать намного быстрее на image1, так как он находится в кеше

Однако это может произойти:

  • image1 загружается в кеш в результате выполнения GrayScale
  • image2 загружается в кеш в результате выполнения GrayScale
  • Теперь этап 2 трубопровода запускает LineDetection на image1, но image1 больше не находится в кеше.

Заключение

Ничто не сравнится с временем в той же среде, в которой он будет запущен.

Лучше всего симулировать эту среду, а также вы можете.

Независимо от того, что понимание дизайна вашей программы должно дать вам представление о том, чего ожидать в новой среде.