void deryabin_m_cannons_algorithm_mpi::CannonsAlgo...

Criado em: 12 de fevereiro de 2025

Respondido usando O1 por Chat01

Pergunta

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_
);
}
}
}
}
}
}

Разбей эту функции на две функции по логике

Pensamento

Analisando a função

Estou dividindo a função DistributeDataIfRoot() em duas partes distintas para esclarecer a lógica envolvida. Isso está me levando a uma compreensão mais clara e detalhada da função.

Distribuindo e enviando

Estou copiando blocos de matrizes de entrada locais e enviando dados para processos de destino usando MPI, tomando cuidado com as coordenadas e dimensões corretas.

Aprimorando a distribuição

Estou detalhando o envio de blocos de dados para processos de destino, garantindo coordenadas e dimensões corretas para input_matrix_A_ e input_matrix_B_.

Organizando o código

Estou pensando em dividir a função atual em duas partes: uma configura as matrizes locais para o processo raiz e outra distribui os subblocos para outros processos.

Separando funções

Estou fragmentando a função principal em InitializeLocalBlocks e SendBlocksToOtherProcs, organizando a lógica de dentro para fora e considerando funções menores para enviar blocos individuais.

Pensou por 14 segundos

Resposta

Ниже приведён пример того, как можно логически разбить исходную функцию на две:

  1. Копирование локальных блоков для корневого процесса (тот блок, который остаётся у процесса с rank=0).
  2. Отправка оставшихся блоков другим процессам.
cpp
void deryabin_m_cannons_algorithm_mpi::CannonsAlgorithmMPITaskParallel::DistributeDataIfRoot() { // Сначала копируем блоки матриц A и B для "корневого" процесса CopyLocalBlocksForRoot(); // Затем рассылаем оставшиеся блоки другим процессам SendBlocksToOtherProcesses(); } // 1. Копируем ту часть A и B, которая принадлежит корневому процессу void deryabin_m_cannons_algorithm_mpi::CannonsAlgorithmMPITaskParallel::CopyLocalBlocksForRoot() { for (unsigned short k = 0; k < block_dimension_; ++k) { // Копируем часть из A std::copy( input_matrix_A_.data() + (k * dimension_), input_matrix_A_.data() + (k * dimension_) + block_dimension_, local_input_matrix_A_.begin() + (k * block_dimension_) ); // Копируем часть из B std::copy( input_matrix_B_.data() + (k * dimension_), input_matrix_B_.data() + (k * dimension_) + block_dimension_, local_input_matrix_B_.begin() + (k * block_dimension_) ); } } // 2. Рассылаем остальные блоки другим процессам 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) { // Пропускаем (0,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 { 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_ ); } } } } } }

Краткие пояснения

  1. CopyLocalBlocksForRoot: Эта функция копирует фрагменты матриц A и B, которые принадлежат блоку (0,0)(0,0), то есть корневому процессу (обычно rank = 0).
  2. SendBlocksToOtherProcesses: Здесь происходит отправка соответствующих блоков остальным процессам.
    • Мы идём по всем блокам (i,j)(i, j).
    • Блок (0,0)(0,0) мы пропускаем, так как он уже локально скопирован (см. первый шаг).
    • Для каждого блока вычисляем destination_proc.
    • Выбираем нужный срез данных из A и B и отправляем его через world_.send().

Таким образом, логика распределения разбивается на две основные части и становится более наглядной и поддерживаемой.

Compartilhar esta Q&A