Risoluzione di problemi di ottimizzazione non lineare non vincolati su GPU


18

Sto cercando di risolvere alcuni problemi di ottimizzazione non lineare non vincolati su GPU (CUDA).

La funzione obiettivo è una funzione non lineare regolare, e il suo gradiente è relativamente economico da calcolare analiticamente, quindi non ho bisogno di preoccuparmi dell'approssimazione numerica.

Voglio risolvere questo problema con la maggior parte delle operazioni matematiche su fp32 (per vari motivi), quindi quale metodo di ottimizzazione non lineare è più robusto rispetto agli errori di arrotondamento mentre ha buone prestazioni? (es. gradiente coniugato / quasi newton / regione di fiducia), qualcuno ha provato BFGS su GPU con buoni risultati?

A proposito, l'Assia, se necessario, è relativamente piccola nel mio caso (<64x64 in genere), ma devo risolvere contemporaneamente migliaia di questi problemi di ottimizzazione su piccola scala.


4
Date le dimensioni ridotte dei tuoi problemi, non credo che la scelta specifica dell'algoritmo (ad esempio, BFGS) sarà la tua sfida più significativa. Invece, minimizzerà l'overhead di comunicazione della GPU <-> CPU. Probabilmente il modo migliore per farlo è risolvere molti casi in parallelo sulla GPU. Caricali tutti in una volta, risolvili tutti in una volta, scarica i risultati tutti in una volta. Non ho consigli specifici sull'algoritmo, ma dirò che le GPU sono migliori con i loop che con i rami.
Michael Grant,

1
@Michael C. Grant: Beh, nel mio caso l'overhead della comunicazione può essere facilmente nascosto dal calcolo, quindi non è un collo di bottiglia lì, sono molto propenso a usare BFGS a memoria limitata o BFGS standard qui, ma non sono sicuro se ci sono approccio migliore.
user0002128

Alcune persone hanno implementato LBFGS con CUDA .
BenC,

Risposte:


8

Ho implementato una vasta gamma di solutori non lineari sulla GPU, tra cui LBFGS, discesa del gradiente Barzilai Borwein e gradiente coniugato non lineare.

Per questo, il gradiente coniugato non lineare di Dai & Yuan è stato il più efficiente. In generale, altre versioni del gradiente coniugato non lineare possono essere più efficienti (come CG-DESCENT), ma possono anche essere più difficili da implementare.

LBFGS è in genere una scelta molto solida e, a meno che tu non sia davvero a corto di memoria, è probabilmente il posto migliore da cui iniziare.

Sia il gradiente coniugato che il BFGS richiedono ricerche di linea, ma è qui che fp32 diventa un problema. Piuttosto che usare le condizioni standard di Wolfe per la ricerca della linea, suggerirei di usare le condizioni approssimative di Wolfe suggerite qui . L'articolo è un po 'coinvolto, ma la cosa importante è l'equazione 4.1. In sostanza introducono esplicitamente la precisione con cui è possibile calcolare la propria funzione.

Considerazioni per la GPU:

Hai molti piccoli problemi, che è leggermente diverso dal mio caso d'uso di un grosso problema. Prendi in considerazione 1 problema per blocco GPU (o warp, piuttosto) se puoi parallelizzare le valutazioni di funzioni e gradiente per usare tutti i thread in un blocco. In questo modo non è un problema se problemi diversi richiedono un numero diverso di iterazioni.

Se questa non è un'opzione, andrei con il risolutore LBFGS. Se la tua funzione è ben educata, potresti cavartela semplicemente usando una dimensione del passo pari a 1 (evitando la ricerca della riga) e semplicemente eseguendo tutti i problemi per un numero fisso di iterazioni.


0

Ti suggerisco di utilizzare Levenberg Marquardt (una variante della regione di fiducia) in quanto viene utilizzato in molte applicazioni pratiche e ha dimostrato ottime prestazioni in termini di velocità e precisione. Inoltre, per GPU ci sono alcune librerie (ad esempio cuLM https://github.com/zitmen/cuLM ), che potresti provare. Se non fanno il lavoro, ci sono tonnellate di risorse da implementare. L'implementazione di LM non è affatto difficile. Dovresti solo preoccuparti di minimizzare la comunicazione GPU. Per avere una breve idea:

http://on-demand.gputechconf.com/gtc/2012/presentations/S0231-Levenberg-Marquardt-Using-Block-Sparse-Matrices-on-CUDA.pdf


2
Levenberg-Marquart è per minimi quadrati non lineari. Non credo che abbia menzionato nulla dei minimi quadrati.
Kurt

0

Forse una procedura di ricottura simulata può gestire meglio gli errori di arrotondamento (ed è facilmente parallelizzabile).

Si inizia con una griglia grezza dell'area di ricerca e un parametro iniziale "temperatura"

Ad ogni passo si calcolano punti di soluzione posibili (si possono anche accettare punti non di soluzione, con una probabilità inversamente analoga alla temperatura)

Quindi conservare solo le soluzioni in quella fase e aumentare la temperatura che fornisce una griglia a grana più fine per la successiva iterazione

Fallo fino a quando la temperatura <un dato limite / soglia di precisione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.