но при работе с многопоточными библиотеками даже нужно беспокоиться о распределении потоков по ядрам.Разве это не работа операционной системы?Так в чем же реальная польза от использования TBB вместо Boost?
Вы правы, библиотеке потоков обычно не нужно заботиться о отображении потоков в ядра.И TBB нет.TBB работает с задачами, а не с потоками.Планировщик TBB использует все ядра, выделяя пул потоков и позволяя ему динамически выбирать, какие задачи запускать.Это главное преимущество над Boost, с которым вам нужно будет вручную сопоставлять доступную работу с потоками.Затем TBB предлагает высокоуровневые конструкции, такие как parallel_for, parallel_pipeline и т. Д., Которые можно использовать для выражения наиболее распространенных параллельных шаблонов и скрытия всех манипуляций с задачами.
Например, давайте возьмем кусок кода, которыйвычисляет точки фрактала Мандельброта (взято из http://warp.povusers.org/Mandelbrot/, инициализация переменной опущена):
for(unsigned y=0; y<ImageHeight; ++y)
{
double c_im = MaxIm - y*Im_factor;
for(unsigned x=0; x<ImageWidth; ++x)
{
double c_re = MinRe + x*Re_factor;
double Z_re = c_re, Z_im = c_im;
bool isInside = true;
for(unsigned n=0; n<MaxIterations; ++n)
{
double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
if(Z_re2 + Z_im2 > 4)
{
isInside = false;
break;
}
Z_im = 2*Z_re*Z_im + c_im;
Z_re = Z_re2 - Z_im2 + c_re;
}
if(isInside) { putpixel(x, y); }
}
}
Теперь, чтобы сделать его параллельным TBB, все, что вам нужно, - преобразовать самый внешний цикл в tbb ::rallel_for.(Для краткости я использую лямбду C ++ 11):
tbb::parallel_for(0, ImageHeight, [=](unsigned y)
{
// the rest of code is exactly the same
double c_im = MaxIm - y*Im_factor;
for(unsigned x=0; x<ImageWidth; ++x)
{
...
// if putpixel() is not thread safe, a lock might be needed
if(isInside) { putpixel(x, y); }
}
});
TBB автоматически распределяет все итерации цикла по доступным ядрам (и сколько их не беспокоит) и динамически балансирует нагрузку, так что еслиу некоторых потоков есть больше работы, другие потоки не просто ждут этого, но помогают, максимально используя процессор.Попробуйте реализовать его с помощью необработанных потоков, и вы почувствуете разницу:)