Научная статья на тему 'Проект системы рефакторинга, ориентированной на программы обработки разреженных матриц'

Проект системы рефакторинга, ориентированной на программы обработки разреженных матриц Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
116
41
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ПРЕОБРАЗОВАНИЕ ПРОГРАММ / РЕФАКТОРИНГ / РАЗРЕЖЕННЫЕ МАТРИЦЫ / PROGRAM TRANSFORMATION / REFACTORING / SPARSE MATRIX

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Симуни Михаил Лазаревич

Рассматривается проект системы рефакторинга, ориентированной на предметную область разработки разреженных матриц. Изучаются особенности программирования задач обработки разреженных матриц, влияющие на трудоемкость разработки. Предлагается подход, использующий технологию рефакторинга, оцениваются преимущества такого подхода и основные возможности проектируемой системы. Описываются проект реализации системы, ее основные подсистемы и их функциональность. Библиогр. 17 назв.

i Надоели баннеры? Вы всегда можете отключить рекламу.

Похожие темы научных работ по компьютерным и информационным наукам , автор научной работы — Симуни Михаил Лазаревич

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

Specifications of refactoring system for sparse matrix processing software

Program transformation and refactoring approaches to create sparse matrix processing software are considered. Specific features of the software development in this domain are studied. Benefits of the refactoring approach are studied. Functionality of the proposed refactoring tool is described. Design of the refactoring system, its organization and implementation are discussed.

Текст научной работы на тему «Проект системы рефакторинга, ориентированной на программы обработки разреженных матриц»

ВЕСТНИК САНКТ-ПЕТЕРБУРГСКОГО УНИВЕРСИТЕТА

Сер. 10. 2010. Вып. 2

УДК 004.4’23 М. Л. Симуни

ПРОЕКТ СИСТЕМЫ РЕФАКТОРИНГА, ОРИЕНТИРОВАННОЙ НА ПРОГРАММЫ ОБРАБОТКИ РАЗРЕЖЕННЫХ МАТРИЦ

Введение. В современных технологиях программирования широко используются средства преобразования программ. Среди наиболее важных можно назвать оптимизацию программ [1] и технологию рефакторинга [2]. В [3] приведен обзор других областей применения систем преобразования программ.

К важным видам систем преобразования программ относятся системы, использующие специфику предметной области. В статье рассматривается система преобразования программ обработки разреженных матриц (матриц, большинство элементов которых составляют нули [4]). Такие матрицы широко применяются в различных прикладных областях - от решения задач математической физики (метод конечных элементов) [5] до ранжирования сайтов [6].

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

Существует ряд инструментальных систем, позволяющих упростить разработку программ этого типа. Их обзор приведен в п. 2. При разработке программного комплекса инженерных расчетов ELCUT [5] был предложен новый подход к созданию инструментальной системы преобразования программ, использующий технологию рефакторинга. В п. 3 приводится обзор данного подхода, рассматриваются его преимущества по сравнению с существующими подходами и перечисляются основные возможности проектируемой инструментальной системы. В п. 4 описывается проект реализации системы.

1. Особенности программирования задач обработки разреженных матриц.

Рассмотрим некоторые особенности программирования задач обработки разреженных матриц.

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

Симуни Михаил Лазаревич — старший преподаватель кафедры информатики математикомеханического факультета Санкт-Петербургского государственного университета. Количество опубликованных работ: 3. Научные направления: преобразования программ, функциональное программирование, логическое программирование. E-mail: simuni@mail.ru.

© М. Л. Симуни, 2010

Наличие нескольких вариантов реализации, зависящих от порядка обхода матрицы. Большинство алгоритмов обработки матриц может быть реализовано разными способами в зависимости от порядка обхода элементов. Как правило, матрицу можно обрабатывать или по строкам, или по столбцам, или можно разбить ее на блоки и обрабатывать по блокам и т. д. В частности, для многих алгоритмов наиболее эффективным является их рекурсивный вариант, в котором блоки разбиваются на меньшие. Для выбора оптимального способа реализации важно иметь возможность легко переходить от одного варианта к другому.

Еще одна причина для перехода от одного варианта реализации алгоритма к другому связана с наличием большого количества форматов представления разреженных матриц. Наиболее распространены форматы хранения по рядам (Compressed Row Storage, CRS), по столбцам (Compressed Column Storage, CCS), по блокам (Block Compressed Row Storage, BCRS) [4]. Существуют и другие, более сложные форматы. В частности, в системе ELCUT используется специальная модификация блочного формата представления, при которой блоки организованы в иерархическую структуру. Для каждого формата существует свой набор эффективных способов доступа к элементам и соответственно, для того чтобы перейти от одного формата к другому, необходимо модифицировать программы для обработки матриц.

Наличие нескольких стандартных вариантов представления промежуточных данных. Эффективность операций с разреженными матрицами в значительной степени зависит от выбора формата хранения промежуточных данных. Существует достаточно стандартный набор способов представления данных. Например, векторы, полученные в ходе вычислений, как правило, хранят или в отсортированном сжатом формате, или в виде обычных плотных массивов, или с применением так называемых разреженных накопителей (sparse accumulators) [7]. Иногда наиболее эффективными являются более сложные структуры данных, например хеш-таблицы для быстрого доступа к элементам.

Необходимость реализации алгоритмов для ра,зличных типов элементов. Большинство алгоритмов обработки матриц должны быть реализованы для разных типов элементов (вещественных, комплексных, различной точности и др.). На языке С+—Н, для которого предполагается использовать проектируемую систему, это можно реализовать с помощью механизма шаблонов. Создание таких шаблонов для каждого алгоритма является хотя и несложным, но длительным рутинным процессом. Поддержка его со стороны инструментальной системы может упростить работу программиста.

2. Обзор существующих подходов. Рассмотрим существующие программные средства, предназначенные для помощи разработчику в решении указанных выше проблем.

Прежде всего отметим, что для плотных матриц многие из этих проблем могут быть решены автоматически. Существуют технологии оптимизации (унимодулярные преобразования, polyhedral transformation, tiling и др.), позволяющие автоматически генерировать высокоэффективный код [8]. К сожалению, большинство из таких технологий не может быть прямо применено к обработке разреженных матриц.

Наиболее распространенными инструментальными средствами являются специализированные библиотеки (например, [9]). Они обеспечивают очень эффективную реализацию, однако их использование ограничено фиксированным набором включенных в них алгоритмов. Кроме того, хотя в некоторых библиотеках есть возможность поддержки определяемых пользователем форматов хранения, но отсутствует возможность получения кода, специально оптимизированного для этих форматов. Таким образом,

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

В работе [10] описана система автоматической генерации программ для обработки разреженных матриц из программ для обработки плотных матриц. Она позволяет получить достаточно эффективные программы, однако имеет ограниченную функциональность и предназначена только для обработки матриц в формате СИБ.

Развивая этот подход, в работах [11,12] были предложены способы автоматической генерации программ для обработки разреженных матриц из высокоуровневых спецификаций с учетом информации о формате хранения данных. Описанные в этих работах системы позволяют быстро получить достаточно удовлетворительный код, но его производительность все же заметно уступает программам, написанным экспертами вруч-

нук>.

Другие интересные подходы приведены в работах [13] (применение аспектно-ориентированного программирования к задачам обработки разреженных матриц) и [14] (автоматический поиск оптимального сочетания преобразований из заданного пользователем набора возможных преобразований программы).

В работе [15] предлагается использовать для программирования высокопроизводительных вычислений технологию рефакторинга. В ней рассматриваются только простейшие преобразования программ.

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

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

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

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

• практический опыт разработки в рамках программного комплекса ELCUT показывает, что многие программисты, не имеющие навыков создания программ такого типа, испытывают трудности при выборе наиболее эффективных вариантов алгоритмов и представления данных. Это связано с тем, что приемы программирования, применяемые при реализации задач обработки матриц, во многом специфичны для указанной предметной области и требуют приобретения навыков работы с ними. Таким образом, разрабатываемая система может быть использована для более быстрого приобретения

новыми разработчиками навыков создания эффективного программного обеспечения для обработки матриц;

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

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

Выделение шаблона функции. Наиболее простым, но важным является метод «Выделение шаблона функции». Переход от функции к шаблону функции во многом аналогичен распространенному методу рефакторинга «Выделение метода» (Extract Method) [2]. Задача определения типов, которые должны быть преобразованы в параметры шаблонов, в общем случае довольно сложна. Однако для данной предметной области она значительно упрощается, поскольку заранее известно, какие типы могут быть параметрами шаблонов - это типы элементов массива, типы самих массивов и типы итераторов для доступа к ним.

Обмен циклов. Пользователь должен указать два вложенных цикла, которые он хочет поменять местами. Программа проверяет, возможно ли это и, если да, выясняет, какие преобразования необходимо сделать.

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

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

Еще одна возможность обработки сложных фрагментов программы применяется, если для преобразуемой функции имеются модульные тесты (unit tests). В этом случае, если полный анализ зависимостей невозможен, система пытается подобрать такое преобразование, при котором тесты по-прежнему выполнялись бы. Если оно найдено, пользователь должен интерактивно подтвердить его приемлемость.

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

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

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

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

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

Использование вспомогательной структуры данных. Для некоторых программ оказывается возможным провести статический анализ кода и обнаружить возможность использования одной из типично применяемых структур данных (плотных массивов, разреженных накопителей, хеш-таблиц). В такой ситуации пользователю предлагается выбор - перейти к применению одной из этих структур или оставить код без изменения.

4. Проект реализации системы. Система преобразования программ включает в себя подсистему синтаксического анализа, подсистему статического анализа кода, подсистему преобразования программ и подсистему пользовательского интерфейса.

Подсистема синтаксического анализа переводит код на языке С++ во внутреннее представление (абстрактное синтаксическое дерево) и сохраняет его в вспомогательном файле. Для анализа кода на С++ предполагается использовать библиотеку анализа кода ОрепС+—+. Известен ряд ограничений этой библиотеки [16]. В частности, она не обрабатывает некоторые новые конструкции языка. Но в рассматриваемом классе программ такие конструкции встречаются очень редко, поэтому данные ограничения не имеют существенного значения.

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

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

Подсистема статического анализа кода извлекает информацию о взаимосвязи операторов программы. Проводятся анализ зависимостей по управлению и по данным и анализ указателей [1]. Кроме этого, подсистема пытается распознать распространенные высокоуровневые конструкции (выполнение некоторой операции над всеми элементами строки или столбца, выполнение бинарной операции над соответствующими элементами двух строк или столбцов, вычисление операции свертки для всех элементов строки или столбца). Полученные результаты также запоминаются в вспомогательном файле. В нем же хранится дополнительная информация о взаимосвязи операторов, которую пользователь может задать интерактивно.

Работа подсистем синтаксического анализа и статического анализа кода выполняется в фоновом режиме параллельно с интерактивными операциями. При этом обрабатываются только те фрагменты кода, для которых анализ еще не проводился или которые были изменены после проведения анализа.

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

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

Заключение. В статье описан проект инструментальной системы для поддержки разработки высокопроизводительных программ, ориентированной на предметную область обработки разреженных матриц. Проект основывается на технологии рефакторинга, которая позволяет объединить возможности известных методов статического анализа и оптимизации программ с возможностями интерактивного задания необходимой информации о преобразованиях. В настоящее время система находится в стадии реализации. Предполагается ее использование при создании новой версии промышленной программы инженерных расчетов ELCUT.

Литература

1. Collard J.-F. Reasoning About Program Transformations. New York: Springer, 2002. 256 p.

2. Фаулер M. Рефакторинг. Улучшение существующего кода / пер. с англ. С. Маккавеева. СПб.: Символ-Плюс, 2008. 432 с.

3. Аветисян А. И., Иванников В. П., Гайсарян С. С. Анализ и трансформация программ // Всерос. конкурсный отбор обзорно-аналитических статей по приоритетному направлению «Информационнотелекоммуникационные системы». 2008. 78 с. URL: http://www.ict.edu.ru /ft/005642/62319e1-st06.pdf.

4. Писсанецки С. Технология разреженных матриц / пер. с англ. Х. Д. Икрамова, И. Е. Капорина; под ред. Х. Д. Икрамова. М.: Мир, 1988. 416 с.

5. Дубицкий C. Д. ELCUT 5.1 — платформа разработки приложений анализа полей // Exponenta Pro. Математика в приложениях. 2004. № 1(5). С. 20—26.

6. Brin S., PageL. The Anatomy of a Large-Scale Hypertextual Web Search Engine // Computer Networks and ISDN Systems. 1998. P. 107-117.

7. Gilbert J.R., MolerC., SchreiberR. Sparse Matrices in MATLAB: Design and Implementation // SIAM J. Matrix Anal. Appl. 1991. Vol. 13. P. 333-356.

8. Bastoul С. Code Generation in the Polyhedral Model Is Easier Than You Think // IEEE Intern. Conference on Parallel Architecture and Compilation Techniques. 2004. P. 7-16.

9. Duff I., Heroux M., Pozo R. An Overview of the Sparse Basic Linear Algebra Subprograms: The New Standard from the BLAS Technical Forum // ACM Transactions on Mathematical Software. 2002. Vol. 28, N 2. P. 239-267.

10. BikA. J. C., Brinkhaus P. J. H., Knijnenburg P. M. W., WijshoffH. A. G. The Automatic Generation of Sparse Primitives // ACM Transactions on Mathematical Software. 1998. Vol. 24. P. 190-225.

11. Kotlyar V., PingaliK., StodghillP. A Relational Approach to the Compilation of Sparse Matrix Programs // Proc. of EUROPAR. 1997. P. 318-327.

12. Ahmed N., MateevN., PingaliK., StodghillP. A Framework for Sparse Matrix Code Synthesis from High-level Specifications // Proc. of Supercomputing. 2000. P. 58-70.

13. IrwinJ., LoingtierJ.M., GilbertJ.R., KiczalesG. et al. Aspect-Oriented Programming of Sparse Matrix Code // Proc. Intern. Scientific Computing in Object-Oriented Parallel Environments (ISCOPE). 1997. P. 249-256.

14. HartonoA., NorrisB., Sadayappan P. Annotation-Based Empirical Performance Tuning Using Orio // IEEE Intern. Parallel and Distributed Processing Symposium (IPDPS). 2009. P. 1-11. URL: http://www.cse.ohio-state.edu/~hartonoa/papers/ipdps09.pdf.

15. Overbey J., Xanthos S., Johnson R., Foote B. Refactorings for Fortran and High-Performance Computing // Second Intern. Workshop on Software Engineering for High Performance Computing System Applications. 2005. P. 37-39.

16. Карпов А. Использование библиотеки анализа кода OpenCH—+: модификация, улучшение, исправление ошибок. 2008. URL: http://www.viva64.com/ru/articles/code-analyzers.

17. Garrido A., Johnson R. Challenges of Refactoring C Programs // IWPSE ’02: Proc. of the Intern. Workshop on Principles of Software Evolution. 2002. P. 6-14.

Статья рекомендована к печати проф. Л. А. Петросяном.

Статья принята к печати 24 декабря 2009 г.

i Надоели баннеры? Вы всегда можете отключить рекламу.