Files
SSPR_25/tukhtarov_ilnur_lab_2/Mpi
2025-03-15 16:32:50 +04:00
..
2025-03-09 07:02:21 +04:00
2025-03-15 16:32:50 +04:00

Second lab work

Local setup

на контейнерах поставить java

apt install openjdk-11-jre-headless -y && apt install openjdk-11-jdk-headless -y

установка mpj

wget https://sourceforge.net/projects/mpjexpress/files/latest/download -O mpjexpress.tar.gz
tar xvf mpjexpress.tar.gz

поставить переменные среды MPJ_HOME и JAVA_HOME

nano /etc/environment
  • Создать файл machines, содержащий адреса контейнеров
  • Беспарольный вход по ssh, добавление адресов в /etc/hosts
  • Компилируем файл Main.java
    javac Main.java -cp mpj-v0_44/lib/mpj.jar
    
  • Запускаем daemons
    mpj-v0_44/bin/mpjboot machines
    
  • Запускаем проект
    mpj-v0_44/bin/mpjrun.sh -np 4 -dev niodev Main
    

Technologies used

  • java (programming language)
    • MPI - интерфейс для общения между процессами.

Project structure

\---src
        Main.java

Modules

Utils (in Main)

  • printMatrix(int[][] matrix) -> вывод матрицы
  • int[][] getMatrix(int n, int m) -> создание матрицы
  • getMinInCols(int totalCols, int[] localMatrix, int[] localMinCols) -> нахождение минимального элемента
  • getArrayByMatrix(int[] oneRowMatrix, int[][] fullMatrix) - создание одномерного массива из двумерного

Params (in Main)

  • ROWS - высота матрицы
  • COLS - ширина матрицы
  • RANDOM_NUMBER_BOUNDS - верхняя граница случайного числа

Code explanation

MPI.Init(args);
int rank = MPI.COMM_WORLD.Rank();
int size = MPI.COMM_WORLD.Size();

MPI инициализация MPI и получение номер текущего процесса, а так же их количества.

if (rank == 0) {
       ...
   MPI.COMM_WORLD.Scatterv(oneRowMatrix, 0, recvCounts, offset, MPI.INT,
           localMatrix, 0, totalCols * ROWS, MPI.INT, 0);
} else {
   MPI.COMM_WORLD.Scatterv(new int[0], 0, recvCounts, offset, MPI.INT,
           localMatrix, 0, totalCols * ROWS, MPI.INT, 0);
}

Основной узел распределяет колонки матрицы по кластерам. Другие узлы получают данные матрицы.

 int[] localMinCols = new int[totalCols];
 getMinInCols(totalCols, localMatrix, localMinCols);

Локальное получение минимума в колонках.

int[] gatherCounts = new int[size];
int[] gatherOffset = new int[size];

Размер данных и смещение.

MPI.COMM_WORLD.Gatherv(localMinCols, 0, totalCols, MPI.INT,
       allMinCols, 0, gatherCounts, gatherOffset, MPI.INT, 0);

Получение локально минимальных столбцов.

MPI.COMM_WORLD.Gatherv(localMatrix, 0, totalCols * ROWS, MPI.INT,
                      allMatrixData, 0, recvCounts, offset, MPI.INT, 0);

Получает данные со всех процессов.

int[][] fullMatrix = new int[ROWS][COLS];
for (int j = 0; j < COLS; j++) {
    for (int i = 0; i < ROWS; i++) {
        fullMatrix[i][j] = allMatrixData[j * ROWS + i];
    }
}

Integer[] idxes = IntStream.range(0, COLS)
        .boxed()
        .toArray(Integer[]::new);

Arrays.sort(idxes, (idx1, idx2) -> allMinCols[idx1] - allMinCols[idx2]);

int[][] sortedMatrix = new int[ROWS][COLS];
for (int j = 0; j < COLS; j++) {
    for (int i = 0; i < ROWS; i++) {
        sortedMatrix[i][j] = fullMatrix[i][idxes[j]];
    }
}

Сборка полной матрицы по завершении процессов по сортированным индексам.

MPI.Finalize();

Корректно завершает параллельную работу.

Tests

Время выполнения тестов на размере матрицы 5_000. Размер

  1. Starting process <0> on
    Starting process <1> on
    Starting process <2> on
    Starting process <3> on
    process on {0} started
    Base matrix generated
    Sorted matrix created
    It took 2 seconds and 63430000 nanos
    Stopping Process <3> on
    Stopping Process <2> on
    Stopping Process <1> on
    Stopping Process <0> on

  2. Starting process <1> on
    Starting process <0> on
    Starting process <2> on
    Starting process <3> on
    process on {0} started
    Base matrix generated
    Sorted matrix created
    It took 2 seconds and 157477000 nanos
    Stopping Process <1> on
    Stopping Process <3> on
    Stopping Process <2> on
    Stopping Process <0> on

  3. Starting process <1> on
    Starting process <0> on
    Starting process <2> on
    Starting process <3> on
    process on {0} started
    Base matrix generated
    Sorted matrix created
    It took 2 seconds and 125367000 nanos
    Stopping Process <3> on
    Stopping Process <2> on
    Stopping Process <0> on
    Stopping Process <1> on

Conclusion

Научился использовать MPI для распределения нагрузки между процессорами. Выяснил, что он используется в следующих задачах:

  • Снижение проблемы переносимости параллельных программ между разными компьютерными системами.
  • Повышение эффективности параллельных вычислений.
  • Уменьшение сложности разработки параллельных программ.