c – 使用TBB进行循环的非常基本
作者:互联网
我是一个非常新的程序员,我对intel的例子有些麻烦.我认为如果能看到tbb中最基本的可能循环是如何实现的话会有所帮助.
for (n=0 ; n < songinfo.frames; ++n) {
sli[n]=songin[n*2];
sri[n]=songin[n*2+1];
}
这是我用来解交错音频数据的循环.这个循环会从tbb中受益吗?你会如何实现它?
解决方法:
首先,对于以下代码,我假设您的数组类型为mytype *,否则代码需要进行一些修改.此外,我假设您的范围不重叠,否则并行化尝试将无法正常工作(至少没有更多的工作)
既然你在tbb中要求它:
首先,您需要在某处初始化库(通常在您的主页中).对于代码假设我在某处使用了一个using namespace tbb.
int main(int argc, char *argv[]){
task_scheduler_init init;
...
}
然后你需要一个函子捕获你的数组并执行forloop的主体:
struct apply_func {
const mytype* songin; //whatever type you are operating on
mytype* sli;
mytype* sri;
apply_func(const mytype* sin, mytype* sl, mytype* sr):songin(sin), sli(sl), sri(sr)
{}
void operator()(const blocked_range<size_t>& range) {
for(size_t n = range.begin(); n !=range.end(); ++n){
sli[n]=songin[n*2];
sri[n]=songin[n*2+1];
}
}
}
现在您可以使用parallel_for来并行化此循环:
size_t grainsize = 1000; //or whatever you decide on (testing required for best performance);
apply_func func(songin, sli, sri);
parallel_for(blocked_range<size_t>(0, songinfo.frames, grainsize), func);
应该这样做(如果我记得没错,有一段时间没有看过tbb,所以可能会有小错误).
如果使用c 11,则可以使用lambda简化代码:
size_t grainsize = 1000; //or whatever you decide on (testing required for best performance);
parallel_for(blocked_range<size_t>(0, songinfo.frames, grainsize),
[&](const blocked_range<size_t>&){
for(size_t n = range.begin(); n !=range.end(); ++n){
sli[n]=songin[n*2];
sri[n]=songin[n*2+1];
}
});
据说tbb并不是我为新程序员推荐的.我真的建议只对并行化的代码进行并行处理,直到你对线程有一个非常牢固的控制.为此,我建议使用openmp,这比使用tbb更安静一点,但仍然足够强大并行化很多东西(取决于编译器支持它).对于你的循环,它将如下所示:
#pragma omp prallel for
for(size_t n = 0; n < songinfo.frames; ++n) {
sli[n]=songin[n*2];
sri[n]=songin[n*2+1];
}
然后你必须告诉你的编译器编译和链接openmp(-fopenmp用于gcc,/ openmp用于visual c).正如你所看到的那样使用起来相当简单(对于这样简单的用例,更复杂的风格是另一回事)然后tbb并且具有不支持openmp或tbb的workonform的额外好处(因为未知的#pragmas)被编译器忽略.我个人在某些项目中使用openmp支持tbb,因为我无法使用它的开源许可证而购买tbb对项目来说有点陡峭.
现在我们已经知道了如何将循环平行化,让我们回答一下它是否值得的问题.这是一个真正无法轻易回答的问题,因为它完全取决于您处理的元素数量以及您的程序预期运行的平台类型.你的问题是带宽很重,所以我不会指望性能的大幅增加.
>如果您只处理1000个元素,则由于开销,并行版本的循环很可能比单线程版本慢.
>如果您的数据不在缓存中(因为它不适合)并且您的系统缺乏带宽,您可能看不到很多好处(尽管您可能会看到一些好处,但如果即使你使用了很多处理器,它的顺序为1.X
>如果您的系统是ccNUMA(可能用于多插槽系统),由于额外的传输成本,无论元素数量多少,您的性能都可能会下降
>编译器可能会错过有关指针别名的优化(因为循环体移动到不同的dunction).使用__restrict(对于gcc,没有vs的线索)可能有助于解决这个问题.
> ……
就个人而言,我认为您最有可能看到性能显着提升的情况是,如果您的系统具有单个多核cpu,则数据集适合L3-Cache(但不适用于单独的L2缓存).对于更大的数据集,您的性能可能会提高,但不会太多(并且正确使用预取可能会获得类似的收益).当然这是纯粹的推测.
标签:c,multithreading,tbb 来源: https://codeday.me/bug/20190826/1731749.html