如果不指定块
#pragma omp for schedule(static)
OpenMP 将:
将循环分成大小相等的块或在
循环迭代次数不能被整除的情况
线程数乘以块大小。 默认情况下,块
大小为 loop_count/number_of_threads
因此,对于 CHUNKSIZE=5、2 threads 和带有 22 迭代的循环(要并行化)。 thread ID=0 将分配迭代 {0 to 10} 和 thread ID=1 {11 to 21}。每个线程都有11 迭代。但是,对于:
#pragma omp for schedule(static, CHUNKSIZE)
到thread ID=0 将分配迭代{0 to 4}、{10 to 14} 和{20 to 21},而thread ID=1 将使用迭代{5 to 9} 和{15 to 19}。因此,它分别被分配给第一个和第二个线程12 和10 迭代。
这一切都表明拥有
#pragma omp for schedule(static)
和
#pragma omp for schedule(static, CHUNKSIZE)
不一样。不同的块大小可能会直接影响loading balancing 和缓存未命中等。即使一个:
假设我的代码的每个循环迭代都花费相同的时间
如果被并行化的循环的每次迭代都在执行不同的工作,那么想法自然会变得更加复杂。例如:
for(int i = 0; i < 22; i++)
for(int j = i+1; j < 22 ; i++)
// do the same work.
有
#pragma omp for schedule(static)
Thread ID=0 将执行 176 迭代,而 Thread ID=1 55。负载不平衡为 176 - 55 = 121。
而
#pragma omp for schedule(static, CHUNKSIZE)
Thread ID=0 将执行 141 迭代和 Thread ID=1 90。负载不平衡为 141 - 90 = 51。
您可以在没有块的情况下看到,一个线程执行121 并行任务比另一个线程多,而使用chunk=5,差异减少到51。
总而言之,这取决于您的代码、执行代码的硬件、执行基准测试的方式、时间差有多大等等。底线是:您需要对其进行分析,寻找潜在的负载平衡问题,测量缓存未命中等。分析始终是答案。