首页 > 解决方案 > 如何确保异步线程不使用共享资源并利用所有 CPU 内核?

问题描述

我正在使用std::asyncwithstd::launch::async来初始化一些线程并并行调用一个渲染函数,该函数接受两个整数(即图像xy的一个像素)并进行大量其他计算并最终输出一些值(即像素值)。只是为了更多的上下文:我正在谈论的函数有很多变量声明和其他函数调用。

我注意到,当我使用std::async和调用该函数并被多次调用时,我不再得到非常准确的结果。另外,我的程序在不使用std::async. 我是 C++ 线程的新手,但看起来,尽管线程应该异步且独立地运行,但它们有时可能会尝试访问彼此的资源(例如内存和 CPU 内核)。因此,它们有时可能会覆盖内存中的某些内容,从而导致结果不准确。

我想知道,我如何保证在通过调用函数时总是得到准确的结果std::async?我正在寻找答案,遇到了这个这个帖子,并了解到我可能应该使用一种叫做atomic变量的东西,以确保我的线程不使用彼此的资源并且并行运行(而不是按顺序运行)。但是,我找不到一个好的、清晰的例子来说明人们如何使用原子变量来实现这一点。原子变量应该在我的函数内部使用还是在创建线程时使用(例如,我传递给函数的参数)?因此,如果有人可以提供一个例子,我将不胜感激。

下面您可以看到我的代码的简化示例,但在调用类实例的成员函数方面与此答案非常相似。

#include <future>
#include <iostream>

class Render {

  public:
    std::vector<float> render (int x,int y);
    
    std::vector<float> m_pixelValue;
    int m_width=800;
    int m_height=600;
};

std::vector<float> Render::render (int x, int y) {
  std::vector<float> currentPixelData;
  // do lots of work here and update currentPixelData
  
  m_pixelValue = currentPixelData;
  return m_pixelValue;
}


int main()
{
  std::vector<float> pixelResult;
  std::vector<std::future<void>> threads;
  threads.reserve(5);
  std::unique_ptr<Render> renderInstance(new Render());
  for (int x=0; x<width;x++){
      for (int y=0;y<height;y++){
          threads.push_back(std::async(std::launch::async, &Render::render, &renderInstance, x, y));

          if(threads.size == 5){
              for (auto &th: threads){
                  pixelResult = th.get();
                  canvasData.update(pixelResult);
              }
              threads.clear();
          }
       }
    }
}

这是我按顺序运行该函数时得到的结果,没有async在此处输入图像描述

这是我使用时得到的async在此处输入图像描述

标签: c++multithreadinggraphicsrenderingatomic

解决方案


推荐阅读