2015-06-17 5 views
16

Ho difficoltà a ottimizzare un programma che si basa sulla funzione conjugateGradientDescent s conjugateGradientDescent per la maggior parte del suo lavoro.Come ottenere più prestazioni dal differenziamento automatico?

Fondamentalmente il mio codice è una traduzione di un old papers code scritto in Matlab e C. Non l'ho misurato, ma quel codice è in esecuzione a più iterazioni al secondo. Il mio è nell'ordine dei minuti per l'iterazione ...

Il codice è disponibile in questo repository:

Il codice in questione può essere eseguito seguendo questi comandi:

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

Utilizzo di GHC s profiling servizi mi hanno confermato che la discesa è infatti la parte che sta prendendo la maggior parte del tempo:

Flamegraph of one iteration

(versione interattiva qui: https://dl.dropboxusercontent.com/u/2359191/learngabors.svg)

-s mi sta dicendo che la produttività è abbastanza basso:

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

da quello che ho raccolto ci sono due cose che possono portare a prestazioni più elevate:

  • Unboxing: attualmente utilizzo un'implementazione matrice personalizzata (in src/Data/SimpleMat.hs). Questo era l'unico modo per far funzionare ad con le matrici (vedi: How to do automatic differentiation on hmatrix?). La mia ipotesi è che usando un tipo di matrice come newtype Mat w h a = Mat (Unboxed.Vector a) si otterrebbero prestazioni migliori a causa di unboxing e fusione. Ho trovato some code che ha istanze ad per vettori unboxed, ma fino ad ora non sono stato in grado di utilizzare questi con il conjugateGradientFunction.

  • derivati ​​Matrix: In un'email non riesco proprio a trovare al momento Edward afferma che sarebbe meglio usare Forward casi per i tipi di matrice invece di avere matrici pieni di Forward casi. Ho una vaga idea di come ottenerlo, ma devo ancora capire come implementarlo in termini di classi di tipo ad s.

Questa è probabilmente una domanda che è troppo ampia per essere risolta su SO, quindi se si è disposti a darmi una mano qui, non esitate a contattarmi su Github.

+0

Domanda per il pubblico: la corsa di cabala usa qualcosa come runhaskell sotto il cofano, cioè fa parte del problema che questo codice viene interpretato invece di compilato? –

+1

@ JohnF.Miller 'cabal run' esegue codice compilato. Eseguire la stessa cosa da GHCi (cioè usare ': main') è ancora più lento. – fho

risposta

3

Si sta verificando lo scenario peggiore per la libreria corrente ad qui.

FWIW- Non sarà possibile utilizzare le classi/tipi ad esistenti con "annuncio matrice/vettore".Sarebbe un gran sforzo di ingegneria, vedi https://github.com/ekmett/ad/issues/2

Per quanto riguarda il motivo per cui non è possibile Unbox: conjugateGradient richiede la capacità di utilizzare la modalità Kahn o due livelli della modalità in avanti sulle vostre funzioni. Il primo gli impedisce di lavorare con vettori non condivisi, poiché i tipi di dati contengono alberi di sintassi e non possono essere disgiunti. Per varie ragioni tecniche non ho capito come farlo funzionare con un "nastro" di dimensioni fisse come la modalità standard Reverse.

Penso che la "giusta" risposta qui sia per noi di sederci e capire come ottenere Matrice/vettore AD a destra e integrato nel pacchetto, ma confesso di essere un po 'troppo sottile in questo momento per dare è l'attenzione che merita.

Se si ha la possibilità di passare da # haskell-lens su irc.freenode.net, sarei felice di parlare di progetti in questo spazio e offrire consigli. Alex Lang ha anche lavorato molto su ad ed è spesso presente e potrebbe avere idee.