Кто-нибудь может помочь с общим форматом для выравнивания трехмерного массива с использованием MPI? Я думаю, что я могу получить массив 1-мерный, просто используя (i + xlength * j + xlength * ylength * k), но тогда у меня возникают проблемы с использованием уравнений, которые ссылаются на конкретные ячейки массива.
Я пытался разбить код на куски, основываясь на том, сколько у меня процессоров, но потом, когда мне понадобилось значение, которое имел другой процессор, мне было трудно. Есть ли способ сделать это проще (и эффективнее), используя призрачные ячейки или манипулирование указателями?
У вас есть как минимум два варианта. Более простым является объявление макроса препроцессора, который скрывает сложность вычисления индекса, например:
#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
оператор.
Других решений пока нет …