haskell - ¿Cómo obtener más rendimiento de la diferenciación automática?
automatic-differentiation hmatrix (1)
Me está costando mucho optimizar un programa que se basa en la función conjugateGradientDescent
los ad
para la mayor parte de su trabajo.
Básicamente, mi código es una traducción de un código de documentos antiguos que está escrito en Matlab y C. No lo he medido, pero ese código se ejecuta en varias iteraciones por segundo. El mío está en el orden de minutos por iteración ...
El código está disponible en este repositorios:
El código en cuestión se puede ejecutar siguiendo estos comandos:
$ cd aer-utils
$ cabal sandbox init
$ cabal sandbox add-source ../aer
$ cabal run learngabors
Al utilizar las instalaciones de perfilado de GHC, he confirmado que el descenso es, de hecho, la parte que más tiempo toma:
(versión interactiva aquí: https://dl.dropboxusercontent.com/u/2359191/learngabors.svg )
-s
me está diciendo que la productividad es bastante baja:
Productivity 33.6% of total user, 33.6% of total elapsed
De lo que he reunido hay dos cosas que pueden conducir a un mayor rendimiento:
Unboxing: actualmente uso una implementación de matriz personalizada (en
src/Data/SimpleMat.hs
). Esta era la única forma en que podía hacer que elad
funcionara con matrices (ver: ¿Cómo hacer la diferenciación automática en hmatrix? ). Mi conjetura es que al usar un tipo de matriz comonewtype Mat wha = Mat (Unboxed.Vector a)
lograría un mejor rendimiento debido a la unboxing y la fusión. Encontré un código que tiene instancias dead
para vectores sin caja, pero hasta ahora no he podido usarlos con elconjugateGradientFunction
.Derivadas de matriz: en un correo electrónico que no puedo encontrar en este momento, Edward menciona que sería mejor usar las instancias de
Forward
para los tipos de matriz en lugar de tener matrices llenas de instancias deForward
. Tengo una pequeña idea de cómo lograrlo, pero aún tengo que descubrir cómo lo implementaría en términos de clases de tipos dead
.
Esta es probablemente una pregunta que es demasiado amplia para ser contestada en SO, así que si está dispuesto a ayudarme aquí, no dude en contactarme en Github.
Se está ejecutando en el peor de los casos de la biblioteca de ad
actual aquí.
FWIW: no podrá utilizar los tipos / clases de ad
existentes con "matriz / vector de anuncios". Sería un esfuerzo de ingeniería bastante grande, consulte https://github.com/ekmett/ad/issues/2
En cuanto a por qué no puedes unboxear: conjugateGradient
requiere la habilidad de usar el modo Kahn
o dos niveles del modo de avance en tus funciones. Lo anterior le impide trabajar con vectores sin caja, ya que los tipos de datos llevan árboles de sintaxis y no pueden ser sin caja. Por diversas razones técnicas, no he descubierto cómo hacer que funcione con una "cinta" de tamaño fijo como el modo Reverse
estándar.
Creo que la respuesta "correcta" aquí es que nos sentemos y averigüemos cómo hacer que la matriz / vector AD sea correcta e integrada en el paquete, pero confieso que en este momento estoy demasiado limitado para prestarle atención. merece
Si tienes la oportunidad de pasar por # haskell-lens en irc.freenode.net, me encantaría hablar sobre los diseños en este espacio y ofrecerte consejos. Alex Lang también ha estado trabajando mucho en ad
y, a menudo, está presente allí y puede tener ideas.