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

使用多线程std::thread发挥多核计算优势(解答)

使用多线程std::thread发挥多核计算优势(题目)

单核无能为力

如果我们的电脑只有一个核,那么我们没有什么更好的办法可以让我们的程序更快。

因为这个作业限制了你修改算法函数。你唯一能做的就是利用你电脑的多核。

使用多线程

由于我们的电脑有多个内核,所以,我们可以创建多线程来把任务“平均”分配给多个核来计算。

这样多个核在“同时”运算的时候就可以加速程序的执行。

多核的细节

关于我们创建多少个线程比较合适,多个线程真的可以各自分配到多个核而“同时”运行吗?

试一下就知道了。

双线程的效果

我们先用两个线程,把任务固定的分配给这两个线程,看看完成任务总的执行时间是不是变短了。

代码如下:

#include <iostream>
#include <cmath>//sqrt
#include <iostream>
#include <iomanip>//format output
#include <chrono>
#include <thread>//for faster code
#include <mutex>//for faster code
#include <sstream>//stringstream
using namespace std::chrono;//time_piont duration
using namespace std;//test helper function begin 测试辅助代码开始
void check_do(bool b, int line = __LINE__)
{if (b) { cout << "line:" << line << " Pass" << endl; }else { cout << "line:" << line << " Ohh! not passed!!!!!!!!!!!!!!!!!!!!!!!!!!!" << " " << endl; exit(0); }
}
#define check(msg)  check_do(msg, __LINE__);
//test helper function end 测试辅助代码结束//do not change this function! 不要修改这个函数
//if you want to check a number is prime number or not, you can use this function only.
//判断素数只能用这个函数
bool is_number_prime(int n)
{if (n == 2 || n == 3)//prime less than 5{return true;//is prime}if (n % 6 != 5 && n % 6 != 1)//is not prime{return false;}int cmb = (int)std::sqrt(n);for (int i = 5; i <= cmb; i += 6){if (n % i == 0 || n % (i + 2) == 0){return false;//is not prime}}return true;//is prime
}/*100以内的素数 primes within 1002 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
*/
//测试判断素数的函数是否正确
void test_is_prime_number(void)
{stringstream ss;for (int  i = 2; i < 100; i++){if (is_number_prime(i)){ss << i << " ";}}check(ss.str() == "2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 ");
}//do not change this function!
//不要修改此函数
long long test_the_sum_of_all_primes_within(long long scale)
{auto start = system_clock::now();long long sum = 0;for (int n = 2; n <= scale; n++) {if (is_number_prime(n)) {sum += n;}}cout << "the sum of all primes from 2~"<< setw(10) << scale << " is : " << setw(15) << sum<< ", elapled " << setw(10) << static_cast<long long>(duration<double, milli>(system_clock::now() - start).count()) << " milliseconds"<< endl;return sum;
}
//please change this function to let your program faster by use multi core in your CPU.
//请重新实现此函数以让你的CPU多核优势得到发挥
//hint: maybe you can use multi thread technology to let your code faster.
//提示:你可以使用多线程来发挥多核的计算优势从而让你的程序跑的更快
long long faster_test_the_sum_of_all_primes_within(long long scale)
{auto start = system_clock::now();long long sum = 0;std::mutex sum_mutex;auto fun = [&sum, &sum_mutex](long long scaleStart, long long scaleLast) {for (int n = scaleStart; n <= scaleLast; n++) {if (is_number_prime(n)) {std::lock_guard<std::mutex> lock(sum_mutex);//如果没有多线程互斥访问sum,那么sum的值就可能是错的。sum += n;}}};//区间平分,这样后面的第二个线程的计算量还是偏大,因为都是在处理更大的数字std::thread t1(fun, 2, scale / 2);std::thread t2(fun, scale / 2 + 1, scale);t1.join();//线程开始运行直到结束t2.join();//线程开始运行直到结束cout << "the sum of all primes from 2~" << setw(10) << scale << " is : " << setw(15) << sum<< ", elapled " << setw(10) << static_cast<long long>(duration<double, milli>(system_clock::now() - start).count()) << " milliseconds"<< endl;return sum;
}
//do not change the code in this function 
//不要修改此函数中的内容
int main()
{test_is_prime_number();long long sum = 0;cout << "base slow version:" << endl;sum = test_the_sum_of_all_primes_within(10000 * 10);check(sum == 454396537);sum = test_the_sum_of_all_primes_within(10000 * 100);check(sum == 37550402023);sum = test_the_sum_of_all_primes_within(10000 * 1000);check(sum == 3203324994356);sum = test_the_sum_of_all_primes_within(10000 * 10000);check(sum == 279209790387276);cout << endl << "my faster version:" << endl;sum = faster_test_the_sum_of_all_primes_within(10000 * 10);check(sum == 454396537);sum = faster_test_the_sum_of_all_primes_within(10000 * 100);check(sum == 37550402023);sum = faster_test_the_sum_of_all_primes_within(10000 * 1000);check(sum == 3203324994356);sum = faster_test_the_sum_of_all_primes_within(10000 * 10000);check(sum == 279209790387276);cout << "please enter enter for exit." << endl;cin.get();return 0;
}

运行结果:

代码分析

如同代码注释中所说,我们把求解区间一分为二,后面的一个线程整体上任务还是偏重。因为处理的都是大数据。

但即便这样简单的划分,两个线程比一个线程耗时还是大幅度降低的。

在一百万个整数求解的时候时间降低了50%;

在一千万个整数求解的时候时间降低了50%;

在一亿个整数求解的时候时间降低了30%;这是因为后面一个线程的计算量过大,两个线程的任务没有起到平分导致的。

可以预见,随着数据量的继续增大,这种平分区间的算法,会导致第二个线程完全占据计算量的大头。这时候会导致这种算法的优势降低,甚至减少的时间可以忽略不计。

但是我们的目的达到了。那就是我们已经验证了多线程多核在计算速度上的确是可以完胜单线程的,只要我们合理分配计算任务给多个线程。

继续增加线程数量

下面我们把区间3等分,创建3个线程,看看是不是耗时会不会继续降低:

long long faster_test_the_sum_of_all_primes_within(long long scale)
{auto start = system_clock::now();long long sum = 0;std::mutex sum_mutex;auto fun = [&sum, &sum_mutex](long long scaleStart, long long scaleLast) {for (int n = scaleStart; n <= scaleLast; n++) {if (is_number_prime(n)) {std::lock_guard<std::mutex> lock(sum_mutex);//如果没有多线程互斥访问sum,那么sum的值就可能是错的。sum += n;}}};//区间平分,这样后面的第二个线程的计算量还是偏大,因为都是在处理更大的数字std::thread t1(fun, 2, scale / 3);std::thread t2(fun, scale / 3 + 1, scale / 3 * 2);std::thread t3(fun, scale / 3 * 2 + 1, scale);t1.join();//线程开始运行直到结束t2.join();//线程开始运行直到结束t3.join();//线程开始运行直到结束cout << "the sum of all primes from 2~" << setw(10) << scale << " is : " << setw(15) << sum<< ", elapled " << setw(10) << static_cast<long long>(duration<double, milli>(system_clock::now() - start).count()) << " milliseconds"<< endl;return sum;
}

运行输出:

代码分析2

正如我们预期,时间继续下降,尤其是数据量达到一亿的时候,总耗时再次变为了原来的一半。

至此,多线程多核可以降低计算总时长已经被我们验证完毕。

怎么样?你学到了吗?

欢迎点赞收藏转发。让其他感兴趣的人也可以看到。

相关文章:

使用多线程std::thread发挥多核计算优势(解答)

使用多线程std::thread发挥多核计算优势&#xff08;题目&#xff09; 单核无能为力 如果我们的电脑只有一个核&#xff0c;那么我们没有什么更好的办法可以让我们的程序更快。 因为这个作业限制了你修改算法函数。你唯一能做的就是利用你电脑的多核。 使用多线程 由于我们…...

MySQL分页查询详解:优化大数据集的LIMIT和OFFSET

最近在工作中&#xff0c;我们遇到了一个需求&#xff0c;甲方要求直接从数据库导出一个业务模块中所有使用中的工单信息。为了实现这一目标&#xff0c;我编写了一条SQL查询语句&#xff0c;并请求DBA协助导出数据。尽管工单数量并不多&#xff0c;只有3000多条&#xff0c;但…...

解构赋值、函数默认值

暂时性死区&#xff0c;TDZ&#xff08;Temporal Dead Zone&#xff09; var x 1 {let x x//此处声明了x&#xff0c;但是没有对x赋值&#xff0c;相当于在赋值之前引用x&#xff0c;所以会造成报错console.log(x)//报错x is not defined&#xff0c;暂时性死区&#xff0c;…...

【已解决】Mybatis 实现 Group By 动态分组查询

&#x1f389;工作中遇到这样一个需求场景&#xff1a;实现一个统计查询&#xff0c;要求可以根据用户在前端界面筛选的字段进行动态地分组统计。也就是说&#xff0c;后端在实现分组查询的时候&#xff0c;Group By 的字段是不确定的&#xff0c;可能是一个字段、多个字段或者…...

Android修改默认gradle路径

Android Studio每次新建项目&#xff0c;都会默认在C盘生成并下载gradle相关文件&#xff0c;由于C盘空间有限&#xff0c;没多久C盘就飘红了&#xff0c;于是就需要把gradle相关文件转移到其他盘 1、到C盘找到gradle文件 具体路径一般是&#xff1a;C:\Users\用户\ .gradle …...

原生JS+canvas实现炫酷背景

原生JScanvas实现炫酷背景 可以在需要的背景页使用 <!doctype html> <html> <head> <meta charset"utf-8"> <title>HTML5 Canvas矩阵粒子波浪背景动画特效</title> <style> html,body { height:100%; } body { …...

Linux学习之NAS服务器搭建

NAS是Network Attached Storage的缩写&#xff0c;也就是网络附属存储。可以使用自己已经不怎么使用的笔记本搭建一台NAS服务器。 fdisk -l可以看一下各个磁盘的状态。 可以看到有sda、sdb、sdc和sdd等四块硬盘。 lvs、vgs和pvs结合起来看&#xff0c;sdb和sdc没有被使用。 …...

分享码云上8个宝藏又有价值的开源图片编辑器

如果你需要高效地处理图片&#xff0c;那么这8款实用工具是可以尝试的&#xff01; 它们能够进行一键抠图、放大、拼接、转矢量图、图标自动生成以及等操作&#xff0c;让你的工作效率飞升&#xff01; 在Gitee这个最有价值的开源项目计划是Gitee综合评定出的优秀开源项目的展示…...

TCP Header都有啥?

分析&回答 源端口号&#xff08;Source Port&#xff09; &#xff1a;16位&#xff0c;标识主机上发起传送的应用程序&#xff1b; 目的端口&#xff08;Destonation Port&#xff09; &#xff1a;16位&#xff0c;标识主机上传送要到达的应用程序。 源端&#xff0c;目…...

无涯教程-Android - AutoCompleteTextView函数

AutoCompleteTextView是一个类似于EditText的视图&#xff0c;只是它在用户键入时自动显示补充数据。 AutoCompleteTextView - 属性 以下是与AutoCompleteTextView控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关方法。…...

【Docker】 07-安装ElasticSearch、Kibana

安装ElasticSearch 1、拉取镜像 docker pull elasticsearch:6.4.2 2、运行 docker run -p 9200:9200 -p 9300:9300 --name es -d elasticsearch:6.4.2 启动会报错&#xff0c;按照下面流程修改 3、在宿主机中&#xff0c;修改配置sysctl.conf vim /etc/sysctl.conf 加入如下配…...

【数据结构篇】线性表1 --- 顺序表、链表 (万字详解!!)

前言&#xff1a;这篇博客我们重点讲 线性表中的顺序表、链表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列... 线性表在逻辑上是…...

C语言每日一练--Day(17)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;数对 截取字符串 &#x1f493;博主csdn个人主页&#xff1a;小小unico…...

8月琐碎但值得的事情

8月份结束了&#xff0c;最近心态比较好&#xff0c;慢点就慢点&#xff0c;没有那么着急了&#xff0c;可能是因为着急也没啥办法&#xff0c; 8月是比较开心的一个月&#xff0c;可能是做的事情更有盼头了&#xff0c;可能是看了喜欢的书&#xff0c;可能是我变瘦了&#xff…...

苹果Mac系统如何优化流畅的运行?提高运行速度

Mac系统的稳定性和流畅性一直备受大家称赞&#xff0c;这也是大多数人选择Mac的原因&#xff0c;尽管如此&#xff0c;我们仍不时地对Mac进行优化、调整&#xff0c;以使其比以前更快、更流畅地运行。以下是小编分享给各位的Mac优化方法&#xff0c;记得保存哦~ 一、释放被过度…...

Python 类和对象

类的创建 Python语言中&#xff0c;使用class关键字来创建类&#xff0c;其创建方式如下&#xff1a; class ClassName(bases):# class documentation string 类文档字符串&#xff0c;对类进行解释说明class_suiteclass是关键字&#xff0c;bases是要继承的父类&#xff0c;…...

VC++使用Microsoft Speech SDK进行文字TTS朗读

Microsoft Speech SDK下载地址 https://www.microsoft.com/en-us/download/details.aspx?id10121 需要msttss22L.exe、SpeechSDK51.exe、SpeechSDK51LangPack.exe三个&#xff0c;下载后全部安装 使用VS2005建立一个win32控制台项目 朗读"hello word"、中文“你好”…...

FFmpeg4.3.1+h264在windows下编译与VS2017项目集成

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。本文是音视频系…...

mapboxGL3新特性介绍

概述 8月7日&#xff0c;mapboxGL发布了3版本的更新&#xff0c;本文带大家一起来看看mapboxGL3有哪些新的特性。 新特新 如上图所示&#xff0c;是mapboxGL官网关于新版的介绍&#xff0c;大致翻译如下&#xff1a; 增强了web渲染的质量、便捷程度以及开发人员体验&#xff…...

类ChatGPT大模型LLaMA及其微调模型

1.LLaMA LLaMA的模型架构:RMSNorm/SwiGLU/RoPE/Transfor mer/1-1.4T tokens 1.1对transformer子层的输入归一化 对每个transformer子层的输入使用RMSNorm进行归一化&#xff0c;计算如下&#xff1a; 1.2使用SwiGLU替换ReLU 【Relu激活函数】Relu(x) max(0,x) 。 【GLU激…...

别再死记硬背了!用Multisim仿真带你玩转计数器与数据选择器(附FPGA引脚配置)

用Multisim仿真与FPGA实战&#xff1a;计数器与数据选择器的设计艺术 数字电路课程中那些抽象的概念&#xff0c;是否曾让你感到困惑&#xff1f;模5计数器、序列信号发生器这些名词听起来高深莫测&#xff0c;但通过Multisim仿真和FPGA实战&#xff0c;你会发现它们其实可以很…...

Qt实战:QGroupBox和QButtonGroup的5个实用技巧(附完整代码)

Qt实战&#xff1a;QGroupBox和QButtonGroup的5个实用技巧&#xff08;附完整代码&#xff09; 在Qt界面开发中&#xff0c;QGroupBox和QButtonGroup是两个看似简单却暗藏玄机的组件。很多开发者只停留在基础使用层面&#xff0c;却不知道它们能实现更复杂的交互逻辑和界面优化…...

智能求职工具GetJobs:让你的投递效率提升300%的全流程指南

智能求职工具GetJobs&#xff1a;让你的投递效率提升300%的全流程指南 【免费下载链接】get_jobs &#x1f4bc;【找工作最强助手】全平台自动投简历脚本&#xff1a;(boss、前程无忧、猎聘、拉勾、智联招聘) 项目地址: https://gitcode.com/gh_mirrors/ge/get_jobs 每天…...

基于麻雀优化算法(SSA)优化shared TCN-Transformer模型超参数,实现时间...

基于麻雀优化算法&#xff08;SSA&#xff09;优化shared TCN-Transformer模型超参数&#xff0c;实现时间序列预测。[1]模型采用共享TCN结构&#xff0c;用于提取Encoder Embedding和Decoder Embedding 的因果特征&#xff0c;在尽可能保证模型复杂度不变的情况下&#xff0c;…...

C# .NET 周刊|2026年3月1期

国内文章.NET 11 预览版1&#xff1a;CoreCLR 在 WebAssembly 上的全面集成与性能突破https://www.cnblogs.com/shanyou/p/19629649.NET 11 Preview 1 正式发布&#xff0c;标志着 CoreCLR 运行时能原生支持 WebAssembly。这是微软在跨平台战略上的重大进展。CoreCLR 提供更优性…...

Cayenne-MQTT-ESP:面向IoT平台的轻量级嵌入式MQTT客户端

1. 项目概述 Cayenne-MQTT-ESP 是一个专为 ESP8266 和 ESP32 平台设计的轻量级 MQTT 客户端库&#xff0c;其核心目标是将嵌入式设备无缝接入 Cayenne IoT 云平台&#xff08;现为 myDevices IoT Platform&#xff09;&#xff0c;实现双向数据通信与可视化控制。该库并非从零…...

MYSQL中 find_in_set() 函数实战:从语法到场景的深度解析

1. 揭开find_in_set()函数的神秘面纱 第一次在项目中看到find_in_set()这个函数时&#xff0c;我也是一头雾水。它看起来和IN操作符很像&#xff0c;但又有明显的不同。经过多次实战应用后&#xff0c;我发现它其实是处理逗号分隔字符串的利器。 这个函数的语法非常简单&#x…...

量化模型实测:百川2-13B-4bits在OpenClaw复杂任务中的精度损失

量化模型实测&#xff1a;百川2-13B-4bits在OpenClaw复杂任务中的精度损失 1. 测试背景与实验设计 去年在部署本地AI助手时&#xff0c;我遇到一个现实矛盾&#xff1a;大模型的能力与硬件成本难以兼得。当尝试用OpenClaw实现自动化办公流程时&#xff0c;发现13B参数的百川原…...

告别PDF转换烦恼:Marker让学术文档秒变Markdown的完整指南

告别PDF转换烦恼&#xff1a;Marker让学术文档秒变Markdown的完整指南 【免费下载链接】marker 一个高效、准确的工具&#xff0c;能够将 PDF 和图像快速转换为 Markdown、JSON 和 HTML 格式&#xff0c;支持多语言和复杂布局处理&#xff0c;可选集成 LLM 提升精度&#xff0c…...

DexGraspNet与多指手抓取算法详解:从理论到工程实现

目录 DexGraspNet与多指手抓取算法详解:从理论到工程实现 第一部分:原理详解 第一章 绪论与灵巧抓取的挑战 1.1 机器人抓取技术演进 1.1.1 从平行夹爪到多指灵巧手 1.1.2 灵巧抓取的独特挑战 1.2 DexGraspNet的研究背景与意义 1.2.1 大规模数据驱动的必要性 1.2.2 D…...