OpenMP基于运行时参数设置固定大小的块

时间:2012-05-12 10:37:45

标签: c openmp

假设我有一个n元素和n_threads的向量。 我想使用#pragma omp parallel使每个线程接收n / n_threads块大小, 最后一个取决于具体情况。

#include <stdio.h>
#include <omp.h>

int main()
{

    int *v = malloc ( n * sizeof(int) );

    #pragma omp parallel for (what should i put here?)
    for(i = 0; i < n; ++i)
    {
        ++v[i];
    }
    return 0;
}

Ex:n = 10003,n_threads = 4

  • thread_0应该获得2500个块
  • thread_1应该获得2500块
  • thread_2应该获得2500个块
  • thread_3应该获得2503块

2 个答案:

答案 0 :(得分:3)

简而言之 - 你做不到。您所能做的就是在不指定块大小的情况下指定schedule(static)子句,OpenMP运行时将以大致相同大小的块划分迭代计数。具体如何取决于实施。这就是OpenMP标准关于静态调度的内容:

  

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

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

对于n = 10003和n_threads = 4,您可以指定块大小为2500,迭代空间将被分成大小为2500,2500,2500,2500和3的块,它们将被分配给线程0,1,因此,线程0将获得2503次迭代,但它们在迭代空间中不会是连续的。如果您没有指定块大小,则由实现来决定给予额外迭代的线程。

答案 1 :(得分:0)

据我所知,OpenMP不能保证确切的块大小,但是自己计算它们并不难。这是一些示例代码:

#include <stdio.h>
#include <omp.h>

int main(void) {

  int n = 10003;
  int n_threads = 4;
  int chunk_size = n / n_threads;

  #pragma omp parallel num_threads(n_threads)
  {
    int id = omp_get_thread_num();
    int b = id * chunk_size;
    int e = id == n_threads - 1 ? n : b + chunk_size;
    printf("thread %d: %d items\n", id, e - b);
    for (int i = b; i < e; i++) {
      // process item i
    }
  }

  return 0;
}

示例输出:

thread 0: 2500 items
thread 1: 2500 items
thread 3: 2503 items
thread 2: 2500 items

当心:策略“每个线程获得n / n_threads个项目,最后一个又一个”对于您给出的数字是合适的,但是在其他情况下,这可能导致工作共享效率非常低下。例如,对于60个项目和16个线程,此公式将为所有线程提供3个项目-除了最后一个项目(该项目将获得15个项目)。如果处理每个项目花费的时间大致相同,则这意味着整个过程所花费的时间将比所需时间长四倍,并且大多数CPU内核大部分时间都处于空闲状态。我认为,只有在有充分的理由需要完全按照这种方式分配作品时,才应使用此公式。否则,OpenMP选择的块大小可能会更好。