Sirius' blog Sirius' blog
首页
  • 学习笔记

    • 《C++》
    • 《MATLAB》
    • 《Python》
  • 学习笔记

    • 《Git》
    • 《CMake》
  • 技术文档
  • 博客搭建
  • 学习
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Sirius0v0

怕什么真理无穷,进一寸有一寸的欢喜
首页
  • 学习笔记

    • 《C++》
    • 《MATLAB》
    • 《Python》
  • 学习笔记

    • 《Git》
    • 《CMake》
  • 技术文档
  • 博客搭建
  • 学习
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础

  • Cpp小记
  • C++学习笔记-220705-V1
  • 进阶

  • 奇思妙用

  • 库的使用

    • googletest配置方法及使用
    • TBB并行编程
      • 并行与并发
      • 安装与使用
      • 基于TBB任务组的用法
        • tbb::task_group
        • tbb::parallel_invoke
      • 并行for循环
        • tbb::parallel_for
        • tbb::parallel_for_each
      • 并行缩并
    • ipopt优化库配置及使用
  • 《C++》学习笔记
  • 库的使用
Sirius0v0
2023-08-20
目录

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)
#Cpp
上次更新: 2023/08/26, 00:19:22
googletest配置方法及使用
ipopt优化库配置及使用

← googletest配置方法及使用 ipopt优化库配置及使用→

最近更新
01
ipopt优化库配置及使用
07-21
02
ubuntu离线安装包的方法
07-21
03
其它控件的使用
03-05
更多文章>
Theme by Vdoing | Copyright © 2020-2024 Sirius0v0 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式