Tuesday, February 28, 2012

Броненосец

Предположим вам понадобился контейнер с арифметическими операциями, с математическими и статистическими функциями - не найти из того, что под рукой. Такие, как std vector, framework vector и std valarray хороши в арифметических операциях и в слияниях/разлияниях подвекторов. valarray хорош в поддержке математических функций и обладает высокой производительностью в версии Intel компилятора благодаря использованию IPP. Конечно, можно вспомнить про boost и blitz++, но использовать одну махину или другую поменьше, с необновляемым кодом, для тестирования и получения простой статистики надо иметь значительно больше энтузиазма, чем у меня есть. Хорошо бы иметь библиотеку с выразительностью операций matlab, легко интегрируемую в С/С++ и бесплатную. Для примера, следующую версию вычисления нормы 2 с std вектором выразительной не назовешь, без std проще будет.
Поиски навели на библиотеку Armadilla, предоставляемую в заголовочных файлах с шаблонами, плюс библиотечные файлы blas и lapack, как дань достигнутой теми производительности. Из-за них, оказалось, размещение arma матриц в памяти сделано, как в Фортране. Библиотека обновляется, автор использует ее в своих научных исследованиях, есть пользователи и форум. 
Сразу нашел в ней то, что мне нужно. Нашел даже больше, чем рассчитывал. Оказалось, что автор Conrad Sanderson сделал многое, чтобы Armadilla стала очень похожа на Octave, и он добился этого. Сравниваем пример кода нахождения коэффициентов линейной регрессии.
Octave:

С++ Armadilla
И код, и результат одинаковы (с поправкой на С и реализацию rand)
Обнаружил, что не хватает гистограммы. Написал автору, получил ответ: “а сам напиши”. Написал аналог histc из Octave. Что оказалось непросто, так это встроить функцию в библиотеку. Во время встраивания открылось еще одно достоинство библиотеки. Код с использованием шаблонов написан так, что векторные или матричные вычисления, подобно таким A=B+C+D*E, не создают временных массивов для промежуточных матриц. Достигается это использованием так называемых Glue классов. Они то и усложнили разработку. 
Сравнил производительность вычисления гистограммы с помощью разработанной arma::histc и кода, написанного с std::vector. Последний не сумел написать проще, чем так

Производительность arma версии лучше почти в 2 раза.
Неплохой броненосец у Конрада Сандерсона получился.

No comments:

Post a Comment