void deryabin_m_cannons_algorithm_mpi::CannonsAlgo...
Criado em: 12 de fevereiro de 2025
Criado em: 12 de fevereiro de 2025
void deryabin_m_cannons_algorithm_mpi::CannonsAlgorithmMPITaskParallel::DistributeDataIfRoot()
{
for (unsigned short k = 0; k < block_dimension_; ++k) {
std::copy(
input_matrix_A_.data() + (k * dimension_),
input_matrix_A_.data() + (k * dimension_) + block_dimension_,
local_input_matrix_A_.begin() + (k * block_dimension_)
);
std::copy(
input_matrix_B_.data() + (k * dimension_),
input_matrix_B_.data() + (k * dimension_) + block_dimension_,
local_input_matrix_B_.begin() + (k * block_dimension_)
);
}
for (unsigned short i = 0; i < block_rows_columns_; ++i) {
for (unsigned short j = 0; j < block_rows_columns_; ++j) {
if (i == 0 && j == 0) {
continue;
}
for (unsigned short k = 0; k < block_dimension_; ++k) {
int destination_proc = (i * block_rows_columns_) + j;
if (i == 0) {
world_.send(
destination_proc,
0,
input_matrix_A_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_),
block_dimension_
);
} else {
if (static_cast<int>((i * block_rows_columns_) + j - i) < static_cast<int>(i * block_rows_columns_)) {
world_.send(
destination_proc + block_rows_columns_ - i,
0,
input_matrix_A_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_),
block_dimension_
);
} else {
world_.send(
destination_proc - i,
0,
input_matrix_A_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_),
block_dimension_
);
}
}
if (j == 0) {
world_.send(
destination_proc,
1,
input_matrix_B_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_),
block_dimension_
);
} else {
if ((static_cast<int>((i - j) * block_rows_columns_) + j) < 0) {
world_.send(
((i + block_rows_columns_ - j) * block_rows_columns_) + j,
1,
input_matrix_B_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_),
block_dimension_
);
} else {
world_.send(
((i - j) * block_rows_columns_) + j,
1,
input_matrix_B_.data() + (((i * block_dimension_) + k) * dimension_) + (j * block_dimension_),
block_dimension_
);
}
}
}
}
}
}
Разбей эту функцию на две более простых функции
Ниже приведён пример, как можно разбить исходную функцию на две более простых. Первая функция будет выполнять локальное копирование блоков для корневого процесса, а вторая — рассылать остальные блоки по другим процессам.
cppvoid deryabin_m_cannons_algorithm_mpi::CannonsAlgorithmMPITaskParallel::CopyLocalBlocks() { // Копируем локальный блок (0,0) для корневого процесса for (unsigned short k = 0; k < block_dimension_; ++k) { std::copy( input_matrix_A_.data() + (k * dimension_), input_matrix_A_.data() + (k * dimension_) + block_dimension_, local_input_matrix_A_.begin() + (k * block_dimension_) ); std::copy( input_matrix_B_.data() + (k * dimension_), input_matrix_B_.data() + (k * dimension_) + block_dimension_, local_input_matrix_B_.begin() + (k * block_dimension_) ); } } void deryabin_m_cannons_algorithm_mpi::CannonsAlgorithmMPITaskParallel::SendBlocksToOtherProcesses() { for (unsigned short i = 0; i < block_rows_columns_; ++i) { for (unsigned short j = 0; j < block_rows_columns_; ++j) { // Корневой блок (i=0, j=0) уже скопирован локально, поэтому пропускаем if (i == 0 && j == 0) { continue; } for (unsigned short k = 0; k < block_dimension_; ++k) { int destination_proc = (i * block_rows_columns_) + j; // Отправка блоков матрицы A if (i == 0) { world_.send( destination_proc, 0, input_matrix_A_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_), block_dimension_ ); } else { if (static_cast<int>((i * block_rows_columns_) + j - i) < static_cast<int>(i * block_rows_columns_)) { world_.send( destination_proc + block_rows_columns_ - i, 0, input_matrix_A_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_), block_dimension_ ); } else { world_.send( destination_proc - i, 0, input_matrix_A_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_), block_dimension_ ); } } // Отправка блоков матрицы B if (j == 0) { world_.send( destination_proc, 1, input_matrix_B_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_), block_dimension_ ); } else { // Вычисляем реальный целевой процесс для блоков B с учётом циклического сдвига if ((static_cast<int>((i - j) * block_rows_columns_) + j) < 0) { world_.send( ((i + block_rows_columns_ - j) * block_rows_columns_) + j, 1, input_matrix_B_.data() + ((i * block_dimension_ + k) * dimension_) + (j * block_dimension_), block_dimension_ ); } else { world_.send( ((i - j) * block_rows_columns_) + j, 1, input_matrix_B_.data() + (((i * block_dimension_) + k) * dimension_) + (j * block_dimension_), block_dimension_ ); } } } } } } void deryabin_m_cannons_algorithm_mpi::CannonsAlgorithmMPITaskParallel::DistributeDataIfRoot() { // Сначала копируем локальный блок для корневого процесса CopyLocalBlocks(); // Затем рассылаем остальные блоки остальным процессам SendBlocksToOtherProcesses(); }
CopyLocalBlocks
input_matrix_A_
и input_matrix_B_
в локальные буферы local_input_matrix_A_
и local_input_matrix_B_
.SendBlocksToOtherProcesses
(i, j)
, кроме (0, 0)
).DistributeDataIfRoot
Вы можете переименовывать функции так, как удобно для вашего проекта (например, InitializeLocalBlocks
, DistributeBlocks
, и т.д.). Главная идея — упростить чтение и поддержку кода путём разделения на более специализированные участки функционала.