Как повысить производительность за счет автоматической дифференциации?

Мне трудно оптимизировать программу, которая опирается на ads conjugateGradientDescent функция для большей части его работы.

По сути, мой код - это перевод старого бумажного кода, написанного на Matlab и C. Я не измерял его, но этот код выполняется с несколькими итерациями в секунду. У меня порядок минут на итерацию...

Код доступен в этих репозиториях:

Рассматриваемый код можно запустить, выполнив следующие команды:

$ cd aer-utils
$ cabal sandbox init
$ cabal sandbox add-source ../aer
$ cabal run learngabors

Используя средства профилирования GHC, я подтвердил, что спуск - это та часть, которая занимает большую часть времени:

Фламограф одной итерации

(интерактивная версия здесь: https://dl.dropboxusercontent.com/u/2359191/learngabors.svg)

-s говорит мне, что производительность довольно низкая

Productivity  33.6% of total user, 33.6% of total elapsed

Из того, что я понял, есть две вещи, которые могут привести к повышению производительности:

  • Распаковка: в настоящее время я использую собственную матричную реализацию (в src/Data/SimpleMat.hs). Это был единственный способ получить ad работать с матрицами (см.: Как сделать автоматическое дифференцирование на Hmatrix?). Я предполагаю, что с помощью типа матрицы, как newtype Mat w h a = Mat (Unboxed.Vector a) достигнет лучшей производительности из-за распаковки и слияния. Я нашел код, который имеет ad экземпляры для неупакованных векторов, но до сих пор я не смог использовать их с conjugateGradientFunction,

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

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

1 ответ

Решение

Вы сталкиваетесь с наихудшим сценарием на текущий момент. ad библиотека здесь.

FWIW - Вы не сможете использовать существующие ad классы / типы с "матричной / векторной рекламой". Это было бы довольно большое инженерное усилие, см. https://github.com/ekmett/ad/issues/2

Что касается того, почему вы не можете распаковать: conjugateGradient требует умения использовать Kahn режим или два уровня прямого режима на ваших функциях. Первый не позволяет работать с распакованными векторами, поскольку типы данных содержат синтаксические деревья и не могут быть распакованы. По разным техническим причинам я не понял, как заставить его работать с "лентой" фиксированного размера, как стандарт Reverse Режим.

Я думаю, что "правильный" ответ здесь для нас, чтобы сесть и выяснить, как правильно создать матричный / векторный AD и интегрировать в пакет, но я признаюсь, что сейчас я слишком тонко нарезан, чтобы уделить ему внимание заслуживает.

Если у вас есть возможность покататься на #haskell-lens на irc.freenode.net, я с удовольствием расскажу о дизайнах в этой области и даду совет. Алекс Ланг также работал над ad много и часто присутствует там и может иметь идеи.

Другие вопросы по тегам