параллельная обработка — выравнивание трехмерного массива в c ++ для использования с MPI

Кто-нибудь может помочь с общим форматом для выравнивания трехмерного массива с использованием MPI? Я думаю, что я могу получить массив 1-мерный, просто используя (i + xlength * j + xlength * ylength * k), но тогда у меня возникают проблемы с использованием уравнений, которые ссылаются на конкретные ячейки массива.

Я пытался разбить код на куски, основываясь на том, сколько у меня процессоров, но потом, когда мне понадобилось значение, которое имел другой процессор, мне было трудно. Есть ли способ сделать это проще (и эффективнее), используя призрачные ячейки или манипулирование указателями?

0

Решение

У вас есть как минимум два варианта. Более простым является объявление макроса препроцессора, который скрывает сложность вычисления индекса, например:

#define ARR(A,i,j,k) A[(i)*ylength*zlength+(j)*zlength+(k)]

ARR(myarray,i,j,k) = ARR(myarray,i+1,j,k) + ARR(myarray,i,j+1,k) + ...

Это неуклюже, поскольку макрос будет работать только с массивами с фиксированными начальными размерами, например, все, что х ylength Икс zlength,

Намного лучший способ сделать это — использовать так называемые допинговые векторы. Допинговые векторы — это в основном индексы в большом массиве. Вы выделяете один большой плоский кусок размером xlength * ylength * zlength сохранить фактические данные и затем создать индексный вектор (фактически дерево в трехмерном случае). В вашем случае индекс имеет два уровня:

  • верхний уровень, состоящий из xlength указатели на
  • второй уровень, состоящий из xlength массивы указателей, каждый из которых содержит ylength указатели на начало блока zlength элементы в памяти.

Давайте назовем массив указателей верхнего уровня A, затем A[i] это указатель на массив указателей, который описывает i-я плита данных. A[i][j] это j-ый элемент iмассив указателей, который указывает на data[i][j][0] (если data был 3D массив). Конструкция вектора допинга работает примерно так:

double *data = new double[xlength*ylength*zlength];
double ***A;

A = new double**[xlength];
for (int i = 0; i < xlength; i++)
{
A[i] = new double*[ylength];
for (int j = 0; j < ylength; j++)
A[i][j] = data + i*ylength*zlength + j*zlength;
}

Допинговые векторы так же просты в использовании, как и обычные массивы, с некоторыми особыми соображениями. Например, A[i][j][k] даст вам доступ к нужному элементу data, Одно предупреждение о допинг-векторах состоит в том, что верхний уровень состоит из указателей на другие таблицы указателей, а не из указателей на сами данные, поэтому A не может использоваться в качестве ярлыка для &A[0][0][0]ни A[i] используется в качестве ярлыка для &A[i][0][0], Еще A[i][j] эквивалентно &A[i][j][0], Другое предостережение заключается в том, что эта форма индексации массивов медленнее, чем обычная индексация трехмерных массивов, поскольку она включает в себя отслеживание указателя.

Некоторые люди, как правило, выделяют один блок хранения как для данных, так и для допинговых векторов. Они просто помещают индекс в начало выделенного блока, а фактические данные идут после этого. Преимущество этого метода заключается в том, что удаление массива так же просто, как удаление всего блока памяти, в то время как удаление допинговых векторов, созданных с помощью кода из предыдущего раздела, требует многократных вызовов free оператор.

2

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

Других решений пока нет …

По вопросам рекламы [email protected]