С MPI бесполезны пользовательские типы данных, когда есть непрерывный массив?
В моей программе я посылаю другим процессорам несколько строк Матрицы, я пишу код на C и знаю, что C является мажорной строкой. Матрица выделяется в виде 1d массива.
matrixInArrayB = malloc(height * width * sizeof(int));
matrixB = malloc(height * sizeof(int*));
for (int y = 0; y < height; y++) {
matrixB[y] = &matrixInArrayB[y * width];
}
Я отправляю их таким образом
MPI_Isend(&matrixB[0][0], width * height, MPI_INT, dest, tag,
MPI_COMM_WORLD, &requestesForB[k]);
Я сомневаюсь, что мне придется использовать какой-то тип данных ad-hoc для обеспечения соприкосновения строк, например:
int MPI_Type_contiguous(int count,
MPI_Datatype oldtype,
MPI_Datatype *newtype)
1 ответ
Нет, вам не нужно определять свои собственные типы данных, если вы не хотите. Однако при правильном использовании они могут быть очень полезны.
Допустим, у вас есть следующая структура для описания вашей матрицы, а не массив указателей на строки данных:
typedef struct {
int rows;
int cols;
ssize_t rowstep;
ssize_t colstep;
int *data;
} matrix;
где элемент данных в строке r
столбец c
матрицы m
является m.data[r*rowstep + c*colstep]
, В этом ответе я изложил еще лучшую версию этой структуры.
Затем вы можете использовать MPI_Type_create_hvector()
чтобы создать типы, соответствующие строке, столбцу или главной диагонали, этого конкретного типа матрицы (определенного размера и шага):
int n = (m.rows <= m.cols) ? m.rows : m.cols; /* min(m.rows, m.cols) */
MPI_Type_create_hvector(m.rows, 1, m.rowstep * sizeof m.data[0],
MPI_INT, &row_vector_type);
MPI_Type_create_hvector(m.cols, 1, m.colstep * sizeof m.data[0],
MPI_INT, &col_vector_type);
MPI_Type_create_hvector(n, 1, (m.rowstep + m.colstep) * sizeof m.data[0],
MPI_INT, &diag_vector_type);
Для ссылки на строку r
, ты используешь m.data + r*m.rowstep
,
Для ссылки на колонку c
, ты используешь m.data + c*m.colstep
,
Для ссылки на основную диагональ вы используете m.data
,
Поле размера всегда равно 1, потому что вы отправляете / получаете отдельные строки или столбцы.
Также возможно определить типы данных, соответствующие любой непрерывной прямоугольной части матрицы.
Затем библиотека MPI будет собирать данные при отправке и разбрасывать данные при получении. Фактические элементы данных не должны быть последовательными в памяти.
В приведенном выше примере можно использовать один и тот же код для отправки и получения любой строки, столбца или диагонального вектора. При использовании пользовательских типов данных нет необходимости различать их, кроме определения типов, как показано выше.
Упрощение кода приводит к получению более надежного кода с меньшим количеством ошибок. (Можно сказать, что ошибки бывают либо по типу "один за другим", т. Е. Трудно обнаруживаемыми, но не сложными, либо сложного типа, где различные аспекты кода взаимодействуют неожиданным или непреднамеренным образом, вызывая ошибку.)
Итак, я бы сказал, что определяемые пользователем типы данных MPI не бесполезны, даже когда данные находятся в непрерывном массиве, потому что они могут использоваться для упрощения кода и, следовательно, для повышения его надежности и простоты обслуживания.
Очевидно, что не весь код MPI хорошо использует пользовательские типы данных MPI. Использование пользовательских типов данных, когда это возможно, определенно не является решением.
Моя точка зрения заключается в том, что вы определяете полезность в каждом конкретном случае в зависимости от того, можете ли вы сделать код проще, легче для чтения и надежным или нет.