размышления о многоядерности

как человек, который непосредственно занимался параллелизацией кода, причём не для галочки, а с целью добиться максимально возможной производительности, поделюсь с вами некоторыми своими мыслями по этому поводу. <br/><br/>начнём с классики, с теории. пусть у нас есть некий нераспараллеленный код. ser - процент кода (по времени работы), который не поддаётся параллелизации, либо по алгоритму, либо по соображениям эффективности. на пример, ввод / вывод, работа с памятью и т.п. коэффициент eff(n) - максимально возможная эффективность параллелизации данного кода на n процессоров / ядер / нодов. он зависит, прежде всего, от самого кода (алгоритма) и от архитектуры параллельной системы, с увеличением n обычно уменьшается. <br/><br/>теперь можно написать формулу ускорения кода на параллельной системе....
31 октября 2007, среда 17:01
mrshurik для раздела Блоги
как человек, который непосредственно занимался параллелизацией кода, причём не для галочки, а с целью добиться максимально возможной производительности, поделюсь с вами некоторыми своими мыслями по этому поводу.

начнём с классики, с теории. пусть у нас есть некий нераспараллеленный код. ser - процент кода (по времени работы), который не поддаётся параллелизации, либо по алгоритму, либо по соображениям эффективности. на пример, ввод / вывод, работа с памятью и т.п. коэффициент eff(n) - максимально возможная эффективность параллелизации данного кода на n процессоров / ядер / нодов. он зависит, прежде всего, от самого кода (алгоритма) и от архитектуры параллельной системы, с увеличением n обычно уменьшается.

теперь можно написать формулу ускорения кода на параллельной системе.
speed(n)=1/[ser+{1-ser}/{eff(n)*n}]

предположим, ser=20%, а eff(n)=90%. это, вообще говоря, очень хороший для параллелизации случай. какое же ускорение мы получим на n=2, 4, 8?

n speed
2 1.55
4 2.37
8 3.21


ближе к практике, пусть eff(n)=90%-log2(n/2)*20%. т.е. при каждом удвоении n, начиная с 2, эффективность падает на 20%. что мы получим?

n eff speed
2 0.9 1.55
4 0.7 2.06
8 0.5 2.5


видно, что переход 4-8 почти не имеет смысла, учитывая повышенную цену системы, затраты на энергию. более того, при n>16 увеличение n замедляет код.

мораль

к чему я всё это пишу? многоядерность это не панацея. с какого-то момента она перестаёт приносить пользу, а даже наоборот, ухудшает так любимую некоторыми метрику производительность / ватт. и уж тем более, очень-очень глупо ожидать почти кратного ускорения, как обещают некоторые производители процессоров.

как же жить дальше? как ускорить программы? во-первых, не надо забывать другие пути увеличения производительности железа: кеш, память, шины данных, частота. да, да, незаслуженно забытая после P4 частота! она ведь даёт почти кратный прирост производительности. IBM помнит об этом и продолжает разрабатывать процессоры с малым числом ядер, но большой частотой.

во-вторых, если уж мы решили делать параллельный код, то очень важно добиться высокого коэффициента eff(n), который только возможен для данного алгоритма и железа. очень важно, чтобы он не сильно уменьшался с ростом n. для этого нужно оптимизировать и ещё раз оптимизировать код, т.е. тратить время и деньги на хороших программистов. хороший последовательный код на обычном компьютере будет работать быстрее, чем плохо распараллеленный на большой кластере. при этом производительность / ватт взлетит до небес.