我想知道一种在使用 C++ 的 OpenMP 中的并行 for 循环中获取给定线程的值范围的方法。例如,在下面的代码中,我想知道每个线程在每个线程的循环中使用的第一个值是什么。
#pragma omp parallel for schedule(static)
for(int i=0; i<n; i++)
让我举一个例子说明为什么我可能需要这些值。假设我想用计数的总和填充一个数组。计数之和的闭式解是n*(n+1)/2
。要使用 OpenMP 做到这一点,我可以这样做:
#pragma omp parallel for schedule(static)
for(int i=0; i<n; i++) {
a[i] = i*(i+1)/2;
}
但是,我怀疑获得计数总和的更快方法是不使用每次迭代的封闭形式解决方案(有一个正方形),而是记住每次迭代的总和,如下所示:
int cnt = 0;
for(int i=0; i<n; i++) {
cnt += i;
a[i] = cnt;
}
但我能想到的使用 OpenMP 执行此操作的唯一方法是明确定义范围值,如下所示:
#pragma omp parallel
{
const int ithread = omp_get_thread_num();
const int nthreads = omp_get_num_threads();
const int start = ithread*n/nthreads;
const int finish = (ithread+1)*n/nthreads;
int cnt = 0;
int offset = (start-1)*(start)/2;
for(int i=start; i<finish; i++) {
cnt += i;
a[i] = cnt + offset;
}
}
如果我可以从中获得起始值, #pragma omp parallel for schedule(static)
我就不必定义start, finish, ithread, and nthreads
.
编辑:阅读Agner Fog 的优化 C++手册后,我意识到我正在做的事情称为归纳。他给出了一个使用归纳法更有效地计算多项式值的例子。以下是他手册中的一些示例
没有感应:
// Example 8.23a. Loop to make table of polynomial
const double A = 1.1, B = 2.2, C = 3.3; // Polynomial coefficients
double Table[100]; // Table
int x; // Loop counter
for (x = 0; x < 100; x++) {
Table[x] = A*x*x + B*x + C; // Calculate polynomial
带感应:
// Example 8.23b. Calculate polynomial with induction variables
const double A = 1.1, B = 2.2, C = 3.3; // Polynomial coefficients
double Table[100]; // Table
int x; // Loop counter
const double A2 = A + A; // = 2*A
double Y = C; // = A*x*x + B*x + C
double Z = A + B; // = Delta Y
for (x = 0; x < 100; x++) {
Table[x] = Y; // Store result
Y += Z; // Update induction variable Y
Z += A2; // Update induction variable Z
}
要使用 OpenMP 执行此操作,我需要获取每个块的起始值。使用 OpenMP 执行此操作的唯一方法是手动定义块。