我有这段代码,但我需要帮助来使用 OpenMP
#pragma
s 来提高其速度。我想在变量 for
和 i
上并行化 j
循环。 n
和 m
的值也可以大得多。例如,n = 1000
、m = 500
。
我的代码:
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
matrix[i][j] = {static_cast<double>(distribution(gen)), static_cast<double>(distribution(gen))};
}
}
#pragma omp parallel
{
n = 50; m=50; ReS=0; ImS=0;
for(int nu = 0; nu < 1; nu++)
{
#pragma omp for num_threads(4)
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
double* matrixPtr = &matrix[i][j].first;
double* matrixPtrSecond = &matrix[i][j].second;
for (double theta = 0; theta < PI; theta += theta_plus)
{
for (double phi = 0; phi < 2 * PI; phi += theta_plus)
{
double angle = *matrixPtr * cos(phi) * sin(theta) + *matrixPtrSecond * sin(phi) * sin(theta);
ReS += cos(angle);
ImS += sin(angle);
}
}
}
}
}
}
那个
#pragma omp parallel
{
// ...
在您的原始代码中,导致整个关联块由团队线程的each并行执行。这似乎适得其反。至少,意图尚不清楚。
...
for(int nu = 0; nu < 1; nu++)
...循环无条件地执行一次迭代。这似乎毫无意义。
主要计算对共享变量
ReS
和ImS
执行频繁更新。这绝对是性能杀手,但该结构非常适合使用归约来解决该问题。
您说过(我认为)您想要并行化
i
和 j
上的循环。您提供的代码仅并行化其中的外部,但当然带有内部循环。循环结构与 (i,j)
对上的并行化兼容,而不是仅在 i
上并行化,所以我将在下面展示这一点,尽管我绝不确定这会产生很大的差异。
这可能适用于主循环:
#if 0
// Remove this
#pragma omp parallel
{
#endif
n = 50;
m = 50;
ReS = 0;
ImS = 0;
#pragma omp parallel for collapse(2) num_threads(4) reduction(+:ReS,ImS)
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
double *matrixPtr = &matrix[i][j].first;
double *matrixPtrSecond = &matrix[i][j].second;
for (double theta = 0; theta < PI; theta += theta_plus) {
for (double phi = 0; phi < 2 * PI; phi += theta_plus) {
double angle = *matrixPtr * cos(phi) * sin(theta)
+ *matrixPtrSecond * sin(phi) * sin(theta);
ReS += cos(angle);
ImS += sin(angle);
}
}
}
}
#if 0
}
#endif
也可能有机会大幅加快计算的串行版本,正如问题评论中所讨论的那样,但我在这里重点关注 OpenMP 指令的使用,这就是问题似乎要问的内容。