如何使用 C++ 和 OpenMP 并行计算数组的总和?
How to calculate the sum of an array in parallel using C++ and OpenMP?
我的任务是使用 C++ 和 OpenMP 并行化在我下面的代码中看到的数组的创建、加倍和求和。但是,我无法使总和正确地并行工作。这是我第一次使用 OpenMP,而且我对 C++ 也很陌生。我已经尝试了在下面的代码中可以看到的内容以及其他变体(在 for 循环之外有总和,并行定义一个总和以添加到全局总和,我已经尝试了建议 here, ETC)。总和 应该 是 4.15362e-14,但是当我使用多个线程时,每次都会得到不同的结果,这些结果是不正确的。实现这一目标的正确方法是什么?
P.S。到目前为止,我们只学到了关键、大师、障碍和单一结构,所以如果答案不包括任何其他结构,我将不胜感激。谢谢!
#include <iostream>
#include <cmath>
#include <omp.h>
using namespace std;
int main()
{
const int size = 256;
double* sinTable = new double[256];
double sum = 0.0;
// parallelized
#pragma omp parallel
{
for (int n = 0; n < size; n++)
{
sinTable[n] = std::sin(2 * M_PI * n / size); // calculate and insert element into array
sinTable[n] = sinTable[n] * 2; // double current element in array
#pragma omp critical
sum += sinTable[n]; // add element to total sum (one thread at a time)
}
}
// print sum and exit
cout << "Sum: " << sum << endl;
return 0;
}
不幸的是,您的代码不正确,因为您 运行 for 循环线程数而不是分配工作。你应该使用:
#pragma omp parallel for
在线程之间分配工作。
另一种选择是使用缩减:
int main()
{
const int size = 256;
const double step = (2.0 * M_PI) / static_cast<double>(size);
double* sinTable = new double[size];
double sum = 0.0;
// parallelized
#pragma omp parallel for reduction(+:sum)
for (int n = 0; n < size; n++)
{
sinTable[n] = std::sin( static_cast<double>(n) * step); // calculate and insert element into array
sinTable[n] = sinTable[n] * 2.0; // double current element in array
sum += sinTable[n]; // add element to total sum (one thread at a time)
}
// print sum and exit
cout << "Sum: " << sum << endl;
delete[] sinTable;
return 0;
}
请注意,理论上总和应为零。您获得的值取决于相加的顺序,因此可能会因四舍五入而略有不同。
size=256 sum(openmp)=2.84217e-14 sum(no openmp)= 4.15362e-14
size=512 sum(openmp)=5.68434e-14 sum(no openmp)= 5.68434e-14
size=1024 sum(openmp)=0 sum(no openmp)=-2.83332e-14
这里是link到CodeExplorer。
我的任务是使用 C++ 和 OpenMP 并行化在我下面的代码中看到的数组的创建、加倍和求和。但是,我无法使总和正确地并行工作。这是我第一次使用 OpenMP,而且我对 C++ 也很陌生。我已经尝试了在下面的代码中可以看到的内容以及其他变体(在 for 循环之外有总和,并行定义一个总和以添加到全局总和,我已经尝试了建议 here, ETC)。总和 应该 是 4.15362e-14,但是当我使用多个线程时,每次都会得到不同的结果,这些结果是不正确的。实现这一目标的正确方法是什么?
P.S。到目前为止,我们只学到了关键、大师、障碍和单一结构,所以如果答案不包括任何其他结构,我将不胜感激。谢谢!
#include <iostream>
#include <cmath>
#include <omp.h>
using namespace std;
int main()
{
const int size = 256;
double* sinTable = new double[256];
double sum = 0.0;
// parallelized
#pragma omp parallel
{
for (int n = 0; n < size; n++)
{
sinTable[n] = std::sin(2 * M_PI * n / size); // calculate and insert element into array
sinTable[n] = sinTable[n] * 2; // double current element in array
#pragma omp critical
sum += sinTable[n]; // add element to total sum (one thread at a time)
}
}
// print sum and exit
cout << "Sum: " << sum << endl;
return 0;
}
不幸的是,您的代码不正确,因为您 运行 for 循环线程数而不是分配工作。你应该使用:
#pragma omp parallel for
在线程之间分配工作。 另一种选择是使用缩减:
int main()
{
const int size = 256;
const double step = (2.0 * M_PI) / static_cast<double>(size);
double* sinTable = new double[size];
double sum = 0.0;
// parallelized
#pragma omp parallel for reduction(+:sum)
for (int n = 0; n < size; n++)
{
sinTable[n] = std::sin( static_cast<double>(n) * step); // calculate and insert element into array
sinTable[n] = sinTable[n] * 2.0; // double current element in array
sum += sinTable[n]; // add element to total sum (one thread at a time)
}
// print sum and exit
cout << "Sum: " << sum << endl;
delete[] sinTable;
return 0;
}
请注意,理论上总和应为零。您获得的值取决于相加的顺序,因此可能会因四舍五入而略有不同。
size=256 sum(openmp)=2.84217e-14 sum(no openmp)= 4.15362e-14
size=512 sum(openmp)=5.68434e-14 sum(no openmp)= 5.68434e-14
size=1024 sum(openmp)=0 sum(no openmp)=-2.83332e-14
这里是link到CodeExplorer。