Как повысить производительность за счет автоматической дифференциации?
Мне трудно оптимизировать программу, которая опирается на ad
s 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
много и часто присутствует там и может иметь идеи.