c++ - 装修调度系统

标签 c++ multithreading queue multiprocessing openmp

我想使用多个处理器并行执行线性运算(将复杂的数学函数拟合到某些数据集)。

假设我的机器有 8 个核心,并且我想要容纳 1000 个数据集。我期望的是某个系统将 1000 个数据集作为队列,并将它们发送到 8 个核心进行处理,因此它首先将 1000 个数据集的前 8 个作为 FIFO。每个数据集的拟合时间通常都不同,因此 8 个数据集中的某些数据集的拟合时间可能比其他数据集长。我想要系统做的是保存拟合数据集的结果,然后为每个完成的线程从大队列(1000 个数据集)中恢复获取新数据集。这必须重新开始,直到处理完全部 1000 个数据集。然后我就可以继续我的程序了。

这样的系统叫什么? C++ 上有相应的模型吗?

我与 OpenMP 并行,并使用先进的 C++ 技术,如模板和多态性。

感谢您的努力。

最佳答案

您可以将 OpenMP 并行用于动态计划或 OpenMP 任务。两者都可以用于并行化每次迭代需要不同时间完成的情况。动态安排:

#pragma omp parallel
{
   Fitter fitter;
   fitter.init();
   #pragma omp for schedule(dynamic,1)
   for (int i = 0; i < numFits; i++)
      fitter.fit(..., &results[i]);
}

schedule(dynamic,1) 使每个线程一次执行一个迭代,并且除非没有更多迭代需要处理,否则线程永远不会闲置。

有任务:

#pragma omp parallel
{
   Fitter fitter;
   fitter.init();
   #pragma omp single
   for (int i = 0; i < numFits; i++)
   {
      #pragma omp task
      fitter.fit(..., &results[i]);
   }
   #pragma omp taskwait
   // ^^^ only necessary if more code before the end of the parallel region
}

此处,其中一个线程运行一个 for 循环,该循环生成 1000 个 OpenMP 任务。 OMP 任务保存在队列中并由空闲线程处理。它的工作原理有点类似于动态 for 循环,但允许代码构造更大的自由度(例如,您可以并行化递归算法的任务)。 taskwait 构造等待所有挂起的任务完成。它隐含在并行区域的末尾,因此只有在并行区域末尾之前有更多代码时才真正有必要。

在这两种情况下,每次调用 fit() 都将在不同的线程中完成。您必须确保拟合一组参数不会影响拟合其他组,例如fit() 是一个线程安全的方法/函数。这两种情况还要求执行 fit() 的时间远高于 OpenMP 构造的开销。

OpenMP 任务需要兼容 OpenMP 3.0 的编译器。如果您碰巧在 Windows 上进行开发,这排除了所有版本的 MS VC++(甚至是 VS2012 中的版本)。

如果您希望每个线程只初始化一个 fitter 实例,那么您应该采取一些不同的方法,例如将 fitter 对象设为全局和 threadprivate:

#include <omp.h>

Fitter fitter;
#pragma omp threadprivate(fitter)

...

int main()
{
   // Disable dynamic teams
   omp_set_dynamic(0);

   // Initialise all fitters once per thread
   #pragma omp parallel
   {
      fitter.init();
   }

   ...

   #pragma omp parallel
   {
      #pragma omp for schedule(dynamic,1)
      for (int i = 0; i < numFits; i++)
         fitter.fit(..., &results[i]);
   }

   ...

   return 0;
 }

这里fitterFitter类的全局实例。 omp threadprivate 指令指示编译器将其放入线程本地存储中,例如使其成为每个线程的全局变量。这些在不同的平行区域之间持续存在。您还可以在static 局部变量上使用omp threadprivate。这些也存在于不同的并行区域之间(但仅在同一函数中):

#include <omp.h>

int main()
{
   // Disable dynamic teams
   omp_set_dynamic(0);

   static Fitter fitter; // must be static
   #pragma omp threadprivate(fitter)

   // Initialise all fitters once per thread
   #pragma omp parallel
   {
      fitter.init();
   }

   ...

   #pragma omp parallel
   {
      #pragma omp for schedule(dynamic,1)
      for (int i = 0; i < numFits; i++)
         fitter.fit(..., &results[i]);
   }

   ...

   return 0;
 }

omp_set_dynamic(0) 调用会禁用动态团队,即每个并行区域将始终使用 OMP_NUM_THREADS 环境变量指定的线程数执行。

关于c++ - 装修调度系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12620183/

相关文章:

laravel - 如何在 Laravel 中收听 Postgres 监听/通知?

c# - 对数组进行排队还是将 Queue 写入更多维数组?

c++ - 用于函数调用的带有可变参数模板的模板类型推导

c++ - SVM 分类器未保存在 ".xml"中?

c++ - 从文本文件中读取单词和数字 (c++)

c++ - gdb 错误 : Backtrace stopped: previous frame identical to this frame (corrupt stack? )

c - 当函数有 void* 参数时如何在函数中传递参数?

c# - 如何同时异步执行多个 ping 操作?

java - 使用两个不同的线程打印偶数和奇数

c - 嵌套并行度 : Why only the main thread runs and executes the parallel for loop four times?