# Лабораторная работа 8. Распределённые вычисления (MPI) **Время на работу:** 2–3 пары. **Зависимости:** лабы 1, 4. ## Цель работы Освоить модель передачи сообщений (MPI) — стандарт распределённых вычислений, на котором работают суперкомпьютеры. Понять отличие «общей памяти» (потоки/процессы Python) от «обмена сообщениями» между независимыми узлами. ## Теория ### Модель MPI MPI (Message Passing Interface) — набор программ на нескольких **узлах** (машинах или процессах), обменивающихся сообщениями. Нет общей памяти: любые данные передаются явно, функциями отправки/приёма. Программа запускается одновременно на N «рангах» (процессах): ```bat mpiexec -n 4 python script.py # 4 копии script.py ``` Каждая копия узнаёт, кто она: ```python from mpi4py import MPI comm = MPI.COMM_WORLD # «мир» — все ранги rank = comm.Get_rank() # мой номер: 0..size-1 size = comm.Get_size() # всего рангов ``` Ранг 0 обычно координатор: он делит работу и собирает результат. ### Операции: «точка-точка» и коллективные **Точка-точка** (ранг ↔ ранг): ```python comm.send(data, dest=1, tag=0) # блокирующая отправка data = comm.recv(source=0, tag=0) # блокирующий приём ``` **Коллективные** (все ранги сразу — проще и обычно быстрее): | Операция | Что делает | |---|---| | `bcast` | один раздает всем (broadcast) | | `scatter` | список режется на части: ранг i получает i-ю часть | | `gather` | части собираются в список на одном ранге | | `reduce` | части сворачиваются операцией (sum/max/…) на одном ранге | | `barrier` | все ждут, пока все дойдут до этой точки | ### Схема параллельной задачи в MPI ``` ранг 0: build -> split -> scatter ─┐ ранги 1..N: получают кусок │-> kernel -> gather -> combine -> checksum ранг 0: собирает ┘ ``` Это ровно ваша схема split→kernel→combine из лаб 1–4, только обмен данными — через сеть/IPC, а не общую память. ### Установка (Windows) 1. MS-MPI: скачать и установить **msmpisetup.exe** и **msmpires.msi** (https://www.microsoft.com/en-us/download/details.aspx?id=105289). 2. `pip install mpi4py` 3. Проверка: `mpiexec -n 2 python -c "from mpi4py import MPI; print(MPI.COMM_WORLD.Get_rank())"` На macOS/Linux: `brew install open-mpi` / `apt install libopenmpi-dev`, затем `pip install mpi4py`, запуск `mpiexec` (или `mpirun`). Важно: запускать `mpiexec -n 4` — тогда `solution.py` выполнится 4 раза параллельно. Запуск без mpiexec допустим: программа работает как один ранг (полезно для отладки и автотестов). ## Задание Заполните `solution.py`: 1. **`mpi_run(task_name, params)`** — параллельное выполнение вашей CPU-задачи: ранг 0 строит данные и делит на `size` кусков, `scatter` раздаёт, каждый ранг считает `kernel` (используя `dispatch_kernel` не нужно — в MPI функции не пиккелятся, только данные), `gather` собирает, ранг 0 возвращает checksum. Для задачи «Жизнь» — цикл по поколениям (см. подсказку в заготовке). 2. **`mpi_pi(N)`** — учебный пример: π методом Монте-Карло на всех рангах, сборка через `reduce` (сумма попаданий). Каждый ранг использует `random.Random(100 + rank)` — свои броски. 3. **`main()`** — checksum и время `mpi_run` на текущем числе рангов (`size`), печать с ранга 0. Запустите при `-n 1, 2, 4` — получите T(p). ### Ожидаемые результаты - checksum совпадает с последовательным запуском (лаба 1). - T(p) на одном компьютере ≈ результатам multiprocessing из лабы 4 (плюс небольшие расходы на обмен). - На настоящих нескольких машинах код не меняется — меняется только запуск (это главный смысл MPI). ### Измерения для отчёта ```bat mpiexec -n 1 python lab08_mpi\solution.py mpiexec -n 2 python lab08_mpi\solution.py mpiexec -n 4 python lab08_mpi\solution.py ``` ## Контрольные вопросы 1. Чем модель передачи сообщений отличается от модели общей памяти? 2. Что делает `scatter` и чем она отличается от `bcast`? 3. Почему в MPI функции не нужно пиккелить, а в multiprocessing — нужно? 4. Что такое ранг? Как ранг 0 узнаёт, сколько всего рангов? 5. Когда MPI выгоднее multiprocessing, даже на одном компьютере? ## Что сдаётся `solution.py` + отчёт: вывод при `-n 1/2/4`, таблица T(p), сравнение с лабой 4, ответы на вопросы. ## Критерии оценки | Пункт | Баллы | |---|---| | mpi_run: checksum корректен при -n 1 и -n 4 | 3 | | mpi_pi через reduce | 2 | | Замеры при разном числе рангов | 2 | | Отчёт и ответы на вопросы | 3 | ## Типичные ошибки - Код с веткой «если rank == 0» выполняется ВСЕМИ рангами — не заворачивайте всю программу в `if rank == 0`. - Разные random на разных рангах без фиксации зерна — невоспроизводимый результат. - Заблокированный `recv` без парной `send` — программа висит. Начинайте с коллективных операций, они безопаснее.