OpenMP вложенный цикл с динамическим назначением массива

Пожалуйста, прости меня, если это глупый вопрос, но я не смог найти ни одного подобного вопроса.

Я хочу присвоить значение трехмерному динамическому массиву с параллельным OpenMP в первом цикле (в C ++).

int i, j, k;
int ***data;
const int NEL = 100;
const int NINT = 2;
data = new int**[NEL];
for (i = 0; i < NEL; i++) {
data[i] = new int*[NINT*NINT*NINT];
for (j = 0; j < NINT*NINT*NINT; j++) {
data[i][j] = new int[NINT*NINT*NINT];
}
}
#pragma omp parallel for
for (i = 0; i < NEL; i++) {
for (j = 0; j < NINT*NINT*NINT; j++) {
for (k = 0; k < NINT*NINT*NINT; k++) {
data[i][j][k] = 1;
}
}
}

Я только хочу, чтобы внешний цикл (i) выполнялся параллельно, а вложенные циклы (j и k) выполнялись последовательно. Но компилятор каждый раз выдает ошибку нарушения доступа.

Если я изменю динамический массив на локальный, он будет работать без проблем.

int i, j, k;
const int NINT = 2;
const int NEL = 100;
int data[NEL][NINT*NINT*NINT][NINT*NINT*NINT];
#pragma omp parallel for
for (i = 0; i < NEL; i++) {
for (j = 0; j < NINT*NINT*NINT; j++) {
for (k = 0; k < NINT*NINT*NINT; k++) {
data[i][j][k] = 123;
}
}
}

Я использую Visual Studio 2015 с включенной функцией OpenMP. Это потому, что версия OpenMP в VS 2015 только 2.0? Или я не использую динамический массив с OpenMP правильно?

0

Решение

Вам нужно объявить переменные цикла в параллельной области, лучше всего

 #pragma omp parallel for
for (int i = 0; i < NEL; i++) {
for (int j = 0; j < NINT*NINT*NINT; j++) {
for (int k = 0; k < NINT*NINT*NINT; k++) {
data[i][j][k] = 1;
}
}
}

в противном случае переменные цикла будут использоваться по умолчанию, что может привести к выходу за пределы data

В общем, здесь предпочтительнее использовать std::vector:

std::vector<std::vector<std::vector<int >  > > data;

И если вы выбираете производительность, вы хотите использовать постоянную память

std::vector<int> data;

а затем доступ data путем построения индекса на лету

data[k+pow(NINT,3)*j+pow(NINT,6)*i] = 1;

Лучше всего использовать небольшую функцию индексации, чтобы облегчить доступ к данным

int dataIndex(int i, int j, int k, int NINT){return k+pow(NINT,3)*j+pow(NINT,6)*i;}

а затем доступ data как

data[dataIndex(i,j,k,NINT)]=1;

Компилятор, скорее всего, встроит функцию, так что при вызове функции не будет никаких дополнительных затрат.

2

Другие решения

Попробуйте изменить прамгу на;

#pragma omp parallel for shared(data) private(i,j,k)

Однако, чтобы расширить мой комментарий, вы распараллеливаете большое количество потоков, но даете каждому из них небольшое количество работы, что означает, что затраты на их планирование будут очень большими по сравнению с фактическим преимуществом.

Кроме того, 2 * 2 * 2 * sizeof (int) может быть меньше, чем кешлайн в большинстве систем, это означает, что 2 потока, вероятно, будут пытаться записывать в одну и ту же строку одновременно, вызывая ложные конфликты и пинг-понг через кэши.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector