Журнал «Компьютерра» №44 от 29 ноября 2005 года - Компьютерра Журнал 619 11 стр.


Поэтому для защиты разделяемых между несколькими потоками переменных в параллельных программах вводятся специальные объекты синхронизации, которые позволяют заблокировать изменение того или иного объекта двумя потоками одновременно. Делается это примерно так: объект[Объект синхронизации, но вместе с ним - и весь объект (тот же наш игровой танк, например), который этот объект синхронизации защищает] отдается какому-то одному конкретному потоку, а другие желающие получить объект в пользование ставятся в очередь и ждут, пока нужный объект не освободится. Программисты, забывающие это сделать, как раз и наступают на те самые вторые грабли, обладающие пренеприятным свойством незаметно ломать программу. И ломать так, что она обрушивается не в момент «поломки», а минуты через три, когда «сомнительное место» давным-давно затерялось в пучинах кода, причем происходит это каждый раз в новом месте и в новое время.

Грабли третьи: если недостаточное количество объектов синхронизации - зло, ибо программист рискует заполучить время от времени глючащую программу, то переизбыток этих объектов - жуткие вериги на шее проекта. Пусть, скажем, практически любой из наших объектов может изменять игровую землю и стремится получить ее для себя. Поскольку принадлежать двум объектам одновременно земля не сможет, то находится она в каждый момент времени только у одного объекта. Который и будет обрабатываться, а всем остальным потокам придется терпеливо ожидать своей очереди. Получится вот такая картинка (рис. 3), где параллельными вычислениями и не пахнет. С этим успешно борются, беря блокировку ровно на то время, пока она действительно необходима (прочитать состояние земли, проверить его и записать новое состояние), но тогда возникают новые грабли - дедлоки. Предположим, что мы угодили снарядом в землю совсем рядышком от стоящего на ней танка. Пострадала и земля, и танк. Программа добросовестно определяет, что, где и как требуется изменить (поменять рельеф земли и изменить «жизни» у танка), берет первый объект синхронизации «на землю», тянется ко второму объекту синхронизации «на танк»… и тут же виснет. В чем дело? Оказывается, этот танк ждет, когда освободится земля, чтобы внести в нее свои изменения. И пока он земли не дождется, он не отдаст блокировку на самого себя, которая нужна потоку, который «держит» блокировку на ту самую землю. Считаете, что подобный дедлок - надуманная штука? Значит, вы никогда не занимались параллельным программированием: подобные ситуации здесь возникают если не на каждом шагу, то, по крайней мере, очень часто. Еще одна ситуация того же рода - один из потоков взял блокировку на что-то, но забыл освободить, а сторонний поток некстати решил это что-то проверить. Отсюда вытекает второе золотое правило «параллельного» программиста - никогда не пытаться обладать двумя объектами одновременно и тщательно проверять, что все однажды взятые объекты своевременно освобождаются.

Неплохой джентльменский набор, не правда ли? А сколько занятных вопросов связано с работой в «параллельном» режиме стандартных библиотек! К примеру, функция GetHostByAddr в стандартном программном интерфейсе Microsoft, активно использующаяся сетевыми программами, одно время грешила тем, что при ее повторных вызовах с разными адресами из разных потоков выдавала обоим потокам указатель на одну и ту же структуру данных, хотя запрашивали они совсем разное. И если производитель клятвенно заверяет вас, что его библиотека совсем-совсем, ну честно-честно является thread-safe[Безопасной для использования в параллельном режиме], - вспомните, что даже Microsoft нет-нет да и ошибается, модифицируя продукт с десятилетней историей. А о трудности отыскания подобных глюков красноречиво свидетельствует то, сколько потребовалось времени, чтобы GetHostByAddr выловить[Исправили его в Windows XP SP1. Сколько лет он жил никем не замеченный, одному богу известно].


Интерфейс MPI

Еще один стандарт де-факто в мире параллельных вычислений - пакет MPI (Message Passing Interface), тоже разрабатывавшийся как универсальное средство облегчения жизни разработчику параллельного ПО. Только устроено оно совсем иначе, нежели OpenMP, и ориентировано в основном для других, «более возвышенных» целей.

Идея MPI заключается в следующем. OpenMP (да и многие другие системы для разработки параллельного ПО) ориентируется на так называемые системы с общей памятью, когда на компьютере запущена всего одна программа (точнее, один процесс), но внутри этого процесса «живет» несколько потоков исполнения, каждому из которых доступна вся память процесса, а стало быть, и все его данные. MPI исходит из другой предпосылки: на компьютере запущено много-много программ (процессов), которые друг с другом напрямую общаться не могут и вынуждены устанавливать контакт через специальные окна или даже внешние каналы связи. Называется все это IPC (Inter-Process Communication) и, как вы уже, наверное, догадались, сильно изменяется от компьютера к компьютеру и от операционной системе к операционной системе. А MPI - попытка стандартизировать связь между процессами, предоставив всем желающим удобную модель запуска на нескольких процессорах тех программ, которые будут коллективно обрабатывать данные, и обеспечивая «почтовые пересылки» между этими программами. Вот и весь Message Passing Interface.

MPI универсален и всеяден. Он не накладывает практически никаких ограничений на приложение, на железо, на каналы, которые используются для связи между компьютерами. Можно в буквальном смысле слова поставить на стол две персоналки с MPI, соединить их Ethernet-кабелем - и кластер на два процессора, на котором можно запускать любое MPI-приложение, - готов! Потому-то этот интерфейс так и любят ученые, реализующие с его помощью программы для самых немыслимых суперкомпьютеров.

Впрочем, при желании можно использовать MPI и для обычных двухъядерных процессоров или двухпроцессорных систем - «вотчины» проектов OpenMP. Но, конечно, MPI для таких целей «тяжеловат», - как в плане быстроты исполнения программного кода, которому, в отличие от его OMP-коллег, приходится еще и оплачивать «накладные расходы» на канал связи, так и в плане высокой сложности разработки MPI-приложений. Последние, правда, лишены большинства тех «граблей», которые существуют для обычных систем с распределенной памятью; но зато для написания соответствующего кода от программиста требуется четкое мышление, позволяющее в деталях продумать систему обмена информацией между процессами.


Отладка параллельных приложений

Это отдельная песня. Я не говорю даже о том, что когда в программе запущен не один, а несколько потоков, то пошаговая отладка превращается в настоящий кошмар: контрольные точки «ловят» все треды подряд, а шаг одного потока запросто может сопровождаться полусотней шагов соседнего. Главная проблема в отладке параллельных приложений заключается в том, что возникающие там глюки уникальны. Зачастую они связаны со случайным совпадением каких-то событий в «жизни» слабо связанных друг с другом потоков, а потому проявляются, как говорится, в соответствии с текущей фазой луны, - возникнут раз-другой и бесследно исчезнут. Мало того, иногда присутствие «наблюдателя» (отладочных средств) изменяет результат измерений, поскольку слегка перестраивает «свойства окружающей среды», - вот и вылавливай после этого какой-нибудь плавающий глюк, обусловленный параллельностью.


***

Возможных решений тут всего три. Во-первых, средства, подобные OpenMP, заметно упрощают разработку «параллельных» программ, поскольку устраняют необходимость ручного задания объектов синхронизации. Правда, платить за это приходится еще более суженной функциональностью и производительностью (автоматика особой сообразительностью не отличается), так что изучить объекты синхронизации программисту не помешает. Второй способ - использование «по старинке» большого объема выводимой вручную отладочной информации. И, наконец, третий - использование специальных программ вроде Intel Thread Checker, не только наглядно и доступно отображающих в виде графика ход исполнения программы, но и способных в некоторых случаях находить распространенные ошибки начинающих.


Выводы

Как ни крути, за параллельными приложениями будущее, - а значит, пришла пора осваивать соответствующие приемы программирования и инструментарий. Компания Intel не только обещает завалить рынок недорогими многоядерными процессорами, но и предоставляет весь необходимый инструментарий для полноценного использования своих разработок. И судя по тому, что новейшие продукты Intel на процессорах AMD зачастую отказываются запускаться - AMD как платформе разработчиков вскоре придется неуютно.


Софтерра: Фотографическая чертовщина

Возможных решений тут всего три. Во-первых, средства, подобные OpenMP, заметно упрощают разработку «параллельных» программ, поскольку устраняют необходимость ручного задания объектов синхронизации. Правда, платить за это приходится еще более суженной функциональностью и производительностью (автоматика особой сообразительностью не отличается), так что изучить объекты синхронизации программисту не помешает. Второй способ - использование «по старинке» большого объема выводимой вручную отладочной информации. И, наконец, третий - использование специальных программ вроде Intel Thread Checker, не только наглядно и доступно отображающих в виде графика ход исполнения программы, но и способных в некоторых случаях находить распространенные ошибки начинающих.


Выводы

Как ни крути, за параллельными приложениями будущее, - а значит, пришла пора осваивать соответствующие приемы программирования и инструментарий. Компания Intel не только обещает завалить рынок недорогими многоядерными процессорами, но и предоставляет весь необходимый инструментарий для полноценного использования своих разработок. И судя по тому, что новейшие продукты Intel на процессорах AMD зачастую отказываются запускаться - AMD как платформе разработчиков вскоре придется неуютно.


Софтерра: Фотографическая чертовщина


В мире программного обеспечения популярны два диаметрально противоположных тезиса. Первый заключается в том, что весь софт должен быть свободным и распространяться с исходными текстами, что только открытый способ разработки приносит плоды, с аппетитом съедаемые конечными пользователями. Против этой идеи выступают некоторые руководители крупных софтверных компаний: они утверждают, что продукция компании должна оплачиваться «нормальным» способом - а именно коммерческой реализацией товара.

Конечно, каждый разработчик вправе сам выбирать модель распространения будущего продукта. Нам же интересно сравнить конечные результаты обоих подходов.


Чертенок с кисточкой в магазине фототоваров

Инструменты обработки цифровых изображений уже давно выпорхнули из умелых рук профессионалов и прочно обосновались на компьютерах пользователей, которых никто ни разу в жизни не называл «фотографами». Сегодня даже начинающим секретарям-референтам вменяется в обязанность обработка цифровых снимков и рассылка заказчикам. Что уж говорить о нас с вами… горе-специалистах.

Ситуацию усугубляет то, что популяризация цифрового фото привела к огромным продажам маленьких аппаратов с еле заметным глазком объектива, в народе называемых «мыльницами». Их использование можно свести к трем этапам: машинальное нажатие на кнопку спуска, укладка прически после увиденного снимка, обращение за помощью к компьютеру, чтобы как-то исправить отснятый материал. И в этот момент нашей последней соломинкой оказывается ПО для обработки цифровых изображений.

За долгие годы бесшабашного использования разнообразного софта россияне привыкли к тому, что программы бывают только бесплатные, но некоторые нехорошие разработчики зачем-то заставляют пользователей при установке вводить серийный код, созданный ближайшей программой keygen.exe. Однако не за горами тот день, когда в домашних ПК будет жить только лицензионный софт. А раз так, то пора подумать - хватит ли нам возможностей бесплатного ПО для обработки цифровых шедевров или все же придется раскошеливаться?

В связи с особенностями лицензирования ПО в нашей стране поистине народным средством обработки фотографий стал весьма недешевый Adobe Photoshop. Единственным редактором из лагеря бесплатного ПО, сравнимым с этим гигантом, является GIMP, распространяемый по свободной лицензии GPL. Логотип редактора - чертенок с кисточкой в зубах.

Разумеется, Photoshop мощнее. Но его преимущества сводятся к наличию функций, применяемых лишь профессионалами: любителям не понять прелестей преобразования RAW-файлов, работы с изображением в пространстве CMYK и прочих фотографических и полиграфических таинств. Зато масса других возможностей наверняка пригодится пользователям мыльниц.


Построение перед боем

Размер дистрибутива GIMP - 7,5 Мбайт. Установка программы в Windows требует наличия библиотеки GTK+, которая весит 3,6 Мбайт. При этом для нормальной работы в Windows XP «Чертенку» достаточно 128-256 Мбайт оперативной памяти. Интерфейс программы не вполне обычен, к нему нужно привыкнуть - например, правая кнопка мыши вызывает не контекстное меню, отвечающее текущему элементу, а главное, что позволяет быстро вызывать любые функции редактора.

GIMP обладает всеми атрибутами серьезного графического «комбайна»: он умеет работать со слоями, накладывать множество фильтров, а также поддерживает язык Script-Fu, с помощью которого можно сделать из нескольких функций одну новую и получить самые немыслимые результаты.

Adobe Photoshop - дорогой профессиональный инструмент, его дистрибутив занимает один CD. Редактор настойчиво требует хотя бы 512 Мбайт оперативной памяти для комфортной работы. Как средство редактирования фотографий, Photoshop, наверное, является самым мощным продуктом среди конкурентов. Остается решить, а не стреляем ли мы из пушки по воробьям, используя этого «монстра»?


Равноправие цветов

Снимки, получаемые в яркий солнечный день, чаше всего не нуждаются в коррекции цвета, но стоит только оказаться в помещении при свете обычных ламп накаливания, как автоматика наших фотоаппаратов начинает барахлить. Несильные завалы в тот или иной тон исправляются в Photoshop с помощью функции «Цветовой баланс». Обратите внимание, что вы можете менять цветовую гамму раздельно в трех диапазонах яркости - тенях, полутонах и бликах.

Другая возможная проблема - ошибки экспозиции. Если снимок получился «засвеченным» и в некоторых местах яркость такая, что все сливается в единый белый фон, то это уже «не лечится». Слишком темные снимки, напротив, поддаются исправлению. Для корректировки экспозиции следует воспользоваться инструментом «Уровни», с помощью которого вы можете не только установить нужные параметры яркости для снимка, но и окончательно выправить баланс цвета.

Нажатие кнопки «Авто» позволит редактору настроить всю группу параметров по своему усмотрению. Если вас не устраивает работа «автоматики» - добро пожаловать в ручную правку уровней. Выбор черной и белой точек позволяет скорректировать изображение так, чтобы равномерно задействовать на снимке весь диапазон яркости, а с помощью серой можно построить всю цветовую гамму без перекосов в сторону того или иного канала.

Аналогичные функции присутствуют и в GIMP, однако меньшее внимание уделяется «автоматике». В меню «Инструменты цвета» нет ни одного пункта, который бы помог автоматически скорректировать изображение, хотя заветная кнопка «Авто» доступна из окошка «Уровней».

Все инструменты обработки цвета у обоих редакторов лежат в меню второй степени вложенности, что несколько замедляет скорость работы пользователя.

В общем, оба редактора заслуживают одинаковую оценку по предмету «манипуляции с цветом».


Шуметь неприлично

Если при съемке использовалось высокое значение ISO, фотография получается зернистой. Этот недостаток отчасти устраняется с помощью гауссова размытия, которое есть у обоих редакторов. Однако не всегда разумно накладывать фильтр сразу на все фото: например, при портретной съемке желательно, чтобы кожа была «размыта» больше, чем волосы и одежда. Чтобы достичь нужного результата, приходится обращаться к функциям выделения произвольных областей изображения - здесь-то и проявляются различия программ.

В Photoshop есть три инструмента для подобных целей. Принцип работы «Лассо» всем известен: вы удерживаете левую кнопку мыши и рисуете на изображении нужный контур. Отпускаете кнопку - контур автоматически замыкается и превращается в выделение. Второй инструмент, «Прямолинейное лассо», отличается тем, что граница выделения составляется из прямых отрезков, а третий, «Магнитное лассо», даже не требует удерживания левой кнопки мыши: достаточно приблизительно обводить нужный контур, а редактор уже сам определит, как прокладывать «маршрут» и в каких местах расставлять точки фиксации. Впрочем, последнее можно делать и вручную.

GIMP обладает аналогами как обычного «лассо», так и магнитного[На самом деле, используя понятия «контура» (path), можно выделять и многоугольники - правда, делать это не так удобно, как в Photoshop. - И.Щ], и если первое работает в обоих редакторах одинаково, то второе ведет себя иначе: вы указываете последовательность точек, между которыми алгоритм редактора рисует кривые, максимально приближаясь к резким переходам цвета.

Назад Дальше