当前位置: 首页 > news >正文

C++多线程编程(第四章 案例1,C++11和C++17 多核并行计算样例)

目录

    • 4.1手动实现多核base16编码
      • 4.1.1 实现base16编码
      • 4.1.2无多线程代码
      • 4.1.3 C++ 11多线程代码
      • 4.1.4 C++ 17多线程并发
      • 4.1.5 所有测试代码汇总

4.1手动实现多核base16编码

4.1.1 实现base16编码

二进制转换为字符串
一个字节8位,拆分为两个4位字节(最大值16)
拆分后的字节映射到0123456789abcdef

4.1.2无多线程代码


#include <thread>
#include<iostream>
#include<future>
#include <string>
#include <vector>
#include <chrono>//计时头,C++11using namespace std;
using namespace chrono;static const char base16[] = "0123456789abcdef";
void Base16Encode(const unsigned char* data, int size, unsigned char* out)
{for (int i = 0; i < size; i++){unsigned char d = data[i];//0000 0000//1234 5678 >> 4              => 0000 1234 移位操作//1234 5678 & 0000 1111       => 0000 5678char a = base16[d >> 4];//取出高位char b = base16[d & 0x0F];//取出低位out[i * 2] = a;out[i * 2+1] = b;}
}int main()
{//使用字符串进行16位编码测试string test_data = "测试base16编码";printf("test_data size=%d\n", test_data.size());//一个中文占用2个字节,一个英文占用1个字节,如果要解码出来包含中文和英文,有点难度unsigned char* out = new unsigned char[test_data.size()*2+1];Base16Encode((unsigned char*)test_data.data(), test_data.size(), out);//编码out[test_data.size()*2] = '\0';//字符串\0结尾,否则后面总有乱码cout << "base16:" << out << endl;//测试单线程base16编码效率{vector<unsigned char>in_data;in_data.resize(1024 * 1024 * 20);//  1024*1024*10  -> 10M 测试数据for (int i = 0; i < in_data.size(); i++){//初始化里面数据in_data[i] = i % 256;}vector<unsigned char>out_data;out_data.resize(in_data.size()*2);//是输入数据2倍auto start = system_clock::now();//计时开始Base16Encode(in_data.data(), in_data.size(),out_data.data());auto end = system_clock::now();//计时结束auto duration = duration_cast<milliseconds>(end-start);//模板函数,转换到毫秒cout << "编码:" << in_data.size() << "字节数据花费" << duration.count() << "毫秒" << endl;//cout << out_data.data() << endl;}printf("All done!\n");getchar();return 0;
}

在这里插入图片描述

4.1.3 C++ 11多线程代码

//C++11多线程
void Base16EncodeThread(const vector<unsigned char>&data, vector<unsigned char> &out)
{long size = data.size();int th_count = thread::hardware_concurrency();//系统支持的线程核心数printf("CPU report thread count:%d\n",th_count);//对原始数据进行切片long slice_count = size / th_count;//余数丢弃了,余数后续单独处理if (size < th_count){//只切一片th_count = 1;//1个线程搞定slice_count = size;}vector<thread> ths;//准备好线程ths.resize(th_count);//任务分配到各个线程   for (int i = 0; i < th_count; i++){//eg. 1234 5678 9abc defg hi//计算偏移位置long offset = i * slice_count;long count = slice_count;//最后一个线程要把余数加起来一起处理if (th_count > 1 && i == th_count - 1){count = slice_count + size%th_count;}//cout << offset << ":" << count << endl;ths[i] = thread(Base16Encode, data.data() + offset,count, out.data());}//等待所有线程处理结束for (auto &th : ths){th.join();}
}

4.1.4 C++ 17多线程并发

		printf("C++17多线程Base16编码效率测试(编译的时候先检查设置C++17) 开始计算===========================\n");//设置C++17方法:属性->C/C++ ->C++语言标准  ,设置ISOC++17vector<unsigned char>in_data;in_data.resize(TestNumber);//  1024*1024*10  -> 10M 测试数据for (int i = 0; i < in_data.size(); i++){//初始化里面数据in_data[i] = i % 256;}vector<unsigned char>out_data;out_data.resize(in_data.size() * 2);//是输入数据2倍auto start = system_clock::now();//计时开始//#include <execution> //C++17 支持std::for_each(std::execution::par,//并行计算 多核in_data.begin(),in_data.end(),[&](auto& d)//多线程进入此函数{char a = base16[(d >> 4)];char b = base16[(d & 0x0F)];int index = &d - in_data.data();out_data[index * 2] = a;out_data[index * 2 + 1] = b;});auto end = system_clock::now();//计时结束auto duration = duration_cast<milliseconds>(end - start);//模板函数,转换到毫秒cout << "C++17多线程 编码:" << in_data.size() << "字节数据花费" << duration.count() << "毫秒" << endl;

4.1.5 所有测试代码汇总


#include <thread>
#include<iostream>
#include<future>
#include <string>
#include <vector>
#include <chrono>//计时头,C++11#include <execution> //C++17 for_eachusing namespace std;
using namespace chrono;static const char base16[] = "0123456789abcdef";
void Base16Encode(const unsigned char* data, long size, unsigned char* out)
{for (int i = 0; i < size; i++){unsigned char d = data[i];//0000 0000//1234 5678 >> 4              => 0000 1234 移位操作//1234 5678 & 0000 1111       => 0000 5678char a = base16[d >> 4];//取出高位char b = base16[d & 0x0F];//取出低位out[i * 2] = a;out[i * 2+1] = b;}
}//C++11多线程
void Base16EncodeThread(const vector<unsigned char>&data, vector<unsigned char> &out)
{long size = data.size();int th_count = thread::hardware_concurrency();//系统支持的线程核心数printf("CPU report thread count:%d\n",th_count);//对原始数据进行切片long slice_count = size / th_count;//余数丢弃了,余数后续单独处理if (size < th_count){//只切一片th_count = 1;//1个线程搞定slice_count = size;}vector<thread> ths;//准备好线程ths.resize(th_count);//任务分配到各个线程   for (int i = 0; i < th_count; i++){//eg. 1234 5678 9abc defg hi//计算偏移位置long offset = i * slice_count;long count = slice_count;//最后一个线程要把余数加起来一起处理if (th_count > 1 && i == th_count - 1){count = slice_count + size%th_count;}//cout << offset << ":" << count << endl;ths[i] = thread(Base16Encode, data.data() + offset,count, out.data());}//等待所有线程处理结束for (auto &th : ths){th.join();}
}int main()
{int TestNumber = 1024 * 1024 * 20 - 1; //1024 * 1024 * 10  -> 10M 测试数据大小//使用字符串进行16位编码测试string test_data = "测试base16编码";printf("test_data size=%d\n", test_data.size());//一个中文占用2个字节,一个英文占用1个字节,如果要解码出来包含中文和英文,有点难度unsigned char* out = new unsigned char[test_data.size()*2+1];Base16Encode((unsigned char*)test_data.data(), test_data.size(), out);//编码out[test_data.size()*2] = '\0';cout << "base16:" << out << endl;//测试单线程base16编码效率{printf("单线程Base16编码效率测试 开始计算===========================\n");vector<unsigned char>in_data;in_data.resize(TestNumber);//  1024*1024*10  -> 10M 测试数据for (int i = 0; i < in_data.size(); i++){//初始化里面数据in_data[i] = i % 256;}vector<unsigned char>out_data;out_data.resize(in_data.size()*2);//是输入数据2倍auto start = system_clock::now();//计时开始Base16Encode(in_data.data(), in_data.size(),out_data.data());auto end = system_clock::now();//计时结束auto duration = duration_cast<milliseconds>(end-start);//模板函数,转换到毫秒cout << "编码:" << in_data.size() << "字节数据花费" << duration.count() << "毫秒" << endl;//cout << out_data.data() << endl;//预览编码后的文本}//测试C++11多线程base16编码效率{printf("C++11多线程Base16编码效率测试 开始计算===========================\n");vector<unsigned char>in_data;in_data.resize(TestNumber);//  1024*1024*10  -> 10M 测试数据for (int i = 0; i < in_data.size(); i++){//初始化里面数据in_data[i] = i % 256;}vector<unsigned char>out_data;out_data.resize(in_data.size() * 2);//是输入数据2倍auto start = system_clock::now();//计时开始Base16EncodeThread(in_data, out_data);//多线程auto end = system_clock::now();//计时结束auto duration = duration_cast<milliseconds>(end - start);//模板函数,转换到毫秒cout << "C++11多线程 编码:" << in_data.size() << "字节数据花费" << duration.count() << "毫秒" << endl;//cout << out_data.data() << endl;//预览编码后的文本}//测试C++11多线程base16编码效率{printf("C++17多线程Base16编码效率测试(编译的时候先检查设置C++17) 开始计算===========================\n");//设置C++17方法:属性->C/C++ ->C++语言标准  ,设置ISOC++17vector<unsigned char>in_data;in_data.resize(TestNumber);//  1024*1024*10  -> 10M 测试数据for (int i = 0; i < in_data.size(); i++){//初始化里面数据in_data[i] = i % 256;}vector<unsigned char>out_data;out_data.resize(in_data.size() * 2);//是输入数据2倍auto start = system_clock::now();//计时开始//#include <execution> //C++17 支持std::for_each(std::execution::par,//并行计算 多核in_data.begin(),in_data.end(),[&](auto& d)//多线程进入此函数{char a = base16[(d >> 4)];char b = base16[(d & 0x0F)];int index = &d - in_data.data();out_data[index * 2] = a;out_data[index * 2 + 1] = b;});auto end = system_clock::now();//计时结束auto duration = duration_cast<milliseconds>(end - start);//模板函数,转换到毫秒cout << "C++17多线程 编码:" << in_data.size() << "字节数据花费" << duration.count() << "毫秒" << endl;//cout << out_data.data() << endl;//预览编码后的文本}printf("All done!\n");getchar();return 0;
}

在这里插入图片描述
分析:
release版本优化的比较多,之所以C++17耗时较长原因是进入多线程次数远远大于C++11,C++11只进入了12次,而C++17采用lambda表达式函数,进入了TestNumber次

相关文章:

C++多线程编程(第四章 案例1,C++11和C++17 多核并行计算样例)

目录 4.1手动实现多核base16编码4.1.1 实现base16编码4.1.2无多线程代码4.1.3 C 11多线程代码4.1.4 C 17多线程并发4.1.5 所有测试代码汇总 4.1手动实现多核base16编码 4.1.1 实现base16编码 二进制转换为字符串 一个字节8位&#xff0c;拆分为两个4位字节&#xff08;最大值…...

获取远程仓库的信息和远程分支的信息

前记&#xff1a; git svn sourcetree gitee github gitlab gitblit gitbucket gitolite gogs 版本控制 | 仓库管理 ---- 系列工程笔记. Platform&#xff1a;Windows 10 Git version&#xff1a;git version 2.32.0.windows.1 Function&#xff1a;获取远程仓库的信息和远…...

QT学习day1

一、思维导图 二、作业&#xff1a;实现登录界面 #include "widget.h" #include<QDebug> #include<QIcon>Widget::Widget(QWidget *parent): QWidget(parent) {/**********************窗口******************///设置窗口图标this->setWindowTitle…...

unity面试八股文 - 框架设计与资源管理

Unity项目框架是如何设计的&#xff1f;有哪些原则 在设计Unity项目框架时&#xff0c;通常会遵循一些基本的原则和步骤。以下是主要的一些原则&#xff1a; 模块化&#xff1a;每个功能都应该被作为一个独立的模块来处理&#xff0c;这样可以方便修改和维护。 低耦合&#x…...

智能网关IOT 2050采集应用

SIMATIC IOT2050 是西门子公司新推出的应用于企业数字化转型的智能边缘计算和云连接网关。 它将云、公司内 IT 和生产连接在一起&#xff0c;专为直接在生产环境中获取、处理和传输数据的工业 IT 解 决方案而设计。例如&#xff0c;它可用于将生产 过程与基于云的机器和生产数据…...

iOS代码混淆-从入门到放弃

​ 目录 1. 什么是iOS代码混淆&#xff1f; 2. iOS自动代码混淆的方法是什么&#xff1f; 3. iOS代码混淆的作用是什么&#xff1f; 4. 怎么样才能做到更好的iOS代码混淆&#xff1f; 总结 参考资料 1. 什么是iOS代码混淆&#xff1f; 代码混淆是指将程序中的方法名、属…...

基于Eigen的位姿转换

位姿中姿态的表示形式有很多种&#xff0c;比如&#xff1a;旋转矩阵、四元数、欧拉角、旋转向量等等。这里基于Eigen实现四种数学形式的相互转换功能。本文利用Eigen实现上述四种形式的相互转换。我这里给出一个SE3&#xff08;4*4&#xff09;(先平移、再旋转)的构建方法&…...

Jmeter之Bean shell使用详解

一、什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精…...

TCP/IP(八)TCP的连接管理(五)四次握手

一 tcp连接断开 每一个TCP报文的超时重传都由一个特定的内核参数来控制 ① 四次握手的过程 遗留&#xff1a; 谁先发送FIN包,一定是client吗? --> upload和download补充&#xff1a; 主动和被动断开连接的场景 "四次握手过程描述" F --> FIN --> F…...

MyBatis-Plus主键生成策略[MyBatis-Plus系列] - 第491篇

历史文章&#xff08;文章累计490&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 ​…...

Spring——和IoC相关的特性

目录 IoC中Bean的生命周期 实例化&#xff08;Instantiation&#xff09; 属性注入&#xff08;Populate Properties&#xff09; 初始化&#xff08;Initialization&#xff09; 使用&#xff08;Bean in Use&#xff09; 销毁&#xff08;Destruction&#xff09; Laz…...

在 TensorFlow 中调试

如果调试是消除软件错误的过程&#xff0c;那么编程一定是添加错误的过程。Edsger Dijkstra。来自 https://www.azquotes.com/quote/561997 一、说明 在这篇文章中&#xff0c;我想谈谈 TensorFlow 中的调试。 在之前的一些帖子&#xff08;此处、此处和此处&#xff09;中&…...

想要精通算法和SQL的成长之路 - 连续的子数组和

想要精通算法和SQL的成长之路 - 连续的子数组和 前言一. 连续的子数组和1.1 最原始的前缀和1.2 前缀和 哈希表 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 连续的子数组和 原题链接 1.1 最原始的前缀和 如果这道题目&#xff0c;用前缀和来算&#xff0c;我们的思路…...

【C++】头文件chrono

2023年10月16日&#xff0c;周一晚上 当前我只是简单的了解了一下chrono 以后可能会深入了解chrono并更新文章 目录 功能原理头文件chrono中的一些类头文件chrono中的数据类型一个简单的示例程序小实验&#xff1a;证明a的效率比a高 功能 这个chrono头文件是用来处理时间的…...

Python学习六

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

Springboot 集成 WebSocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在WebSocket API中&#xff0c;浏览器和服务器只需要完成一次握手&#xff0c;两者之间就直接可以创建持久性的连接…...

谨以此篇,纪念我2023年曲折的计算机保研之路

目录 阶段一&#xff1a;迷茫阶段二&#xff1a;准备个人意愿保研材料准备套磁老师5.1日 浙大线上编程测试5.8日 浙大线上面试 —— 一面5.17日 浙大线上面试——二面5.29日 实验室面试结果5.27日 南开线上面试6.20日 华师电话面试 阶段三&#xff1a;旅途北航CS&#xff08;6.…...

VSS、VDD、VBAT、VSSA

引言 在学习设计TM32时&#xff0c;发现芯片除了GPIO引脚外还会引出许多引脚&#xff0c;以STM32F407ZGT6为例除了GPIO引脚还会有以下引脚 如VSS、VDD、VBAT、VSSA、NRST、VREF、VDDA、VCAP_1、VCAP_2、PDR_ON这些引脚。他们有何作用&#xff0c;电路设计中应如何连接&#x…...

【Rust基础③】方法method、泛型与特征

文章目录 6 方法 Method6.1 定义方法self、&self 和 &mut self 6.2 自动引用和解引用6.3 关联函数 7 泛型和特征7.1 泛型 Generics7.1.1 结构体中使用泛型7.1.2 枚举中使用泛型7.1.3 方法中使用泛型为具体的泛型类型实现方法 7.1.4 const 泛型 7.2 特征 Trait7.2.1 为类…...

48.排列问题求解

思路分析&#xff1a;通过为每一队分配一个id&#xff0c;join条件要求t1.num < t2.num实现相同两队只比一次 代码实现&#xff1a; with t as (SELECT team_name,caseteam_nameWHEN 勇士 then 1WHEN 湖人 then 2WHEN 灰熊 then 3else 4end numFROM team )SELECT t1.team_…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

shell脚本质数判断

shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数&#xff09;shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数&#xff09; 思路&#xff1a; 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …...

Android多媒体——音/视频数据播放(十八)

在媒体数据完成解码并准备好之后,播放流程便进入了最终的呈现阶段。为了确保音视频内容能够顺利输出,系统需要首先对相应的播放设备进行初始化。只有在设备初始化成功后,才能真正开始音视频的同步渲染与播放。这一过程不仅影响播放的启动速度,也直接关系到播放的稳定性和用…...