Первый метод (распараллелить внутренний цикл):
for(j=0; j<LATTICE_VW; ++j) {
x = j*DX + LATTICE_W;
#pragma omp parallel for ordered private(y, prob)
for(i=0; i<LATTICE_VH; ++i) {
y = i*DY + LATTICE_S;
prob = psi[i][j].norm();
#pragma omp ordered
out << x << " " << y << " " << prob << endl;
}
}
Второй метод (распараллелить внешний цикл):
#pragma omp parallel for ordered private(x, y, prob)
for(j=0; j<LATTICE_VW; ++j) {
x = j*DX + LATTICE_W;
for(i=0; i<LATTICE_VH; ++i) {
y = i*DY + LATTICE_S;
prob = psi[i][j].norm();
#pragma omp ordered
out << x << " " << y << " " << prob << endl;
}
}
Третий метод (распараллелить свернутые циклы)
#pragma omp parallel for collapse(2) ordered private(x, y, prob)
for(j=0; j<LATTICE_VW; ++j) {
for(i=0; i<LATTICE_VH; ++i) {
x = j*DX + LATTICE_W;
y = i*DY + LATTICE_S;
prob = psi[i][j].norm();
#pragma omp ordered
out << x << " " << y << " " << prob << endl;
}
}
Если бы я собирался угадать, я бы сказал, что метод 3 должен быть самым быстрым.
Однако способ 1 является самым быстрым, в то время как второй и третий занимают примерно одинаковое количество времени, как если бы не было распараллеливания. Почему это происходит?
Посмотри с этим:
for(int x = 0; x < 4; ++x)
#pragma omp parallel for ordered
for(int y = 0; y < 4; ++y)
#pragma omp ordered
cout << x << ',' << y << " (by thread " << omp_get_thread_num() << ')' << endl;
у тебя есть:
0,0 (by thread 0)
0,1 (by thread 1)
0,2 (by thread 2)
0,3 (by thread 3)
1,0 (by thread 0)
1,1 (by thread 1)
1,2 (by thread 2)
1,3 (by thread 3)
Каждый поток просто должен подождать cout
всю работу можно выполнить параллельно.
Но с:
#pragma omp parallel for ordered
for(int x = 0; x < 4; ++x)
for(int y = 0; y < 4; ++y)
#pragma omp ordered
cout << x << ',' << y << " (by thread " << omp_get_thread_num() << ')' << endl;
а также
#pragma omp parallel for collapse(2) ordered
for(int x = 0; x < 4; ++x)
for(int y = 0; y < 4; ++y)
#pragma omp ordered
cout << x << ',' << y << " (by thread " << omp_get_thread_num() << ')' << endl;
ситуации это:
0,0 (by thread 0)
0,1 (by thread 0)
0,2 (by thread 0)
0,3 (by thread 0)
1,0 (by thread 1)
1,1 (by thread 1)
1,2 (by thread 1)
1,3 (by thread 1)
2,0 (by thread 2)
2,1 (by thread 2)
2,2 (by thread 2)
2,3 (by thread 2)
3,0 (by thread 3)
3,1 (by thread 3)
3,2 (by thread 3)
3,3 (by thread 3)
Так thread 1
должен ждать thread 0
закончить всю свою работу, прежде чем он сможет cout
в первый раз, и почти ничего нельзя сделать параллельно.
Попробуйте добавить schedule(static,1)
до коллапс-версии, и она должна работать по крайней мере так же хорошо, как и первая версия.
Других решений пока нет …