OpenMP Nested Loop,代码在做什么?

时间:2012-11-27 05:31:30

标签: c loops parallel-processing openmp nested-loops

我在理解OpenMP如何使用嵌套循环时遇到问题。请帮忙!

我得到以下代码并行运行:

#pragma omp parallel private(i)
{
for(i=0; i<n; i++)
{
    #pragma omp for
    for(j=0; j<n; j++)
    {
        if(asubsref(seed,j) > 0)
            asubsref(bin,j) = asubsref(bin,j) + 1;
    }
    #pragma omp for
    for(j=0; j<n; j++)
        asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
}
}

但是,我不太确定这段代码是如何工作的(我只是运气好)。这就是我认为它正在做的......

因此for(i=0; i<n; i++)被拆分为不同的线程并且并行运行。因为i被声明为private,所以循环的每个实例都是“沙盒”;也就是说,对j的任何更改都保留在该线程中(至少在完成所有线程之前?)。我很困惑,因为没有声明#pragma omp for导致代码破坏......我不确定为什么会这样。

如果有人能指导我完成这段代码的工作,我会非常感激!谢谢!

1 个答案:

答案 0 :(得分:2)

这是人们通常所做的,以减少多次进入的开销并进出并行区域。将您问题中的代码与以下等效代码进行比较:

for (i=0; i<n; i++)
{
    #pragma omp parallel for
    for (j=0; j<n; j++)
    {
        if (asubsref(seed,j) > 0)
            asubsref(bin,j) = asubsref(bin,j) + 1;
    }
    #pragma omp parallel for
    for (j=0; j<n; j++)
        asubsref(seed,j) = asubsref(seed,j) - asubsref(w,i);
}

它在i n次上运行外循环。在外部循环的每次迭代中,它在j上运行两个并行循环,在线程之间拆分n次迭代。这里的问题是你内部有两个平行区域,每个区域被激活n次。这可能会增加n的特定时间间隔的显着开销(实际间隔取决于许多因素)。

为了减少开销,可以将整个代码放在并行区域内。因此,每个线程将执行外部循环的所有迭代,并且内部迭代仍将在线程之间分割。如果删除工作共享构造,则内部循环不会在线程之间分配。相反,每个线程都会执行完整范围的外部内部迭代,因此例如asubsref(bin,j)将增加到num_threads次,而不是仅增加一次(为什么&# 34;最多&#34;?提示:不受保护的并发数据访问)。

大多数情况下,当一个人在并行构造中运行外部循环时,人们希望不同的线程在相同的迭代中保持滴答作响。这可以通过循环体末端的屏障来实现:

#pragma omp parallel private(i)
{
    for (i = 0; i < n; i++)
    {
        ...
        #pragma omp barrier
    }
}

在您的情况下,由于for工作共享结构在其末尾具有隐式屏障,因此不需要显式屏障。