栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

如何让C++运行的更快 in C++【C++学习笔记】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何让C++运行的更快 in C++【C++学习笔记】

79.如何让C++运行的更快 in C++

这次的主题是:如何通过多线程来提高性能

此次的多线程是来源于C++11的std::asnyc

asnyc的意思的 异步

std::asnyc用法 首先要包含头文件#include

伪代码演示

如果要加载一个文件里所有的东西,则可以用下面的for循环

for (const auto &file : meshFilepaths) {
    m_Meshes.push_back(Mesh::Load(file));
}

然而如果文件里的东西很大,则会使得加载的时间很长。因为这里是加载完一个后再加载一个

所以这里可以实现一个并行for来多线程加载

std::async(启动类型, 某种实际异步运行的函数)

在这里的并行for的实现中,设置启动类型为async是很重要的,如果不设置成这个而设置成deferred,那么它可能不会在一个单独的线程上完成,C++会根据当前工作负载来选择

deferred的意思是 延期

而以当前为例子实现的函数中,要有两个操作

  • 一个是Mesh::Load(file)加载文件
  • 一个是push_back进vector

所以这里要把这两步包装成一个函数放到std::async的第二个参数中

static void LoadMesh(std::vector>& meshes, std::string filepath) {
    auto mesh = Mesh::Load(filepath);	//一个Load
    meshes.push_back(mesh);	//一个push_back
}

然而这里还是会有点小问题:如果在push_back的时候修改这个vector,则会出问题

所以这里必须要锁定这个网格vector,当它被修改时我们锁定它,push_back之后,我们就解锁它

  • 这个锁意味着,在我们完成当前线程的push_back之前,如果另一个mesh正在并发加载,试图同时push_back,它就会等待,直到我们解锁那个网格vector

    • 所用到的做法是使用互斥量mutex

      static std::mutex s_MeshesMutex;
      
      static void LoadMesh(std::vector>& meshes, std::string filepath) {
          auto mesh = Mesh::Load(filepath);	//一个Load
          
          std::lock_guard lock(s_MeshesMutex);
          //意思是,这个所会在某个地方锁定了这个mutex互斥锁,这样它就不能被其他线程锁定,直到它被解锁
          //而只要我们退出这个函数,它就会解锁,因为lock的析构函数会解锁那个锁
          //防止同时间push_back元素使得vector乱了
          meshes.push_back(mesh);	//一个push_back
      }
      

而写完了一个大的函数后,就可传进async去完成并行for的制作了

for (const auto& file : meshFilepaths) {
    //此处的LoadMesh就是上面完成总操作的函数了
    std::async(std::Launch::async, LoadMesh, m_Meshes, file);
}

async实际上返回一个std::future,而我们是需要保留这个返回值std::future的

如果不保留,它将被摧毁,而在被摧毁时,它需要确保过程实际上已经完成了,这基本上意味着它根本就不是并行的。因为在结束这个for循环的一次迭代后,这个函数实际上将在std::future的析构函数中

所以我们只需把它储存进一个超脱这个for的作用域的变量就可以了。所以这里创建一个std::future的vector

std::vector> m_Futures;
//future的类型是void,即是LoadMesh总操作函数的返回类型

for (const auto& file : meshFilepaths) {
    //此处的LoadMesh就是上面完成总操作的函数了
    m_Futures.push_back(std::async(std::Launch::async, LoadMesh, m_Meshes, file));
}

至此便结束了,完成了一个并行的for。我们分派了MeshLoad函数(总的操作函数)在另一个线程上异步完成,C++库为我们处理所有这些东西

我们可以自己用线程写这个,写一些线程池(可以自行多线程操作,利用std::thread,但是需要自己写线程池),这样就可以重用线程,做所有这些事情。然而,我们也可以依赖C++标准库,因为它已经为我们做了所有的事情

而完成了这个并行的for后,它的速度能比之前快了10倍甚至更多!!!

故这种多线程对于程序而言是非常有益的,你可以通过充分利用你的硬件来提高速度

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873523.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号