J'ai implémenté une grande variété de solveurs non linéaires sur le GPU, y compris LBFGS, la descente de gradient de Barzilai Borwein et le gradient conjugué non linéaire.
Pour cela, le gradient conjugué non linéaire de Dai & Yuan a été le plus efficace. En général, une autre version du gradient conjugué non linéaire peut être plus efficace (comme CG-DESCENT), mais peut également être plus difficile à mettre en œuvre.
LBFGS est en général un choix très solide, et à moins que vous ne soyez vraiment à court de mémoire, c'est probablement le meilleur endroit pour commencer.
Le gradient conjugué et le BFGS nécessitent cependant des recherches de ligne, c'est là que le fp32 devient un problème. Plutôt que d'utiliser les conditions Wolfe standard pour la recherche de ligne, je suggère d'utiliser la condition Wolfe approximative suggérée ici . Le papier est un peu impliqué, mais l'important est l'équation 4.1. Essentiellement, ils introduisent explicitement la précision avec laquelle vous pouvez calculer votre fonction.
Considérations pour le GPU:
Vous avez beaucoup de petits problèmes, ce qui est légèrement différent de mon cas d'utilisation d'un gros problème. Envisagez d'exécuter 1 problème par bloc GPU (ou warp, plutôt) si vous pouvez paralléliser les évaluations de fonction et de gradient pour utiliser tous les threads d'un bloc. De cette façon, ce n'est pas un problème si différents problèmes nécessitent un nombre différent d'itérations.
Si ce n'est pas une option, j'irais avec le solveur LBFGS. Si votre fonction se comporte bien, vous pouvez vous en sortir en utilisant simplement une taille de pas de 1 (en évitant la recherche de ligne) et en exécutant simplement tous les problèmes pour un nombre fixe d'itérations.