Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "mpi.h"
- #include <iostream>
- #include <time.h>
- #include <cmath>
- using namespace std;
- struct ProcessorData {
- int N, H;
- int rank, size;
- float *M;
- ProcessorData(int N1, int H1, int rank1, int size1): N(N1), H(H1), rank(rank1), size(size1) {
- // инициализируем рандом
- int stime = (unsigned int)time(NULL) / (rank + 1);
- srand(stime);
- // задаем случайную матрицу
- M = new int[H * N];
- for (int i = 0; i < H * N; i++)
- M[i] = rand();
- }
- void SwapMax() {
- int center;
- float max_above, max_below;
- float max_above_t, max_below_t;
- int max_above_row, max_below_row;
- // вычисление шлобального номера строки, чтобы понять где диагональный элемент
- center = H * rank;
- // начальные значения саксимумов
- max_above = M[0 + center + 1];
- if (rank != 0)
- max_below = M[0];
- else
- max_below = M[N];
- // номера строк (локальные), в которых лежат максимумы
- max_above_row = 0;
- max_below_row = 0;
- // поиск максимумов над и под диагональю
- for (int i = 0; i < H; i++) {
- for (int j = 0; j < center; j++)
- if (max_below <= M[i * N + j]) {
- max_below = M[i * N + j];
- max_below_row = i;
- }
- for (int j = center + 1; j < N; j++) {
- if (max_above <= M[i * N + j]) {
- max_above = M[i * N + j];
- max_above_row = i;
- }
- }
- center += 1;
- }
- // переход к глобальным номерам строк
- max_below_row += H * rank;
- max_above_row += H * rank;
- // поиск общих максимумов
- MPI_Allreduce(&max_below, &max_below_t, 1, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
- MPI_Allreduce(&max_above, &max_above_t, 1, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
- // если у данного процесса нет максимума, его макс строка "исключается"
- if (max_above < max_above_t)
- max_above_row = -1;
- if (max_below < max_below_t)
- max_below_row = -1;
- // поиск наибольших номеров строк, содержащих максимумы (на случай если максимумов несколько)
- MPI_Allreduce(MPI_IN_PLACE, &max_above_row, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
- MPI_Allreduce(MPI_IN_PLACE, &max_below_row, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
- if (max_above_row / H == max_below_row / H) { // оба максимума лежат среди строк, доступных одному процессу
- if (max_above_row != max_below_row) { // и при этом лежат в разных строках
- float tmp;
- max_above_row -= H * rank;
- max_below_row -= H * rank;
- for (int i = 0; i < N; i++) {
- tmp = M[max_above_row * N + i];
- M[max_above_row * N + i] = M[max_below_row * N + i];
- M[max_below_row * N + i] = tmp;
- }
- }
- }
- else { // максимумы лежат в областях доступа разных процессов
- int rank1 = max_above_row / H;
- int rank2 = max_above_row / H;
- float *sendbuf, *recvbuf;
- MPI_Status stat;
- if (rank == rank1) {
- sendbuf = new float[N];
- recvbuf = new float[N];
- // переход к локальным номерам строк
- max_above_row -= H * rank;
- // перенос нужной строки в буффер отправки
- for (int i = 0; i < N; i++)
- sendbuf[i] = M[max_above_row * N + i];
- // обмен с другим процессом
- MPI_Sendrecv(&sendbuf, N, MPI_FLOAT, rank2, 1, &recvbuf, MPI_FLOAT, rank2, 1, MPI_COMM_WORLD, &stat);
- // перенос строки из буффера приема в матрицу
- for (int i = 0; i < N; i++)
- M[max_above_row * N + i] = recvbuf[i];
- }
- else if (rank == rank2) { //здесь всё то же самое, но для второго процесса
- sendbuf = new float[N];
- recvbuf = new float[N];
- max_below_row -= H * rank;
- for (int i = 0; i < N; i++)
- sendbuf[i] = M[max_below_row * N + i];
- // здесь тот же обмен, но номера процессов идут в другом порядке, чтобы передача/прием шли в обратную сторону
- MPI_Sendrecv(&sendbuf, N, MPI_FLOAT, rank1, 1, &recvbuf, MPI_FLOAT, rank1, 1, MPI_COMM_WORLD, &stat);
- for (int i = 0; i < N; i++)
- M[max_below_row * N + i] = recvbuf[i];
- }
- }
- }
- };
- int main(int argc, char** argv) {
- int N, H;
- int rank, size;
- float *TM, *trecv;
- N = stoi(argv[1]);
- MPI_INIT(&argc, &argv);
- MPI_COMM_RANK(MPI_COMM_WORLD, &rank);
- MPI_COMM_SIZE(MPI_COMM_WORLD, &size);
- H = N / size;
- ProcessorData pd(N, H, rank, size);
- pd.SwapMax();
- TM = new float[N*N];
- MPI_Gather(pd.M, &TM, MPI_FLOAT, 0, MPI_COMM_WORLD);
- if (rank == 0) {
- // У нас есть матрица. Что с ней делать дальше никто не сказал.
- }
- MPI_Finalize();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement