【问题标题】:C++ condition variables vs new threads for vectorizationC++ 条件变量与向量化的新线程
【发布时间】:2020-08-02 11:00:33
【问题描述】:

我有一个循环的代码块。一段代码对数据向量进行操作,我想对这个操作进行向量化。这个想法是将数组的细化分解到多个线程上,这些线程将在数组的子部分上工作。我必须在两种可能性之间做出决定。第一个是每次遇到本节时创建线程,并在最后将它们与主线程重新连接:

for(....)
{
//serial stuff

//crate threads
for(i = 0; i < num_threads; ++i)
{
    threads_vect.push_back(std::thread(f, sub_array[i]));
}

//join them
for(auto& t : threads_vect)
{
    t.join();
}

//serial stuff
}

这与使用 OpenMP 所做的类似,但由于问题很简单,我想使用 std::threads 而不是 OpenMP(除非有充分的理由反对)。

第二种方案是预先创建线程,避免创建和销毁的开销,并使用条件变量进行同步(同步省略了很多东西,只是大致思路):

std::condition_variable cv_threads;
std::condition_variable cv_main;

//create threads, the will be to sleep on cv_threads

for(....)
{
//serial stuff

//wake up threads
cv_threads.notify_all();

//sleep until the last thread finishes, that will notify.
main_thread_lock.lock();
cv_main.wait(main_lock);

//serial stuff
}

为了实现并行性,线程必须在计算开始时一醒来就解锁 thread_lock,然后再次获取它以进入睡眠状态并在它们之间进行同步以通知主线程。

我的问题是,在这样的上下文中,哪种解决方案通常更受欢迎,如果避免线程创建和销毁的开销通常值得增加复杂性(或者考虑到增加的同步也会增加时间,那么完全值得)。

显然,这也取决于每个线程的计算时间,但这可能会有很大差异,因为数据向量的长度也可能非常短(每个线程大约两个元素,这会导致计算时间大约 15 毫秒)。

【问题讨论】:

    标签: c++ openmp vectorization condition-variable stdthread


    【解决方案1】:

    创建新线程的最大缺点是线程创建和关闭通常非常昂贵。与通知条件变量相比,想想操作系统必须做的所有事情来启动线程。

    请注意,同步是始终所必需的,线程创建也是如此。例如,C++11 std::thread 在构造时引入了与创建线程的 synchronizes-with 关系。因此,您可以放心地假设,无论您的实现如何,线程创建总是比条件变量信令昂贵得多。

    像 OpenMP 这样的框架通常会尝试以某种方式分摊这些成本。例如,OpenMP 实现不需要在每次循环后关闭工作线程,许多实现不会这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 1970-01-01
      • 2017-09-27
      • 2018-09-10
      相关资源
      最近更新 更多