OpenMP 并行计算循环索引
OpenMP parallel calculating for loop indices
我的并行编程 class 下面的程序演示了如何使用 OpenMP 中的并行构造来计算要在 for 循环中使用的每个线程的数组边界。
#pragma omp parallel
{
int id = omp_get_thread_num();
int p = omp_get_num_threads();
int start = (N * id) / p;
int end = (N * (id + 1)) / p;
if (id == p - 1) end = N;
for (i = start; i < end; i++)
{
A[i] = x * B[i];
}
}
我的问题是,if 语句 (id == p - 1) 是否必要?根据我的理解,如果 id = p - 1,那么 end 已经是 N,因此 if 语句不是必需的。我在 class 的问答板上提问,但未能得到我理解的正确答案。假设是:N 是数组的大小,x 只是一个 int,id 在 0 和 p - 1 之间。
你说得对。实际上,(N * ((p - 1) + 1)) / p
相当于
(N * p) / p
假设 p
是 严格正数 (这是因为 OpenMP 线程数保证至少为 1)。 (N * p) / p
等同于 N
假设没有 溢出 。当整数除法导致某些截断时,这种情况通常很有用,但这里不是这种情况(像 (N / p) * id
这样的情况)。
请注意,此代码对于大 N
不是很安全,因为 sizeof(int)
通常为 4,乘法可能会导致溢出(导致 未定义的行为).在超级计算机节点等具有许多内核的机器上尤其如此。最好使用 size_t
类型,它通常是无符号的 64 位类型,意味着能够表示任何对象的大小(例如数组的大小)。
我的并行编程 class 下面的程序演示了如何使用 OpenMP 中的并行构造来计算要在 for 循环中使用的每个线程的数组边界。
#pragma omp parallel
{
int id = omp_get_thread_num();
int p = omp_get_num_threads();
int start = (N * id) / p;
int end = (N * (id + 1)) / p;
if (id == p - 1) end = N;
for (i = start; i < end; i++)
{
A[i] = x * B[i];
}
}
我的问题是,if 语句 (id == p - 1) 是否必要?根据我的理解,如果 id = p - 1,那么 end 已经是 N,因此 if 语句不是必需的。我在 class 的问答板上提问,但未能得到我理解的正确答案。假设是:N 是数组的大小,x 只是一个 int,id 在 0 和 p - 1 之间。
你说得对。实际上,(N * ((p - 1) + 1)) / p
相当于
(N * p) / p
假设 p
是 严格正数 (这是因为 OpenMP 线程数保证至少为 1)。 (N * p) / p
等同于 N
假设没有 溢出 。当整数除法导致某些截断时,这种情况通常很有用,但这里不是这种情况(像 (N / p) * id
这样的情况)。
请注意,此代码对于大 N
不是很安全,因为 sizeof(int)
通常为 4,乘法可能会导致溢出(导致 未定义的行为).在超级计算机节点等具有许多内核的机器上尤其如此。最好使用 size_t
类型,它通常是无符号的 64 位类型,意味着能够表示任何对象的大小(例如数组的大小)。