Init
This commit is contained in:
commit
c394677d07
59 files changed
+5149
No files matched your search
@@ -0,0 +1,140 @@
|
||||
# Лабораторная работа 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` — программа висит. Начинайте с
|
||||
коллективных операций, они безопаснее.
|
||||
Reference in new issue
Block a user