C ++ intel TBB оптимизация внутреннего цикла - PullRequest
0 голосов
/ 15 февраля 2012

Я пытаюсь использовать Intel TBB для распараллеливания внутреннего цикла (2-й из 3-х), однако, я получаю достойную отдачу только тогда, когда внутренние 2 цикла имеют значительный размер.

Является ли TBB порождающим новые потокидля каждой итерации основного цикла?Есть ли способ уменьшить накладные расходы?

tbb::task_scheduler_init tbb_init(4); //I have 4 cores
tbb::blocked_range<size_t> blk_rng(0, crs_.y_sz, crs_.y_sz/4);
boost::chrono::system_clock::time_point start   =boost::chrono::system_clock::now();
for(unsigned i=0; i!=5000; ++i)
{   
    tbb::parallel_for(blk_rng, 
    [&](const tbb::blocked_range<size_t>& br)->void
    {   
    :::

Интересно отметить, что у openMP (который я пытаюсь удалить !!!) такой проблемы нет.

IЯ собираю с:

intel ICC 12.1 в -03 -xHost -mavx

На Intel 2500k (4 ядра)

РЕДАКТИРОВАТЬ: я действительно могу изменить порядок цикловпотому что тест выходных циклов необходимо заменить на предикат, основанный на результате циклов.

1 Ответ

1 голос
/ 16 февраля 2012

Нет, TBB не порождает новые темы для каждого вызова parallel_for. На самом деле, в отличие от параллельных областей OpenMP, каждая из которых может создавать новую группу потоков, TBB работает с одной и той же группой потоков, пока все объекты task_scheduler_init не будут уничтожены; и в случае неявной инициализации (с пропуском task_scheduler_init) одни и те же рабочие потоки используются до конца программы.

Таким образом, проблема с производительностью вызвана чем-то другим. Исходя из моего опыта, наиболее вероятные причины:

  • отсутствие оптимизации компилятора, в первую очередь автоматическая векторизация (можно проверить, сравнив однопотоковую производительность OpenMP и TBB; если TBB намного медленнее, то это наиболее вероятная причина).
  • отсутствует кеш; если вы 5000 раз просматриваете одни и те же данные, локальность кэша имеет огромное значение, и по умолчанию OpenMP schedule(static) работает очень хорошо, детерминистически повторяя одно и то же разбиение каждый раз, в то время как планировщик кражи работы TBB имеет значительную случайность. Установка размера зерна block_range равным problem_size / num_threads обеспечивает один кусок работы на поток, но не гарантирует одинаковое распределение частей; и affinity_partitioner должен помочь с этим.
...