52 lines
2.4 KiB
Python
52 lines
2.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Демо: разбиение работы на куски не должно менять результат.
|
|
|
|
Запуск из корня курса:
|
|
python lab01_sequential/examples/02_split_check_demo.py
|
|
|
|
Ключевая идея курса: задача формулируется как split -> kernel -> combine ->
|
|
checksum. Разбиение — это подготовка к параллелизму: последовательный запуск
|
|
кусков обязан давать тот же checksum, что и один большой кусок.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
|
|
|
from common.tasks import TASKS, smoke_params
|
|
|
|
|
|
def run(task_name: str, parts: int):
|
|
"""Последовательный запуск задачи из `parts` кусков."""
|
|
task = TASKS[task_name]
|
|
params = smoke_params(task_name)
|
|
data = task["build"](params)
|
|
chunks = task["split"](data, parts)
|
|
partials = [task["kernel"](ch) for ch in chunks]
|
|
raw = task["combine"](partials)
|
|
return task["checksum"](raw)
|
|
|
|
|
|
def main():
|
|
print(f"{'задача':<12} {'parts=1':>18} {'parts=2':>18} {'parts=4':>18} совпадает")
|
|
for name in ("pi_mc", "integrate", "nqueens", "blur", "hashing"):
|
|
v1 = run(name, 1)
|
|
v2 = run(name, 2)
|
|
v4 = run(name, 4)
|
|
# float-результаты (π, интеграл) сравниваем с допуском: при разбиении
|
|
# меняется порядок суммирования, меняются последние биты мантиссы
|
|
def same(a, b):
|
|
if isinstance(a, float):
|
|
return abs(a - b) <= 1e-6 * max(1.0, abs(a))
|
|
return a == b
|
|
same12 = same(v1, v2)
|
|
same14 = same(v1, v4)
|
|
marker = "True" if (same12 and same14) else "False <-- ОШИБКА"
|
|
print(f"{name:<12} {v1:>18.6f} {v2:>18.6f} {v4:>18.6f} {marker}")
|
|
print("\nЕсли checksum зависит от разбиения — параллельная версия будет")
|
|
print("давать «случайный» результат. Это ошибка, а не особенность.")
|
|
print("(Float-задачи сравниваются с допуском — см. код демо.)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |