openMP静态调度中的CHUNKSIZE

标签 c multithreading parallel-processing openmp scheduling

假设我的代码的每次循环迭代都花费相同的时间。
请注意,每次循环迭代都涉及来自大型连续内存的不相交部分的内存访问。
我使用的是VS2019编译器。

我认为我是否使用应该不重要

#pragma omp for schedule(static, CHUNKSIZE)

或者

#pragma omp for schedule(static)

我使用了像 5 这样的值作为 CHUNKSIZE。 我问这个问题是因为我发现第一个变体的表现稍好一些。
有人可以提供一些线索吗?

最佳答案

如果不指定 block

#pragma omp for schedule(static)

OpenMP 将:

Divide the loop into equal-sized chunks or as equal as possible in the case where the number of loop iterations is not evenly divisible by the number of threads multiplied by the chunk size. By default, chunk size is loop_count/number_of_threads

因此,对于 CHUNKSIZE=52 个线程 和具有 22 迭代的循环(要并行化)。将向 thread ID=0 分配迭代 {0 到 10} 并分配给 thread ID=1 {11 to 21} 。每个线程都有 11 次迭代。但是,对于:

#pragma omp for schedule(static, CHUNKSIZE)

thread ID=0 将分配迭代 {0 到 4}{10 到 14}{ 20 到 21},而线程 ID=1 将使用迭代 {5 到 9}{15 到 19} >。因此,第一个和第二个线程分别被分配了 1210 迭代。

这一切都表明拥有

#pragma omp for schedule(static)

 #pragma omp for schedule(static, CHUNKSIZE)

不一样。不同的 block 大小可能会直接影响负载平衡和缓存未命中等。即使有一个:

Assume that each loop iteration of my code takes the same time

如果并行化循环的每次迭代都执行不同的工作,那么情况自然会变得更加复杂。例如:

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

正如您所见,在没有 block 的情况下,一个线程比另一个线程执行的 121 并行任务多,而使用 chunk=5 时,差异为减少到 51

总而言之,这取决于您的代码、执行该代码的硬件、您执行基准测试的方式、时间差有多大等等。底线是:您需要对其进行分析,查找潜在的负载平衡问题,测量缓存未命中等。分析始终是答案。

关于openMP静态调度中的CHUNKSIZE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65180820/

相关文章:

c++ - 指针转换字节顺序

c - 在linux中查看c中的头文件

无法理解读取系统调用的行为

java - 使用本地对象引用如何保证线程安全?

functional-programming - xappings, xectors, xets

c - 在 scanf() 之后,我如何 "delete"无用

c++ - 使用 Visual Studio Express 2013 为 C++ 代码创建独立的可执行文件

multithreading - 集成多线程测试以对服务器进行压力测试

java - java程序在多核机器上如何提高性能

java - Parallel Stream 与 Stream 的行为不同