@mva Есть ещё одна вещь, которая мешает многопоточности — синхронизация. Она будет отъедать время, и даже не постоянное его количество, как в в законе Амдала, а возрастающее с числом потоков. Так что распараллеливание задачи на миллион потоков может занять даже больше времени, чем на десять (в законе Амдала этого не увидишь, там время в любом случае уменьшится при большем распарралеливании).
В идеальном случае время на синхронизацию будет расти логарифмически, в худшем — может линейно или даже ещё хуже, не знаю. Это даже не так влияет на закон Амдала, как на закон Густавсона-Барриса. Если его дополнить расходами на синхронизацию, то ситуация может стать печальной. Итак…
Пусть \(n\) — число процессоров, \(s\) — доля последовательно выполняемых операций, \(t\) — доля времени на синхронизацию \(e = 2,7...\) процессоров (это абстракция, число легко привести к времени на синхронизацию каждых 2, 3, 4 и т. п. процессоров), тогда доля времени на синхронизацию между \(n\) процессорами будет:
\[t_s = t\log n;\]
время на параллельные вычисления:
\[p = 1 - s - t\log n.\]
Как результат, итоговый объём вычислений:
\[S_n = n\left(1-s-t\log n\right) + s\].
Допустим что условные затраты на синхронизацию составляют 0,1, доля последовательных вычислений тоже 0,1. Тогда, например
n = 10 — Sn = 8,3
n = 100 — Sn = 72
n = 1000 — Sn = 605
n = 10 000 — Sn = 4895 (уже не так радужно, потеряли половину производительности)
n = 100 000 — Sn = 37 425
n = 1 000 000 — Sn = 259 225 (уже потеряли три четверти)
n = 10 000 000 — Sn = 1 440 952
n = 100 000 000 — Sn = 2 896 590 (всего 2,8% времени процессоры заняты делом!)
и ещё маленький шажочек…
n = 150 000 000 — Sn = 1 303 906 (производительность вообще упала!)
Не надо думать, что синхронизация это надуманная проблема — она включает в себя много всего: создание процесса, пересылку данных между процессорами, синхронный запуск, ожидание процессами других процессов, и в массивно-параллельных системах — те самые суперкомпьютеры, представляет отдельную проблему, решаемую кучей разных способов.
@iron_bug @mva Если мы говорим о результате, который зависит от всех данных, а не просто несколько независимых расчётов, синхронизировать всё равно придётся, просто в некоторых случаях это тривиально.
Хардварные баги в ПК-подобных системах от того, что проблему пытаются «замести под ковёр» железом, делая вид, что память между ядрами полностью синхронна. Попытка переложить синхронизацию на программистов вызовет их закономерный вой. Ведь общая память это так удобно! (sarcasm)
@iron_bug @mva Lockless это тоже вид синхронизации (т. е. синхронизация есть, ожиданий нет). Но опять же Lockless базируется на атомарных операциях, которые просто реализованы в железе (необходимый минимум — неделимый read-write общей памяти). Это то же самое заметание под ковёр — пользуемся общей памятью, надеемся, что это быстро и безглючно (на самом деле нет).
@iron_bug @mva Синхронизация памяти есть, если есть разделяемая память. Если разделяемой памяти нет, то синхронизации памяти нет. В своё время топовых DSP такое практиковалось, каждый проц имеет собственную память, а весь обмен через шустрые каналы связи точка-точка. Это предполагалось соединять в большую прямоугольную сетку.
к тому же, выяснилось, что процессоры делать толком не умеют, и попытки оптимизировать эту самую синхронизацию внутри архитектуры процессоров породили столько хардварных багов, что просто капец. и ккривые попытки их залатать или обойти с помощью нелепых софтовых изворотов сделали всё ещё намного хуже, чем оно было.