Мне сложно оптимизировать программу, которая полагается на функцию ad
conjugateGradientDescent
для большей части работы.
В основном мой код является переводом кода старых документов, который написан в Matlab и C. Я его не оценил, но это код работает с несколькими итерациями в секунду. Мина находится в порядке минут на итерацию...
Код доступен в этих репозиториях:
Этот код можно запустить, выполнив следующие команды:
$ cd aer-utils
$ cabal sandbox init
$ cabal sandbox add-source ../aer
$ cabal run learngabors
Используя средства профилирования GHCs, я подтвердил, что спуск фактически является частью, которая занимает большую часть времени:
(интерактивная версия здесь: https://dl.dropboxusercontent.com/u/2359191/learngabors.svg)
-s
говорит мне, что производительность довольно низкая:
Productivity 33.6% of total user, 33.6% of total elapsed
Из того, что я собрал, есть две вещи, которые могут привести к повышению производительности:
-
Unboxing: В настоящее время я использую реализацию пользовательской матрицы (в
src/Data/SimpleMat.hs
). Это был единственный способ получитьad
для работы с матрицами (см. Как сделать автоматическое дифференцирование на hmatrix?). Я предполагаю, что использование матричного типа, такого какnewtype Mat w h a = Mat (Unboxed.Vector a)
, обеспечит лучшую производительность из-за распаковки и слияния. Я нашел некоторый код, который имеет экземплярыad
для распакованных векторов, но до сих пор я не смог использовать их с помощьюconjugateGradientFunction
. -
Матричные производные: В электронном письме, которое я просто не могу найти в тот момент, Эдвард упоминает, что было бы лучше использовать экземпляры
Forward
для матричных типов вместо матриц, заполненныхForward
экземпляры. Я имею слабое представление о том, как этого достичь, но еще не понял, как реализовать его в терминах классов типаad
.
Это, вероятно, вопрос, который слишком широк для ответа на SO, поэтому, если вы готовы помочь мне здесь, не стесняйтесь обращаться ко мне в Github.