Накладные расходы на параллелизм
Ваша модель затрат неверна.
Идеальное время параллельных вычислений:
Tpar(ideal) = N * t / C + Pstart + Pend
где Pstart
- это время, необходимое для начала параллелизма, а Pend
- время, необходимое для его завершения. Для Pstart
нет ничего необычного в том, что оно составляет порядка десятков миллисекунд.
Я не уверен, знаком ли вы с OpenMP (хотя это полезно знать), но для наших целей это модель потоков, которая разделяет работу между группой потоков. На следующей диаграмме показаны накладные расходы некоторых команд в зависимости от размера группы потоков:
Вывод состоит в том, что запуск вашего параллелизма (строка parallel for
) потенциально дорогостоящий и растет с увеличением количества потоков. Прекращение параллелизма (строка barrier
) имеет аналогичные затраты.
Фактически, если вы посмотрите учебник TBB, Раздел 3.2.2 («Автоматическое разбиение на части») говорит:
ВНИМАНИЕ: Обычно цикл должен занять не менее миллиона тактов для parallel_for, чтобы повысить его производительность. Например, цикл, который занимает не менее 500 микросекунд на процессоре с частотой 2 ГГц, может выиграть от parallel_for.
Повышение скорости
Лучший способ ускорить такой код - выполнять операции параллельно, только если их много, и / или настраивать количество потоков, выполняющих работу, так, чтобы у каждого потока было много дел. В TBB вы можете добиться аналогичного поведения, например:
#include <tbb/parallel_for.h>
// . . .
if(work_size>1000)
tbb::serial::parallel_for( . . . );
else
tbb::parallel_for( . . . );
// . . .
где вы хотели бы установить 1000
на достаточно высокое число, чтобы вы начали замечать выгоды от параллелизма.
Вы также можете уменьшить количество потоков, так как это несколько снижает накладные расходы:
tbb::task_scheduler_init init(nthread);
TBB также выполняет динамическую балансировку нагрузки (см. здесь). Это замечательно, если вы ожидаете, что ваши итерации / задачи цикла будут иметь широкое распределение времени выполнения, но представляют собой ненужные накладные расходы, если ожидаемое время выполнения одинаково. Я не уверен, есть ли у TBB статическое планирование, но, возможно, стоит изучить его.
Если люди останутся здесь без твердой приверженности TBB, в OpenMP вы должны сделать что-то вроде:
#pragma omp parallel for if(work_size>1000) num_threads(4) schedule(static)
person
Richard
schedule
03.01.2018