当前位置: 首页 > 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_…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

[拓扑优化] 1.概述

常见的拓扑优化方法有&#xff1a;均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有&#xff1a;有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...

EEG-fNIRS联合成像在跨频率耦合研究中的创新应用

摘要 神经影像技术对医学科学产生了深远的影响&#xff0c;推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下&#xff0c;基于神经血管耦合现象的多模态神经影像方法&#xff0c;通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里&#xff0c;本研…...