Boost:创建对象并使用线程填充向量

Posted

技术标签:

【中文标题】Boost:创建对象并使用线程填充向量【英文标题】:Boost: Creating objects and populating a vector with threads 【发布时间】:2017-11-05 00:48:16 【问题描述】:

使用基于this boost asio 的线程池,在这种情况下,该类被命名为ThreadPool,我想并行化std::vector<boost::shared_ptr<T>> 类型的向量的填充,其中T 是一个struct,其中包含一个std::vector<int> 类型的向量,其内容和大小在结构初始化后动态确定。

不幸的是,我在 c++ 和多线程方面都是新手,所以我解决这个问题的尝试非常失败。这是一个过于简化的示例程序,它对任务的非线程和线程版本进行计时。线程版本的性能是可怕的......

#include "thread_pool.hpp"
#include <ctime>
#include <iostream>
#include <vector>


using namespace boost;
using namespace std;


struct T 
  vector<int> nums = ;
;


typedef boost::shared_ptr<T> Tptr;
typedef vector<Tptr> TptrVector;


void create_T(const int i, TptrVector& v) 
  v[i] = Tptr(new T());
  T& t = *v[i].get();
  for (int i = 0; i < 100; i++) 
    t.nums.push_back(i);
  



int main(int argc, char* argv[]) 
  clock_t begin, end;
  double elapsed;

  // define and parse program options

  if (argc != 3) 
    cout << argv[0] << " <num iterations> <num threads>" << endl;
    return 1;
  
  int iterations = stoi(argv[1]),
      threads    = stoi(argv[2]);

  // create thread pool
  ThreadPool tp(threads);

  // non-threaded
  cout << "non-thread" << endl;
  begin = clock();

  TptrVector v(iterations);
  for (int i = 0; i < iterations; i++) 
    create_T(i, v);
  

  end = clock();
  elapsed = double(end - begin) / CLOCKS_PER_SEC;
  cout << elapsed << " seconds" << endl;

  // threaded
  cout << "threaded" << endl;
  begin = clock();

  TptrVector v2(iterations);
  for (int i = 0; i < iterations; i++) 
    tp.submit(boost::bind(create_T, i, v2));
  
  tp.stop();

  end = clock();
  elapsed = double(end - begin) / CLOCKS_PER_SEC;
  cout << elapsed << " seconds" << endl;

  return 0;

在进行了一些挖掘之后,我认为性能不佳可能是由于线程争夺内存访问,但我的新手状态让我无法利用这种洞察力。 您能否使用多个线程(最好是在线程池中)有效地填充指针向量?

【问题讨论】:

【参考方案1】:

您没有提供足够的详细信息或Minimal, Complete, and Verifiable example,所以请期待大量猜测。

createT 是一个“便宜”的功能。调度任务及其执行的开销要昂贵得多。这就是为什么你的表现不好。要从并行性中获得提升,您需要具有适当的工作粒度和工作量。粒度意味着每个任务(在您的情况下是一次调用createT)应该足够大以支付多线程开销。最简单的方法是将createT 呼叫分组以获得更大的任务。

【讨论】:

我同意gruffalo,而且因为你只是模拟工作,你可以只使用睡眠。但我确实想提出几点。 new T() 没有做你认为的事情。它实际上不是分配一个默认构造的 T,而是创建一个临时的默认构造 T,然后为新分配的对象使用 复制构造函数,最后销毁临时对象。此外,为所有变量声明包含类型更清楚,尤其是当它们在自己的行中时。 感谢您的帮助。事实证明,多线程正在改善程序的运行时间,但 ctime 没有透露这一点,因为它测量的是 CPU 时间而不是挂钟时间。切换到 chrono 使加速变得明显。无论如何,批处理作业是一个很好的建议,并且确实进一步提高了程序的运行时性能。所以我会将此标记为正确答案。

以上是关于Boost:创建对象并使用线程填充向量的主要内容,如果未能解决你的问题,请参考以下文章

两个线程c ++之间的boost asio通信

boost库 线程使用

在工作完成后立即删除 boost::thread 对象的最佳方法是啥?

boost thread:对象被释放后修改

提升线程不填充通过引用传递的本地对象

使用 boost::make_shared 创建矢量元素无法正常工作