我是一名非常新的程序员,我在使用intel的例子时遇到了一些麻烦。我认为如果能看到tbb中最基本的可能循环是如何实现的话会有所帮助。
for (n=0 ; n < songinfo.frames; ++n) {
sli[n]=songin[n*2];
sri[n]=songin[n*2+1];
}
这是我用来解交错音频数据的循环。这个循环会从tbb中受益吗?你会如何实现它?
答案 0 :(得分:6)
首先,对于以下代码,我假设您的arrays
属于mytype*
类型,否则代码需要进行一些修改。此外,我假设您的范围不重叠,否则并行化尝试将无法正常工作(至少没有更多的工作)
因为你在tbb中提出要求:
首先,您需要在某处初始化库(通常在main
中)。对于代码假设我在某处放置了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的额外好处(因为未知{{ 1}}被编译器忽略。我个人在某些项目中使用openmp支持tbb,因为我无法使用它的开源许可证而购买tbb对项目来说有点陡峭。
现在我们已经知道了如何将循环平行化,让我们回答这个问题是否值得。这是一个真正无法轻易回答的问题,因为它完全取决于您处理的元素数量以及您的程序预期运行的平台类型。你的问题带宽非常大,所以我不会指望性能提升很多。
#pragmas
元素,则由于开销,循环的并行版本很可能比单线程版本慢。 1000
,即使你使用了很多处理器,也会受到侮辱。1.X
(对于gcc,对于vs没有任何线索)可能有助于解决这个问题。就我个人而言,我认为您最有可能看到显着性能提升的情况是,您的系统是否具有单个多核cpu,数据集适合于L3-Cache(但不适用于单独的L2缓存)。对于更大的数据集,您的性能可能会提高,但不会太多(并且正确使用预取可能会获得类似的收益)。当然这是纯粹的推测。