使用TBB的非常基本的for循环
Very Basic for loop using TBB
我是一个非常新的程序员,我有一些麻烦从英特尔的例子。如果我能看到最基本的循环是如何在tbb中实现的,我想这将是有帮助的。
for (n=0 ; n < songinfo.frames; ++n) {
sli[n]=songin[n*2];
sri[n]=songin[n*2+1];
}
这是一个循环,我正在使用去交错音频数据。这个循环会受益于它吗?你将如何实现它?
首先,对于以下代码,我假设您的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);
应该可以了(如果我没记错的话,我有一段时间没看了,所以可能会有一些小错误)。如果使用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];
}
});
话虽如此,这并不是我推荐给新程序员的东西。我真的建议只并行化那些在你非常牢固地掌握线程之前不需要并行化的代码。对于这一点,我建议使用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的平台上工作的额外好处(因为未知的#pragmas
被编译器忽略)。就我个人而言,我在一些项目中使用openmp而不是tbb,因为我不能使用它的开源许可证,而且购买tbb对项目来说有点贵。
现在我们已经知道了如何并行化循环,让我们来看看是否值得这样做。这是一个很难回答的问题,因为这完全取决于你要处理多少元素,以及你的程序要运行在什么样的平台上。你的问题是带宽非常大,所以我不指望性能有很大的提高。
- 如果您只处理
1000
元素,则由于开销的原因,并行版本的循环很可能比单线程版本慢。 - 如果你的数据不在缓存中(因为它不适合),并且你的系统非常缺乏带宽,你可能看不到太多的好处(尽管很可能你会看到一些好处,只是不要惊讶,如果它在
1.X
的顺序,即使你使用了很多处理器) - 如果您的系统是ccNUMA(可能用于多套接字系统),由于额外的传输成本,无论元素的数量如何,性能都可能下降 编译器可能会错过关于指针混叠的优化(因为循环体被移动到不同的函数中)。使用
- …
__restrict
(gcc, vs没有线索)可能有助于解决这个问题。我个人认为,你最有可能看到显著的性能提高的情况是,如果你的系统有一个单一的多核cpu,数据集适合L3-Cache(但不是单独的L2缓存)。对于更大的数据集,性能可能会提高,但不会提高太多(正确使用预取可能会获得类似的收益)。当然这是纯粹的推测。
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么我的for循环不能正确获取argv
- 在基于范围的for循环中使用结构化绑定声明
- 通过for循环使用用户输入填充列表
- 使用for循环检查数组中的重复项
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 正在使用for循环创建QScatterSerie
- Python中的for循环与C++有何不同
- 在更改for循环的第三部分后,未使用for循环结果
- 在 for 循环中查找问题时遇到困难
- 嵌套for循环C++的问题(初学者)
- 如何用for循环在c++中生成单词三角形
- 如何在for循环中包含两个索引值的测试条件
- 带有多个独立参数的C++For循环
- 为什么我的程序在for循环中k=0时返回垃圾值
- 如何通过替换顺序代码的while循环来添加OpenMP for循环
- C++-For循环未执行
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- C++ 无法在字符数组中使用 for 循环打印字母模式