суббота, 18 сентября 2010 г.

Размышления о движке моделирования

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

Создал два очень разных движка: MapSim и Aivika.

1. Первый – MapSim (лицензия LGPL). Генерирует очень быструю симуляцию, даже удивительно быструю. Но умеет только системную динамику. Очень узкая область. Движок очень хорошо делает свое дело, хотя даже в таком качестве MapSim может показаться отступнически революционным, ибо целиком написан на C#, а не на популярных в этой области Си или Си++ с Фортраном.

2. Второй – Айвика (лицензия BSD). Фантастически универсальный движок. Умеет самые разные парадигмы имитационного моделирования. Но редкостный тормоз на задачах системной динамики (интегралы чудовищно неэффективны). Дискретное событийное моделирование более-менее (быстрый двоичный хип). Скорость же процесс-ориентированной дискретной симуляции сильно зависит от качества реализации системы памяти (создается много легковесных функций) и хвостовой рекурсии (.NET на порядок быстрее, чем Mono), но в целом медленная симуляция. Агентное моделирование медленнее, чем в AnyLogic, но я думаю, что приемлемо. Еще движок Айвика – это полный переворот сознания для обычного модельера. Трудно для понимания.

В общем, два антипода. Есть идея скрестить их. Это возможно благодаря универсальности Айвики. Тут два момента.

1. Симуляцию, сгенерированную с помощью MapSim, можно представить как вычисление в монаде моделирования Dynamics. Это значит, что такую симуляцию можно использовать в Айвике как равноправную. Есть накладные расходы, связанные с оборачиванием итерационного процесса, порождаемого MapSim, в небольшую прослойку, которая будет выглядеть внешне как динамический процесс Dynamics. Нужно будет где-то хранить значения выходных переменных. Чем меньше переменных на выходе, тем быстрее эта прослойка. Придется повозиться.

2. Внутри симуляции под управлением MapSim можно использовать вычисления в монаде Dynamics. Другими словами, MapSim может использовать модели Айвики. Накладные расходы минимальны. Реализовать очень просто.

Теоретических проблем нет. Все должно работать. Я уже продумал. И если бы я снова стал создавать визуальную среду моделирования Simtegra MapSys, то сейчас уже взял бы за основной общесистемный движок Айвику, а системную динамику оптимизировал бы с помощью MapSim. То есть, я очень серьезно отношусь к Айвике, хотя с первого взгляда она может показаться просто игрушкой функционального программирования :)

пятница, 17 сентября 2010 г.

CodeDom для F#

Сегодня взял свою библиотеку MapSim, которая умеет создавать код через CodeDom, и заменил СSharpCodeProvider на FSharpCodeProvider из F# PowerPack. Сработало! MapSim по заданному входу сгенерировал код на F#. Только местами забавный код получился. В одном месте создаются исключения только для того, чтобы их тут же перехватить. Странно как-то. Но в целом качество кода сопоставимо с тем, что у меня создает стандартный провайдер C#.

среда, 15 сентября 2010 г.

А не переписать ли MapSim на F#?

Иногда возникают мысли переписать свою библиотеку моделирования MapSim на F#. Сейчас она написана на C#. Думаю, что будет большая польза от использования абстрактных типов данных (ADTs). Также можно будет добавить разный back-end, т.е. создавать симуляции не только для .NET, но и для Java, JavaScript и C++ с фортраном.

Чертовски быстрая симуляция получается даже сейчас на .NET. Код линеен, почти не создает объектов, не выделяет память, а используемая память умещается в кеш процессора. JIT-компилятор создает код, сравнимый с ассемблером. Симуляцию можно еще ускорить, если использовать локальные переменные – сейчас везде используются поля объекта для надежности (в .NET есть лимит в 64 кб для локальных переменных).

Думаю, что когда-нибудь можно будет подружить MapSim и Айвику. Тогда симуляция в Айвике для системной динамики будет намного быстрее. Эту тему затронул в обзорной статье Aivika Overview.

Aivika версии 2.0.12.0

Залил новую версию своей библиотеки по моделированию. Сам код не изменился. Перевел проект на .NET v4 и Visual Studio 2010. Добавил статью Aivika Overview, где на восьми страницах дается обзор метода. Кроме прочего, упоминаются и монады, ибо вся соль моего метода в том, что заданная имитационная модель сводится к динамическому процессу, а такой процесс является монадой. Отсюда фантастические возможности по комбинированию процессов. Хотя я уже писал об этом прежде :)

воскресенье, 12 сентября 2010 г.

О вычислительных выражениях

Уже почти год пишу на F#, и мне так понравились вычислительные выражения! Удивительно простая в использовании штука. Такое выражение можно записать в императивном стиле как почти обычный код на F#, используя while, for и try, а оно потом на выходе будет преобразовано компилятором F# в выражение, состоящее из композиции функции. Императивная конструкция превращается в сугубо функциональное выражение. Замечательная идея. Сюда же легко вписываются монады и моноиды. Вот, с монадными трансформерами накладка.

Поддержка таких выражений – это просто непередаваемая по значимости вещь для императивных монад типа Async для асинхронных вычислений. Более того, не нужно поддерживать на уровне языка продолжения – для них можно использовать те же вычислительные выражения (но нужна поддержка TCO на уровне исполняющей среды). Продолжения не совсем императивны, но все же блоки try-with и try-finally обрабатывать в таком языке как F# надо. И здесь нет известной проблемы Common Lisp.

Кстати, о Лиспе. Считаю, что вычислительные выражения и макросы мешают друг другу. Эти выражения предполагают, что есть ограниченное множество конструкций языка, которые могут быть “офункционалены” (превращены в функции). Макросы это нарушают. Когда я добавлял поддержку вычислительных выражений в Немерле, то оставлял макросы как есть. Не знаю, можно ли придумать здесь что-то лучше? (интересно, а как макросы и продолжения сосуществуют в Схеме?)

Мне теперь стало очень не хватать вычислительных выражений в Скале и Окамле. Скаловский for-comprehension смотрится как-то слабо, особенно для императивных монад, когда вычисления нужно разбавить обычным кодом. Что касается Окамла, то для него есть одно расширение, но очень хотелось бы, чтобы решение было стандартизировано и “из-коробки”. Надеюсь, что когда-нибудь добавят.