TBB并行编程2 _ 性能测试,任务域

2023-12-02 16:10

本文主要是介绍TBB并行编程2 _ 性能测试,任务域,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

性能测试:

#include <tbb/tick_count.h>
#define TICK(x) auto bench_##x = tbb::tick_count::now();
#define TOCK(x) std::cout << #x ": " << (tbb::tick_count::now() - bench_##x).seconds() << "s" << std::endl;#include <iostream>
#include"ticktock.h"
#include <string>
#include <cmath>
#include <vector>
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/parallel_reduce.h>void test01() {size_t n = 1 << 27;std::vector<float> a(n);TICK(for);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++) {a[i] = std::sin(i);}});TOCK(for);TICK(reduce);float res = tbb::parallel_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 += a[i];}return local_res; }, [](float x, float y) {return x + y;});TOCK(reduce);std::cout << res << std::endl;
}
void test02() {size_t n = 1 << 27;std::vector<float> a(n);TICK(for);for (size_t i = 0; i < n; i++){a[i] += std::sin(i);}TOCK(for);TICK(reduce);float res = 0;for (size_t i = 0; i < n; i++){res += a[i];}TOCK(reduce);std::cout << res << std::endl;
}int main() {test01();std::cout << "------------" << std::endl;test02();
}

通过上面那个时间戳就可以计时,从结果来看显然并行算法耗时更少。

评价一个并行速度通常会用加速比=串行用时÷并行用时

更专业的性能测试框架:Google benchmark

这个我安装了之后一直显示连接不上。。。。我也很奇怪

#include <iostream>
#include <vector>
#include <cmath>
#include <benchmark/benchmark.h>constexpr size_t n = 1<<27;
std::vector<float> a(n);void BM_for(benchmark::State &bm) {for (auto _: bm) {// fill a with sin(i)for (size_t i = 0; i < a.size(); i++) {a[i] = std::sin(i);}}
}
BENCHMARK(BM_for);void BM_reduce(benchmark::State &bm) {for (auto _: bm) {// calculate sum of afloat res = 0;for (size_t i = 0; i < a.size(); i++) {res += a[i];}benchmark::DoNotOptimize(res);}
}
BENCHMARK(BM_reduce);BENCHMARK_MAIN();

 代码是这样的

回更:安装好啦

 总结安装错误:要找到config。

cmake_minimum_required(VERSION 3.10)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Release)
SET(TBB_DIR "D:\\vsstl\\C_CUDA\\vcpkg-master\\vcpkg-master\\packages\\tbb_x64-windows\\share\\tbb")
SET(benchmark_DIR "D:\\vsstl\\C_CUDA\\vcpkg-master\\vcpkg-master\\packages\\benchmark_x64-windows\\share\\benchmark")
project(main LANGUAGES CXX)add_executable(main main.cpp)#find_package(OpenMP REQUIRED)
#target_link_libraries(main PUBLIC OpenMP::OpenMP_CXX)find_package(TBB REQUIRED)
target_link_libraries(main PUBLIC TBB::tbb)set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "Turn off the fking test!")
find_package(benchmark CONFIG REQUIRED)
target_link_libraries(main PUBLIC benchmark::benchmark benchmark::benchmark_main)

任务域与嵌套

#include <iostream>
#include <tbb/parallel_for.h>
#include <tbb/task_arena.h>
#include <vector>
#include <cmath>int main() {size_t n = 1<<26;std::vector<float> a(n);tbb::task_arena ta(4);//可以指定用多少线程ta.execute([&] {tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t i) {a[i] = std::sin(i);});});return 0;
}

也可以用两个for进行嵌套,这样可以解决n比较小,核心没有用光的问题:

tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t i) {tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t j) {a[i * n + j] = std::sin(i) * std::sin(j);});});

但是嵌套会导致死锁问题:

tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t i) {std::lock_guard lck(mtx);tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t j) {a[i * n + j] = std::sin(i) * std::sin(j);});});

这是因为tbb采用的是工作窃取法,就是在线程t1做完自己的工作之后,就会去看别的线程有没有做完工作,如果还有没做完的工作就会从这个线程里将工作取出,放到自己的t1线程里。

因此内部 for 循环有可能“窃取”到另一个外部 for 循环的任务,从而导致 mutex 被重复上锁。

所以为了解决这种问题:

1、用递归锁:

std::recursive_mutex mtx;

2、另外创建一个任务域

 tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t i) {std::lock_guard lck(mtx);tbb::task_arena ta;ta.execute([&] {tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t j) {a[i * n + j] = std::sin(i) * std::sin(j);});});});

3、isolate隔离:

tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t i) {std::lock_guard lck(mtx);tbb::this_task_arena::isolate([&] {tbb::parallel_for((size_t)0, (size_t)n, [&] (size_t j) {a[i * n + j] = std::sin(i) * std::sin(j);});});});

这篇关于TBB并行编程2 _ 性能测试,任务域的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/445962

相关文章

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

在Golang中实现定时任务的几种高效方法

《在Golang中实现定时任务的几种高效方法》本文将详细介绍在Golang中实现定时任务的几种高效方法,包括time包中的Ticker和Timer、第三方库cron的使用,以及基于channel和go... 目录背景介绍目的和范围预期读者文档结构概述术语表核心概念与联系故事引入核心概念解释核心概念之间的关系

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-

使用Python进行GRPC和Dubbo协议的高级测试

《使用Python进行GRPC和Dubbo协议的高级测试》GRPC(GoogleRemoteProcedureCall)是一种高性能、开源的远程过程调用(RPC)框架,Dubbo是一种高性能的分布式服... 目录01 GRPC测试安装gRPC编写.proto文件实现服务02 Dubbo测试1. 安装Dubb

Python的端到端测试框架SeleniumBase使用解读

《Python的端到端测试框架SeleniumBase使用解读》:本文主要介绍Python的端到端测试框架SeleniumBase使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录SeleniumBase详细介绍及用法指南什么是 SeleniumBase?SeleniumBase