TBB并行编程
# TBB打开并行编程大门
# 并行与并发
- 并发:轮换执行不同线程的任务,看起来好像同时运行,为的是异步处理多个不同的任务,避免同步造成的阻塞;
- 并行:每个处理器执行一个线程,真正的同时运行,为的是将一个任务分派到多个核上,更快地完成任务。
# 安装与使用
# Ubuntu
sudo apt-get install libtbb-dev
# Arch Linux
sudo pacman -S tbb
# Windows
.\vcpkg install tbb:x64-windows
# 基于TBB任务组的用法
# tbb::task_group
用一个任务组 tbb::task_group
可以启动多个任务,并在主线程中等待任务组内的所有任务完毕。
tbb::task_group tg;
tg.run([&] {
download("hello1.zip");
});
tg.run([&] {
download("hello2.zip");
});
tg.wait();
# tbb::parallel_invoke
上述用法等价于 tbb::parallel_invoke(Fs &&fs...)
tbb::parallel_invoke(
[&] {
download("hello1.zip");
},
[&] {
download("hello2.zip");
});
# 并行for循环
# tbb::parallel_for
size_t n = 1 << 26;
std::vector<double> sin_v(n);
tbb::parallel_for(tbb::blocked_range<size_t>(0, n),
[&](tbb::blocked_range<size_t> r) {
for (size_t i = r.begin(); i < r.end(); ++i)
{
sin_v[i] = std::sin(i);
}
});
如果觉得用法繁琐,可以使用下面的简化版本:【但是简化版无法进行simd优化】
tbb::parallel_for((size_t)0, (size_t)n, [&](size_t i) {
sin_v[i] = std::sin(i);
});
另外,二维区间上的for循环范围:tbb::blocked_range2d(row_begin, row_end, col_begin, col_end)
tbb::parallel_for(tbb::blocked_range2d<size_t>(0, 8, 0, 7),
[&](tbb::blocked_range2d<size_t> r) {
for (size_t i = r.rows().begin(); i < r.rows().end(); ++i) {
for (size_t j = r.cols().begin(); j < r.cols().end(); ++j) {
sin_v[i * 7 + j] = j;
}
}
});
三维区间范围:tbb::blocked_range3d(page_begin/end, row_begin/end, col_begin/end)
:
tbb::parallel_for(tbb::blocked_range3d<size_t>(0,n,0,n,0,n),
[&] (tbb::blocked_range3d<size_t> r) {
for (size_t i = r.pages().begin(); i < r.pages().end(); ++i){
for(size_t j = r.rows().begin(); j < r.rows().end(); ++j){
for(size_t k = r.cols().begin(); k < r.cols().end(); ++k){
sin_v[i*n*n + j*n + k] = 1;
}
}
}
})
还有
blocked_rangeNd
,可自行查阅相关资料了解用法
# tbb::parallel_for_each
该函数是引用传参。
tbb::parallel_for_each(sin_v.begin(), sin_v.end(), [&](double& a) {
a = 1.2;
});
# 并行缩并
tbb::parallel_reduce
或tbb::parallel_deterministic_reduce
均可实现对一组数的缩并操作(诸如累加、累乘等)。前者由于分配的范围动态,由于小数的四舍五入等误差导致每次运算结果不一,但通常性能较好,后者可以保证每次分配的范围一直,因而计算结果一致,但是性能较差。
size_t N = 1 << 26;
float res = tbb::parallel_deterministic_reduce(tbb::blocked_range<size_t>(0, N), (float)0,
[&](tbb::blocked_range<size_t>r, float local_res) {
for (size_t i = r.begin(); i < r.end(); ++i) {
local_res += std::sin(i);
}
return local_res;
}, [](float x, float y) {
return x + y;
});
编辑 (opens new window)
上次更新: 2023/08/26, 00:19:22