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. Размер
-
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 -
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 -
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 для распределения нагрузки между процессорами. Выяснил, что он используется в следующих задачах:
- Снижение проблемы переносимости параллельных программ между разными компьютерными системами.
- Повышение эффективности параллельных вычислений.
- Уменьшение сложности разработки параллельных программ.