![]() |
||||||||||||||||||||||||||||||||||
![]() |
||||||||||||||||||||||||||||||||||
![]() |
Инженерная методика адаптации приложения к гибридному кластеру с ускорителями на ПЛИСЧасть 8. Думаем, как добиться ускорения.С. С. Андреев, С. А. Дбар, А. О. Лацис, Е. А. Плоткина
Формальная работоспособность полученного нами гибридно - параллельного приложения не означает, что в его нынешнем виде оно имеет хоть какой-нибудь разумный шанс выполняться быстро, скажем, быстрее, чем его программный прототип. Как ни грустно это звучит, но все, что мы делали с программой до сих пор, является не достижением ускорения как таковым, а только созданием возможностей для его достижения. Процессорную часть приложения мы, худо - бедно, изготовили. Кроме подбора подходящих значений PORTION и STW с ней, пожалуй, ничего существенного сделать уже нельзя. Теперь все наши усилия должны быть направлены на то, чтобы заставить транслятор C в VHDL изготовить схему как можно лучшего качества. Если бы мы не поленились описать схему сопроцессора в схемотехнических терминах, например, на языке Автокод Stream, или непосредственно на VHDL, мы знали бы совершенно точно, сколько тактов рабочей частоты потребуется этой схеме для обработки массива того или иного размера, а также - за счет чего, и как именно, это значение можно улучшить. Вопрос же о том, как это записать, чтобы транслятор нас "понял", не стоял бы вообще. По вполне понятной причине, мы от такой захватывающей перспективы уклонились, выбрали для описания схемы язык, известный и привычный нам, но не очень приспособленный для описания именно схем, и получив в результате схему совершенно неведомого качества. Чтобы это качество улучшить, нам предстоит, в известном смысле, решить обратную задачу: догадаться, что и как сказать компилятору, чтобы он сделал то, что нам нужно. Каким бы именно конкретным способом мы ни собирались транслятору это "говорить", ясно, что наши шансы на успех квадратично (или даже в более высокой степени) зависят от того, насколько хорошо мы понимаем, что именно нам нужно в действительности. То есть от нашего умения, хотя бы в общих чертах, "на пальцах", решать задачу прямую. Для начала неплохо было бы задуматься о том, откуда вообще берется ускорение расчетов при использовании вычислителей именно нетрадиционной архитектуры. Давно и безвозвратно ушли в прошлое те времена, когда более новый компьютер, приходя на смену морально устаревшему, обеспечивал ускорение более или менее любой программы просто за счет того, что был более новым и совершенным. В эти далекие времена быстродействие программ вычислительного характера определялось, в основном, скоростью выполнения арифметических операций над вещественными числами, а каждый более новый компьютер, как правило, выполнял их быстрее, чем более старый. Процессоры общего назначения практически достигли предела в скорости выполнения арифметических операций над вещественными числами без малого лет 10 назад. Подавляющее большинство вычислителей нетрадиционной архитектуры (а особенно - ускорители на ПЛИС) выполняют арифметические операции не быстрее, а гораздо медленнее, чем процессоры общего назначения. За счет чего же они ускоряют обработку данных, причем иногда - довольно сильно? Дело в том, что процессор общего назначения тратит львиную долю времени работы над программой вычислительного характера вовсе не на вычисления, а на перемещение данных внутри системы "процессор - память" (сюда включаются и операции по вычислению адресов, и взятие косвенностей, и вообще все "вспомогательные" действия, не являющиеся "полезными" арифметическими операциями). Любая нетрадиционная архитектура - это попытка многократно сократить объем такой работы по перемещению данных, тем или иным способом. Особенно велик потенциал экономии на перемещении данных у процессоров, реализующих аппаратно одну, конкретную вычислительную процедуру, как наши сопроцессоры на ПЛИС. За счет ориентации на конкретную вычислительную процедуру, такие сопроцессоры могут выстраивать арифметические устройства в цепочки, соответствующие структуре формул и циклов исходного алгоритма, и работающие в режиме конвейера. За счет прямого соединения арифметических устройств друг с другом, "лишняя" работа по перемещению данных в таком сопроцессоре сведена к минимуму. За счет конвейерного режима, при котором итоговая производительность конвейера мало зависит от времени выполнения каждой отдельной операции от начала до конца, арифметические устройства в конвейерах можно делать сравнительно медленными, но зато - в большом количестве. Наконец, чтобы без задержек "кормить" такие конвейеры исходными данными, и вовремя забирать с них результаты обработки, нужны десятки одновременно и независимо работающих устройств памяти, произвольным образом соединяемых с арифметическими устройствами при синтезе схемы. Большое количество одновременно и независимо работающих блоков оперативной памяти, пригодных для произвольного комбинирования с арифметическими устройствами, в ПЛИС присутствует, но их суммарный объем ограничен первыми мегабайтами. Возможность же произвольного комбинирования, как легко догадаться, ограничена пределами одной ПЛИС. Именно по этой причине, условием ускорения обработки в ПЛИС - сопроцессоре является нарезка обрабатываемых данных на мелкие блоки, которой мы уделили так много времени и сил в начале этого документа. Нарезка данных на мелкие блоки, как мы убедились выше, сопряжена с дополнительной коммуникационной работой по передаче данных между процессором и сопроцессором. Наша задача теперь состоит в том, чтобы сэкономить во много раз больше коммуникационной работы на микро-уровне, то есть внутри самого сопроцессора. Теперь, когда мы провели такую солидную подготовительную работу, нам осталось сделать совсем немного: "убедить" компилятор из C в VHDL построить по тексту функции, реализуемой в качестве сопроцессора, конвейер, по возможности - широкий, из нескольких "ниток". Средств "убеждения" у нас довольно мало: прагмы, в том числе, явно подсказывающие строить конвейер для того или иного цикла, и такая работа с массивами памяти, чтобы в один и тот же массив, по возможности, не требовалось лазить одновременно по разным адресам, поскольку при таком порядке доступа к данным конвейер у компилятора может не получиться. После всего сказанного, совершенно логично задать вопрос, наивный лишь на первый взгляд: если нам не удастся "уговорить" компилятор построить конвейер, что же он построит тогда, и с какой скоростью это "что" будет работать? Ответ столь же прост, сколь малоутешителен. Язык C недаром называется алгоритмическим. Он идеально приспособлен для записи алгоритмов. То есть вычислительных процедур, выполняющихся строго последовательно, шаг за шагом, включая в эту последовательность как арифметические операции, так и вспомогательные действия по вычислению адресов операндов. То есть работающих так, как работает ... процессор общего назначения. Поэтому, без дополнительных, и очень энергичных, усилий программиста, транслятор из C в VHDL, скорее всего, изготовит схему, хотя и не нуждающуюся в программе для своего функционирования, но, тем не менее, работающую, с точки зрения временной диаграммы, примерно так же, как работал бы процессор общего назначения, выполняя соответствующую программу. Схема эта имеет очень большие шансы унаследовать все недостатки и узкие места процессора общего назначения, и очень малые шансы его обогнать. Почти наверняка она будет работать медленнее, чем ядро процессора общего назначения, во столько раз, во сколько раз рабочая частота ПЛИС-сопроцессора ниже рабочей частоты процессора. То есть примерно в 20-25 раз. ◄ Часть 7 Часть 9 ► |
![]() |
||||||||||||||||||||||||||||||||
Тел. +7(499)220-79-72; E-mail: inform@kiam.ru |