OpenMP任务并行性-性能问题



我有一个问题与OpenMP任务。我试图使用omp任务创建"for"循环的并行版本。但是,这个版本的执行时间比我使用omp for的基本版本长近2倍,我不知道这是什么原因。查看下面的代码:

omp for version:

t.start();
#pragma omp parallel num_threads(threadsNumber)
{
    for(int ts=0; ts<1000; ++ts)
    {
        #pragma omp for
        for(int i=0; i<size; ++i)
        {
            array_31[i] = array_11[i] * array_21[i];
        }
    }
}
t.stop();
cout << "Time of omp for: " << t.time() << endl;

omp任务版本:

t.start();
#pragma omp parallel num_threads(threadsNumber)
{
    #pragma omp master
    {
        for(int ts=0; ts<1000; ++ts)
        {
            for(int th=0; th<threadsNumber; ++th)
            {
                #pragma omp task
                {
                    for(int i=th*blockSize; i<th*blockSize+blockSize; ++i)
                    {
                        array_32[i] = array_12[i] * array_22[i];
                    }
                }                    
            }
            #pragma omp taskwait
        }
    }
}
t.stop();
cout << "Time of omp task: " << t.time() << endl;

在tasks版本中,i按与omp for相同的方式划分循环。每个任务都必须执行相同数量的迭代。任务总数等于线程总数。

性能结果:

Time of omp for: 4.54871
Time of omp task: 8.43251

什么是问题?两个版本是否有可能实现相似的性能?附加的代码很简单,因为我想只说明我的问题,我试图解决。我不期望两个版本给我相同的性能,但是我希望减少差异。

感谢您的回复。致以最亲切的问候。

我认为这里的问题是开销。当你声明一个循环为并行循环时,它会让所有线程同时执行for循环的各自部分。当你启动一个任务时,它必须经历整个设置过程,每次你启动一个任务。为什么不这样做呢?

#pragma omp parallel num_threads(threadsNumber)
{
    #pragma omp master
    {
        for(int ts=0; ts<1000; ++ts)
        {
            #pragma omp for
            for(int th=0; th<threadsNumber; ++th)
            {
                    for(int i=th*blockSize; i<th*blockSize+blockSize; ++i)
                    {
                        array_32[i] = array_12[i] * array_22[i];
                    }                   
            }

        }
    }
}

我想说的是,你在这里实验的问题与数据亲和力有关:当你使用#pragma omp for时,跨线程的迭代分布对于ts的所有值总是相同的,而对于任务,你没有办法指定任务到线程的绑定。

曾经说过,我在我的机器上用三个1M元素的数组执行了你的程序,两个版本之间的结果更接近:

  • t1_for: 2.041443 s
  • t1_tasking: 2.159012 s

(我用的是GCC 5.3.0 20151204)

最新更新