未指定块大小的OpenMP调度(静态):块大小和分配顺序

时间:2013-09-11 16:14:04

标签: openmp

关于未指定块大小的#pragma omp for schedule(static),我有几个问题。

在OpenMP中并行化循环的一种方法是手动执行此操作:

#pragma omp parallel 
{
    const int nthreads = omp_get_num_threads();
    const int ithread = omp_get_thread_num();
    const int start = ithread*N/nthreads;
    const int finish = (ithread+1)*N/nthreads;
    for(int i = start; i<finish; i++) {
        //          
    }
}

有没有充分的理由不在OpenMP中手动并行化这样的循环?如果我将值与#pragma omp for schedule(static)进行比较,我会发现给定线程的块大小不是t始终同意,因此OpenMP(在GCC中)实现的夹头尺寸与startfinish中定义的夹头尺寸不同。这是为什么?

我定义的startfinish值有几个方便的属性。

  1. 每个帖子最多只能获得一个块。
  2. 迭代值的范围直接随线程数增加(即对于100个线程,第一个线程将使用两个线程) 处理迭代1-50和第二个线程51-100而不是相反)。
  3. 对于完全相同范围内的两个for循环,每个线程将在完全相同的迭代上运行。
  4. 编辑: 原文我只说了一个块,但在考虑之后,如果线程数是,则块的大小可能为零比Nithread*N/nthreads = (ithread*1)*N/nthreads)大得多。我真正想要的属性最多只有一个块。

    使用#pragma omp for schedule(static)

    时,所有这些属性都能得到保证吗?

    根据OpenMP规范:

      

    依赖于哪个线程在任何其他情况下执行特定迭代的程序是不符合的。

      

    具有相同调度和迭代计数的不同循环区域,即使它们出现在相同的并行区域中,也可以不同地在线程之间分配迭代。唯一的例外是静态计划

    对于schedule(static),规范说:

      

    按照线程编号的顺序以循环方式将块分配给团队中的线程。

    另外,规范说“schedule(static):

      

    当没有指定chunk_size时,迭代空间被划分为大小大致相等的块,并且最多只有一个块被分配给每个线程。

    最后,规范针对schedule(static)

      

    静态计划的合规实施必须确保   逻辑迭代次数与线程的相同分配将在两个中使用   如果满足以下条件,则循环区域:1)两个循环区域具有相同数量的循环迭代,2)两个循环区域具有相同的chunk_size值,或者两个循环区域都没有指定chunk_size,3)两个循环区域绑定到同一个平行区域。

    因此,如果我正确读取此schedule(static)将具有我列为startfinish的相同方便属性,即使我的代码依赖于线程执行特定迭代。 我是否正确解释了这一点?当未指定块大小时,这似乎是schedule(static)的一种特殊情况。

    像我一样定义startfinish更容易,然后尝试中断此案例的规范。

1 个答案:

答案 0 :(得分:5)

有没有充分的理由不在OpenMP中手动并行化这样的循环?

我想到的第一件事:

  1. 您向OpenMP库添加了依赖项,因此如果要维护串行编译或者必须为库函数调用提供存根,则必须复制部分代码。
  2. 工作共享构造需要的代码更少,并且比显式并行化的循环更方便读取。如果你需要维护一个大的代码库,那就重要了。
  3. 您错过了schedule(static)之间的所有日程安排机会。
  4. 低级细节的混乱很容易反击。
  5. 使用#pragam omp进行计划(静态)时是否保证所有这些属性?

    让我们一个接一个地看:

    1。)每个线程只有一个块

      

    当没有指定chunk_size时,迭代空间被分成   大小大致相等的块,最多一个块   分发给每个线程。请注意,块的大小是   在这种情况下没有说明。

    最多一个块不是恰好一个块。因此,财产一不履行。此外,这就是为什么大块的大小没有说明。

    2。)迭代值的范围直接随线程数增加(即,对于具有两个线程的100次迭代,第一个线程将 进程迭代1-50和第二个线程51-100而不是 其他方式)

      

    静态的兼容实现   schedule必须确保逻辑迭代的分配相同   如果满足以下条件,则数字到线程将用于两个循环区域   条件得到满足:

         
        
    1. 两个循环区域具有相同数量的循环迭代
    2.   
    3. 两个循环区域都指定了相同的chunk_size值,或者两个循环区域都没有指定chunk_size
    4.   
    5. 两个循环区域都绑定到同一个并行区域。
    6.         

      两个这样的相同逻辑迭代之间的数据依赖性   保证满足循环,允许安全使用nowait   (例如,参见第182页的A.10节)。

    尽管我从来没有看到过与你所说的不同的东西,但我敢说即使属性二也没有实现,至少不是schedule(static)。在我看来,在某个基数的迭代空间中,唯一的保证是,如果遵守条件1,2和3,则相同的“逻辑迭代数”将被赋予相同的线程。

    如果您指定块大小,则确实已授予:

      

    当指定schedule(static,chunk_size)时,迭代被划分   进入大小为chunk_size的块,并将块分配给   团队中的线程以循环方式按顺序排列   线号。

    3。)对于两个完全相同范围的for循环,每个线程将在完全相同的迭代上运行

    这确实被授予,并且更加通用:对于具有相同基数的迭代空间的两个循环,将给予每个线程相同的“逻辑迭代数”。 OpenMP 3.1标准的Example A.10.2c应澄清这一点。