Skip to content

Latest commit

 

History

History
88 lines (65 loc) · 5.87 KB

File metadata and controls

88 lines (65 loc) · 5.87 KB

Distributed Computing — максимально понятный README

Тут собраны небольшие учебные программы на MPI (много процессов, обмениваются сообщениями) и OpenMP (один процесс, много потоков).

Самое важное про MPI (очень просто)

Представьте, что вы запустили программу не один раз, а много одинаковых копий одновременно. Каждая копия — это процесс.

rank и size

  • size — сколько процессов всего (например, mpirun -np 4 ...size = 4).
  • rank — номер конкретного процесса: 0, 1, 2, ..., size-1.
  • Обычно rank = 0 делают “главным” (root): он формирует входные данные, собирает результат и печатает.

Что такое MPI_COMM_WORLD

Это “группа всех процессов”, которые вы запустили вместе. Почти все примеры работают именно в ней.

MPI-функции из ваших работ — что делают

MPI_Init(&argc, &argv)

Запуск MPI-среды. Без этого MPI не работает. Всегда в начале.

MPI_Comm_rank(MPI_COMM_WORLD, &rank)

Даёт текущему процессу его номер (rank). У каждого процесса свой.

MPI_Comm_size(MPI_COMM_WORLD, &size)

Говорит, сколько процессов в группе (size). Одинаково у всех.

MPI_Barrier(MPI_COMM_WORLD)

“Ждём друг друга”. Пока все процессы не дойдут до барьера — никто дальше не идёт. Зачем обычно нужно:

  • чтобы ровно начать замер времени
  • чтобы вывод не превращался в кашу

MPI_Send(...) и MPI_Recv(...)

Это “отправить сообщение” и “получить сообщение”.

Очень простая идея:

  • MPI_Send — процесс A отправляет массив данных процессу B.
  • MPI_Recv — процесс B ждёт и принимает эти данные в свой буфер.

Параметры, которые важно понимать:

  • destSend) — кому отправляем (rank получателя)
  • sourceRecv) — от кого ждём (rank отправителя)
  • tag — “ярлык” сообщения, чтобы не перепутать разные типы сообщений. Например, в одной программе можно пересылать несколько разных вещей — tag помогает отличать их.

Важно: если один процесс “ждёт” (Recv), а ему никто не отправляет — он будет ждать бесконечно.

MPI_Finalize()

Корректное завершение MPI. Всегда в конце.

Что делает код по лабораторным (по делу)

lab1 (MPI)

  • Пример с MPI_Alltoall: каждый процесс рассылает куски своего массива всем процессам и получает куски от всех.
  • Пример с MPI_Scatterv + MPI_Allgatherv:
    • root делит один большой вектор на куски (кусок может быть разной длины)
    • раздаёт куски всем процессам (Scatterv)
    • потом собирает исходный вектор на каждом процессе (Allgatherv)

В этих программах есть вспомогательные функции, которые специально делают упорядоченный вывод, чтобы строки от разных процессов не перемешивались.

lab2 (MPI)

MPI_Reduce с операцией MPI_PROD: каждый процесс имеет небольшой вектор, и root получает результат “поэлементно перемножить значения всех процессов”.

lab3 (MPI)

Сортировка столбцов матрицы:

  • root создаёт матрицу
  • каждый столбец “отдаётся” какому-то процессу (по правилу col % size)
  • процесс сортирует свой столбец и возвращает обратно
  • root собирает столбцы обратно в матрицу

lab4 (OpenMP)

Поиск максимума в векторе:

  • сначала считается максимум последовательно (для контроля)
  • потом параллельно с reduction(max: ...)
  • результаты сравниваются

lab5 (OpenMP)

Сортировка строк матрицы 70x90:

  • каждая строка сортируется независимо, значит можно распараллелить цикл по строкам
  • делается последовательный “эталон” и параллельный вариант, потом сравнение
  • дальше идёт интерактивный цикл: вводите номер строки и смотрите всю строку до/после сортировки

Сборка (кратко)

  • MPI: обычно mpic++ ... внутри папки лабораторной.
  • OpenMP на macOS: чаще всего нужен brew install libomp, затем сборка через clang++ -Xpreprocessor -fopenmp ... -lomp.