为什么某些机器上的openmp并行化速度较慢

时间:2012-04-12 14:19:10

标签: parallel-processing openmp

我正在开发一种可以并行运行以提高速度的数值模拟。我通常多次运行模拟,然后对各个结果进行平均。这个循环,多次运行,使用openmp并行化:

    // set the number of threads
    omp_set_num_threads (prms.nthreads);

#pragma omp parallel if(prms.parallel) shared(total) private(iRun)
    {
#pragma omp for schedule(dynamic)
        for (iRun = 1; iRun <= prms.number_runs; iRun++)
        {
            // perform the simulation
        }
    }

除了total之外,实际上没有共享变量,它是一个大小为iRun的数组,其中每个元素都包含相应运行的结果。在我到目前为止测试的所有机器上,速度与核心数量成比例增加;因此,使用4个线程比没有并行化时快4倍。但是,在我们的计算集群上情况并非如此(第二次运行是并行化并使用2个线程,因此应该快两倍):

$ time hop ...

real    0m50.595s
user    0m50.484s
sys 0m0.088s

$ time hop ... -P

real    1m35.505s
user    3m9.238s
sys 0m0.134s

如您所见,并行计算比序列化计算慢得多,即使总计也是如此。我确信这不是内存问题,而且计算机有多个内核。

可能是什么问题?它可能是openmp实现吗?或者系统中的某些内容是否配置错误?我真的不知道该找什么。

2 个答案:

答案 0 :(得分:0)

缓存一致性似乎是一个问题。如果total是您的共享数组,并且每个线程都在total中更新自己的单元格,由于线程正在动态选择工作,因此线程很可能必须更新{{1}中的相邻值这可能在同一个缓存行中。

在您的测试计算机上,这可能不会造成太大伤害,因为total可能在共享L3中是连贯的,但在群集中,它需要在网络上来回传递,这应该是伤。

答案 1 :(得分:0)

由于我没有足够的声誉,我将其添加为答案而不是评论:

您是否确保为并行而非串行初始化不同模拟的数据?

我知道根据您的架构,这会产生巨大的差异。也许你可以暗示一下架构。

准确地说: 如果你这样做

for(i = 1; i < prms.number_runs; ++i)
   allocAndInitializeSimulationData( i )

#pragma omp parallel if(prms.parallel) shared(total) private(iRun)
{
#pragma omp for schedule(dynamic)
    for (iRun = 1; iRun <= prms.number_runs; iRun++)
    {
        // perform the simulation
    }
}

这可能比

慢得多
#pragma omp parallel if(prms.parallel) shared(total) private(iRun)
{
   #pragma omp for schedule(dynamic)
   for(i = 1; i < prms.number_runs; ++i)
      initializeAndAllocSimulation( i )

   #pragma omp for schedule(dynamic)
   for (iRun = 1; iRun <= prms.number_runs; iRun++)
   {
      // perform the simulation
   }
}