tbb parallel_for 使用教程1
tbb parallel_for 的接口
tbb parallel_for主要用于并发的执行任务,对于tbb的接口函数如下所示:
//! Parallel iteration over a range of integers with a step provided and simple partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& partitioner) {parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner);
}
也就是它就接受的参数,就是迭代器的first和last以及这个步长信息,如果没有给步长信息的话,默认的话会调用下面的接口,也就是步长默认是1.
//! Parallel iteration over a range of integers with a default step value and default partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, const Function& f) {parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, auto_partitioner());
}
而在我们的实际开发中使用tbb::parellel_for的时候其实主要有两种情况。
例子
我想求0-9 10个数的平方,如果我们正常的写法的话,我们直接一个for循环就能搞定了,因为每次计算都比较省时间,但是如果不是求一个数的平方,而是其它复杂的计算逻辑,那么这个计算量可能就比较的大了,而我们如果用for循环,就没有办法充分利用我们多个核心的优势,导致是串行计算。
我们如果想计算每个数据,然后把数据放在一个结构中存储起来,就是涉及到读写的问题,那么如果引入了tbb一定要保证线程的安全,如果线程不安全就没有办法保证并行了。
然后针对两种不同情况给出不同的代码写法:
1.我们并行操作的数据比如vector,数组的长度是固定的,不需要动态的扩容
我么就可以用tbb直接并行了,代码如下:
#include <iostream>
#include <vector>
#include <tbb/parallel_for.h>
#include <tbb/global_control.h>int main() {tbb::global_control gc(tbb::global_control::max_allowed_parallelism, 10);const int N = 10;std::vector<int> numbers(N);for (int i = 0; i < N; ++i) {numbers[i] = i;}// 关键改动:预分配固定大小,每个元素位置独立std::vector<std::pair<int, unsigned long>> results(N); // 直接初始化大小为Ntbb::parallel_for(0, N, 1,[&](int i) {int num = numbers[i];results[i] = {num, num * num}; // 直接通过索引写入,无竞争!});// 打印结果(顺序固定)for (const auto& [num, square] : results) {std::cout << num << "^2 = " << square << std::endl;}return 0;
}
tbb的源码我已经安装到我的机器上了,这个大家如果没有安装,可以自行参考 tbb官网进行安装。
编译代码:
g++ -std=c++17 tbb_parallel_for.cpp -I /opt/voy-sdk/include/ -L /opt/voy-sdk/lib -o test -ltbb
执行代码:
./test
代码的输出结果如下:
0^2 = 0
1^2 = 1
2^2 = 4
3^2 = 9
4^2 = 16
5^2 = 25
6^2 = 36
7^2 = 49
8^2 = 64
9^2 = 81
2.我们并行操作的数据比如vector,数组的长度不是固定的,需要动态扩容,我们不确定大小
这个时候如果想要保证写入的安全性,就需要我们用到tbb提供的安全容器。
#include <iostream>
#include <vector>
#include <tbb/parallel_for.h>
#include <tbb/concurrent_vector.h>
#include <tbb/global_control.h>int main() {tbb::global_control gc(tbb::global_control::max_allowed_parallelism, 10);const int N = 10;std::vector<int> numbers(N);for (int i = 0; i < N; ++i) {numbers[i] = i;}tbb::concurrent_vector<std::pair<int, unsigned long>> results;// 步长=1,每个i对应一个元素tbb::parallel_for(0, N, 1, // 关键改动:步长=1[&](int i) {int num = numbers[i];results.push_back({num, num * num}); // 直接处理单个元素});// 打印结果for (const auto& [num, square] : results) {std::cout << num << "^2 = " << square << std::endl;}return 0;
}