Требуется обновление браузера.

Повышение производительности систем моделирования полёта на базе многоядерных ПЭВМ


Просмотров: 1176
2012 год
Е.А. Бурлак, А.М. Набатчиков, А.А. Огинский. Повышение производительности систем моделирования полёта на базе многоядерных ПЭВМ // Проблемы совершенствования робототехнических и интеллектуальных систем летательных аппаратов: Сб. докл. IX-й Всерос. науч.-техн. конф. "Проблемы совершенствования робототехнических и интеллектуальных систем летательных аппаратов", Москва, Мос. авиац. ин-т, 25-26 июня 2012 г. / Редкол.: К.М. Тихонов (пред.). – М.: Изд-во МАИ-ПРИНТ, 2012. – С. 334-339.
Мероприятие: IX Всероссийская научно-техническая конференция «Проблемы совершенствования робототехнических и интеллектуальных систем летательных аппаратов»
УДК: 004.032.3:004.272.4

Аннотация


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

Введение


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

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

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

Взаимодействие с устройством


Большинство современных устройств, используемых в исследованиях (такие как модули ЦАП\АЦП) поддерживают асинхронный и синхронный режимы опроса. Рассмотрим детальнее основные различия этих режимов на примере простой задачи регистрации сигнала, для чего итерацию цикла опроса разделим на три составляющие: постановку запроса устройству – t1, ожидание данных (все операции, скрытее за API аппаратуры: работа драйвера, работа устройства, прочее) – t2, обработка принятых данных в программе (сохранение, анализ, подготовка к новой итерации) – t3. Времена t1, t2, и t3 соответствуют средним временам выполнения соответствующих групп операций. В соответствии с принятыми обозначениями, временная диаграмма цикла синхронного опроса устройства выглядит следующим образом (см. рис. 1).

i01.png
Рис.1. Синхронный режим опроса устройства

Опрос устройства совершается в одном потоке, таким образом, время, необходимое на выполнение одного такта получения информации, выражается как Ts = t1 + t2 + t3

Временная диаграмма асинхронного режима опроса представлена на рис.2.

i02.png
Рис.2. Асинхронный режим опроса устройства

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

Несмотря на то, что первый такт занимает времени (Ta0) даже больше чем при синхронном опросе (см. рис 3.А), все последующие (Tan) итерации (рис. 3.B) позволяют компенсировать «стартовый» простой.

Ta0 = t1 + t2 + t1 + t3
Tan = t1 + max( t2, t3 ) = t1 + t2

i03.png
Рис.3. Итерации асинхронного режима опроса устройства

В качестве демонстрации результатов применения разных способов опроса, рассмотрим результаты взаимодействия с библиотекой, имитирующей устройство, способное работать в обоих режимах. В обоих случаях, с выхода «устройства» снималась синусоида (с частотой 4 Гц) в течение 5 секунд. Так как основные операции в данном, идеализированном случае выполняются за пренебрежимо малое время δt, производительность системы искусственно уменьшена путём введения дополнительных задержек (для обоих режимов). На рис.4 представлены типовые результаты замеров.

i04.png
Рис.4. Результаты синхронного и асинхронного опроса устройства

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

  • Разработка так называемой «обёртки» библиотеки (wrapper), обеспечивающей более удобную работу с API устройства, в том числе в языках, не обладающих необходимым инструментарием для работы с потоками. В этом случае обёртка может быть реализована (на C++), например, в виде динамически подключаемой библиотеки для использования в приложении, написанном на другом языке [2]. С такой необходимостью, в частности, столкнулись авторы при исследованиях, описанных в [3].
  • В случае если помимо регистрации данных на каждой итерации осуществляются некоторые операции, большую часть времени не зависящие от состояния устройства, вследствие чего их можно выполнять параллельно с опросом. Например, получаемые с устройства данные подлежат длительной обработке, в ходе которой текущее состояние источника информации игнорируется, при этом актуальность данных определяется разницей во времени между их получением и началом операций над ними.

Для решения вышеозначенных задач требуются некоторые манипуляции с потоками. На рис.5 приведена схема работы варианта реализации обёртки.

i05.png
Рис.5. Выделение потока получения данных

Асинхронный опрос источника данных (например, органа управления летательного аппарата в авиа-тренажёре) вынесен в отдельный поток: постановка запроса устройству происходит за время равное t1, устройство формирует ответ за время равное t2, поток записывает в некоторый участок памяти (буфер) результат опроса, затрачивая на эту операцию время равное t3. Поток приложения, использующий обёртку, выполняет длительную обработку информации (например, расчет параметров динамики ЛА, визуализацию внекабинной обстановки) за время равное t4, затем тратит t5, на чтение актуальных (на сколько позволяет скорость работы устройства) данных из буфера. Таким образом, устройство опрашивается постоянно: каждый новый блок данных заменяет собой предыдущий. Данные запрашиваются по мере необходимости (на рис.5: блоки A и C) за время t5 < t1 + t2, при этом невостребованные данные перезаписываются более поздними (на рис.5: блок B).

Технология


Поток (thread) – это управляемая единица исполняемого кода. В многозадачной среде, основанной на потоках, у всех процессов обязательно есть один поток, но их может быть и больше. Это означает, что в одной программе могут выполняться несколько задач одновременно [4].

Аппаратными возможностями реализации могут выступать: многоядерный процессор (реальное одновременное выполнение), технология гиперпоточности (hyper-threading; выделение двух логических ядер на одном физическом) или переключение контекста (на одноядерном процессоре без гиперпоточности). На данный момент, наиболее распространенным является первый вариант. Следует отметить, что Windows 98 при работе с многоядерными процессорами использует только одно ядро, игнорируя остальные.

Аспекты


Отдельно стоит отметить, что при разработке многопоточного приложения на языке C++, вероятно, придётся отказаться от паттерна проектирования «одиночка» (singleton, [5]): так называемый «синглтон Майерса» не является потокобезопасным. Полностью переносимое решение проблемы (в рамках существующего стандарта языка) отсутствует [6].

На некоторых многоядерных процессорах при работе в ОС Windows Server 2000, Windows Server 2003 и Windows XP выполнение потока на разных ядрах приводит к сложной ситуации при взаимодействии со счётчиком производительности ядра[7], вызванной разной, отличной от номинальной, частотой работы ядер. Данная проблема приводит к тому, что функция
QueryPerformanceCounter
, использующаяся для замеров времени с высокой точностью, вызванная последовательно два раза, может вернуть показание счётчика для первого вызова больше, чем для второго. Подобное поведение функции приводит к неправильным вычислениям времени, прошедшего между операциями (вплоть до отрицательных величин).

На работоспособность многопоточного приложения может повлиять версия ОС: некоторые функции могут быть определены, но не реализованы, или не поддерживать некоторые значения аргументов.

Список источников


Комментарии

Инкогнито
  Загружаем captcha