主要摘录《结构化并行程序设计》(Structured Parallel Programming) 中关于 TBB(现为oneTBB) 的一些知识和代码,并添加了一些其他东西。
安装
Intel TBB 安装可直接在 github 搜索 tbb,clone 下载后 cmake 安装即可,本文编写时(2021.7.12)tbb 已位于 oneapi 下:oneTBB,安装可参考:Intel TBB库+CMake+Ubuntu配置流程。
Debian/Ubuntu 系列可直接安装
sudo apt install libtbb-dev libtbb-doc libtbb2
oneTBB 中 example 目录里有不少参考代码,整个 oneapi 的参考 demo 可以参见 oneAPI-samples,其中包含使用 GPU+CPU 的 TBB 代码。此外,目标大一统的 oneapi 也支持 FPGA 等,值得关注。
测试代码如下:
#include <iostream>
#include <tbb/tbb.h>
int main() {
tbb::parallel_for(0, 100, 1, [](int i) {
std::cout << i << std::endl;
std::cout << "Hello World!" << std::endl;
});
return 0;
}
节选结果如下,可见乱序输出
Hello World!
28
Hello World!
66
Hello World!
98
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
60
Hello World!
SAXPY
SAXPY 的数学定义为
$$ \bm{y} \leftarrow a\bm{x}+\bm{y} $$
串行版本:
#include <cstdlib>
void saxpy_serial(
size_t n,
float a,
const float x[],
float y[])
{
for (size_t i = 0; i < n; ++i)
y[i] = a * x[i] + y[i];
}
TBB 版本,分块得到的每个子区间 r 由独立任务处理。
#include <cstdlib>
#include <tbb/tbb.h>
void saxpy_tbb(
size_t n,
float a,
const float x[],
float y[])
{
tbb::parallel_for(
tbb::blocked_range<int>(0, n),
[&](tbb::blocked_range<int> r) {
for (size_t i = r.begin(); i != r.end(); ++i)
y[i] = a * x[i] + y[i];
});
}
点积
数学定义:
$$ \bm{a} \cdot \bm{b} = \sum_{i=0}^{n-1}{a_i b_i} $$
串行版本
#include <cstdlib>
float sprod(
size_t n,
const float a[],
const float b[])
{
float res = 0.0f;
for (size_t i = 0; i < n; i++)
{
res += a[i] * b[i];
}
return res;
}
TBB 单精度版本
#include <cstdlib>
#include <functional> // std::plus, std::divides
#include <numeric> // std::inner_product
#include <tbb/tbb.h>
float sprod_tbb(
size_t n,
const float a[],
const float b[])
{
return tbb::parallel_reduce(
tbb::blocked_range<size_t>(0, n),
float(0),
[=](
tbb::blocked_range<size_t> &r,
float in) {
return std::inner_product(a + r.begin(), a + r.end(), b + r.begin(), in);
},
std::plus<float>());
}
TBB 提升到双精度版本
double sprod_tbb2(size_t n, const float a[], const float b[]) {
return tbb::parallel_reduce(
tbb::blocked_range<size_t>(0, n), double(0),
[=](tbb::blocked_range<size_t> &r, double in) {
return std::inner_product(a + r.begin(), a + r.end(), b + r.begin(), in,
std::plus<double>(),
std::multiplies<double>());
},
std::plus<double>());
}
注:来自书中的代码版权满足以下版权声明
Copyright (c) 2012 Michael McCool, Arch Robison, and James Reinders.
All rights reserved.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。