Пожалуйста, прости меня, если это глупый вопрос, но я не смог найти ни одного подобного вопроса.
Я хочу присвоить значение трехмерному динамическому массиву с параллельным 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 правильно?
Вам нужно объявить переменные цикла в параллельной области, лучше всего
#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;
Компилятор, скорее всего, встроит функцию, так что при вызове функции не будет никаких дополнительных затрат.
Попробуйте изменить прамгу на;
#pragma omp parallel for shared(data) private(i,j,k)
Однако, чтобы расширить мой комментарий, вы распараллеливаете большое количество потоков, но даете каждому из них небольшое количество работы, что означает, что затраты на их планирование будут очень большими по сравнению с фактическим преимуществом.
Кроме того, 2 * 2 * 2 * sizeof (int) может быть меньше, чем кешлайн в большинстве систем, это означает, что 2 потока, вероятно, будут пытаться записывать в одну и ту же строку одновременно, вызывая ложные конфликты и пинг-понг через кэши.