Метрики: ускорение, эффективность, масштабируемость

Урок вводит численные меры того, насколько хорошо алгоритм использует много процессоров.

Ускорение (speedup) S(p) = T(1) / T(p) — во сколько раз p процессоров справились быстрее одного.

Ускорение

Базовая метрика. Если на одном ядре задача шла 100 секунд, а на четырёх — 25, ускорение равно 4. Идеальное (линейное) ускорение S(p) = p достигается редко: накладные расходы на координацию и неустранимая последовательная часть мешают. Иногда наблюдают сверхлинейное ускорение (S(p) > p) — обычно из-за того, что на нескольких ядрах данные целиком влезают в кэши, чего не было на одном.

Эффективность

Эффективность E(p) = S(p) / p показывает, какую долю мощности процессоров вы реально используете. Если 4 ядра дали ускорение 3, эффективность 0.75 — каждое ядро занято на 75%. Эффективность ближе к 1 означает, что параллелизм почти не теряется впустую. Падение эффективности с ростом p — нормальное явление: чем больше ядер, тем больше тратится на коммуникацию.

# измеряем ускорение и эффективность по замерам времени
T1 = 100.0          # время на 1 ядре
times = {1: 100.0, 2: 52.0, 4: 28.0, 8: 16.0}

print(f"{'p':>3} {'T(p)':>7} {'speedup':>8} {'eff':>6}")
for p, tp in times.items():
    speedup = T1 / tp
    eff = speedup / p
    print(f"{p:>3} {tp:>7.1f} {speedup:>8.2f} {eff:>6.2f}")

Вывод:

  p    T(p)  speedup    eff
  1   100.0     1.00   1.00
  2    52.0     1.92   0.96
  4    28.0     3.57   0.89
  8    16.0     6.25   0.78

Видно типичную картину: ускорение растёт, но эффективность медленно падает — на 8 ядрах мы используем уже только 78% потенциала.

Почему вообще важно различать ускорение и эффективность? Потому что они отвечают на разные вопросы бизнеса. Ускорение говорит «насколько быстрее стало» — это интересно пользователю, который ждёт результат. Эффективность говорит «насколько окупились ядра» — это интересно тому, кто платит за них. Можно получить ускорение 50× на ста ядрах, но эффективность 0.5 означает, что половину дорогих ядер вы топите впустую; иногда выгоднее взять меньше ядер и эффективность повыше. Поэтому при выборе конфигурации смотрят на обе метрики сразу, а не на одну.

Масштабируемость: сильная и слабая

Сильная масштабируемость (strong scaling): фиксируем размер задачи и добавляем процессоры. Хорошо масштабируется — значит, время продолжает падать. Здесь правит закон Амдала: последовательная часть рано или поздно становится потолком.

Слабая масштабируемость (weak scaling): увеличиваем размер задачи пропорционально числу процессоров (на каждое ядро — фиксированная порция работы). Хорошо масштабируется — значит, время держится почти постоянным, сколько бы ядер вы ни добавили. Здесь правит закон Густафсона. Для «больших данных» слабое масштабирование часто важнее: мы не ускоряем фиксированную задачу, а решаем всё большие задачи за то же время.

Как работает под капотом

Метрики — это не свойство алгоритма в вакууме, а результат измерения на конкретной машине. Один и тот же алгоритм покажет разное ускорение на CPU с быстрой общей памятью и на кластере с медленной сетью. Поэтому всегда указывают, что измерялось: какой размер задачи, какое железо, какая базовая последовательная версия. Особенно коварен выбор T(1): если сравнивать с нарочно плохой однопоточной реализацией, ускорение будет завышенным.

Частые ошибки

  • Сравнивать параллельную версию с медленной, неоптимизированной последовательной — это раздувает мнимое ускорение.
  • Ожидать роста ускорения без предела: на фиксированной задаче оно упирается в потолок Амдала.
  • Путать сильное и слабое масштабирование — это разные вопросы и разные законы.

Итоги

  • Speedup = T(1)/T(p); эффективность = speedup/p (доля используемой мощности).
  • Сильное масштабирование — фиксированная задача, больше ядер; слабое — задача растёт вместе с ядрами.
  • Метрики зависят от железа и от честности выбора базовой версии.
Проверьте себя
1. Как считается ускорение (speedup)?
AT(p) / T(1)
BT(1) / T(p)
Cp / T(p)
DT(1) * p
2. Что показывает эффективность E(p) = S(p)/p?
AРазмер задачи
BДолю мощности процессоров, которая реально используется
CКоличество гонок данных
DОбъём памяти
3. Чем слабое масштабирование отличается от сильного?
AНичем
BПри слабом размер задачи растёт пропорционально числу процессоров
CСильное всегда лучше
DСлабое работает только на GPU