与 MPICH 相比,我试图用 OpenMP 来证明一个观点,我编写了以下示例来演示在 OpenMP 中实现高性能是多么容易。
Gauss-Seidel 迭代被分成两个独立的运行,这样在每次扫描中,每个操作都可以按任何顺序执行,并且每个任务之间应该没有依赖关系。所以理论上每个处理器都不应该等待另一个进程执行任何类型的同步。
我遇到的问题是,与问题大小无关,我发现只有 2 个处理器的加速很弱,如果有 2 个以上的处理器,它甚至可能会更慢。许多其他线性并行例程我可以获得非常好的缩放,但这一个很棘手。
我担心我无法向编译器“解释”我在数组上执行的操作是线程安全的,因此它无法真正有效。
请参见下面的示例。
任何人都知道如何使用 OpenMP 使其更有效?
void redBlackSmooth(std::vector<double> const & b,
std::vector<double> & x,
double h)
{
// Setup relevant constants.
double const invh2 = 1.0/(h*h);
double const h2 = (h*h);
int const N = static_cast<int>(x.size());
double sigma = 0;
// Setup some boundary conditions.
x[0] = 0.0;
x[N-1] = 0.0;
// Red sweep.
#pragma omp parallel for shared(b, x) private(sigma)
for (int i = 1; i < N-1; i+=2)
{
sigma = -invh2*(x[i-1] + x[i+1]);
x[i] = (h2/2.0)*(b[i] - sigma);
}
// Black sweep.
#pragma omp parallel for shared(b, x) private(sigma)
for (int i = 2; i < N-1; i+=2)
{
sigma = -invh2*(x[i-1] + x[i+1]);
x[i] = (h2/2.0)*(b[i] - sigma);
}
}
补充:我现在也尝试使用原始指针实现,它与使用 STL 容器具有相同的行为,因此可以排除它是来自 STL 的一些伪关键行为。