Rapide Exp calcul: possible pour améliorer la précision sans perdre trop de la performance?

Je suis en train de sortir de la fast Exp(x) la fonction qui, auparavant, a été décrit dans cette réponse à un DONC, la question sur l'amélioration de la vitesse de calcul en C#:

public static double Exp(double x)
{
  var tmp = (long)(1512775 * x + 1072632447);
  return BitConverter.Int64BitsToDouble(tmp << 32);
}

L'expression est l'utilisation de certaines virgule flottante IEEE "trucs et astuces" et est principalement conçu pour une utilisation dans des ensembles de neurones. La fonction est environ 5 fois plus rapide que le Math.Exp(x) fonction.

Malheureusement, la précision numérique est seulement -4% -- +2% par rapport à la régulière Math.Exp(x) fonction, idéalement, je voudrais avoir une précision à l'intérieur d'au moins la sous-gamme pour cent.

J'ai tracé le quotient entre l'approximatif et le régulier fonctions Exp, et comme on peut le voir dans le graphique de la différence relative semble être répété avec pratiquement constante de fréquence.

Rapide Exp calcul: possible pour améliorer la précision sans perdre trop de la performance?

Est-il possible de profiter de cette régularité pour améliorer la précision de la "fast exp" fonction " sans réduire la vitesse de calcul, ou serait le calcul de la surcharge d'une précision d'amélioration de l'emporter sur le calcul du gain de l'expression d'origine?

(Comme une note de côté, j'ai aussi essayé de d'un autre approches proposées dans la même DONC, la question, mais cette approche ne semble pas être efficaces de calcul en C#, du moins pas pour le cas général.)

MISE À JOUR LE 14 MAI

À la demande de @Adriano, j'ai effectué un très simple indice de référence. J'ai réalisé 10 millions de calculs à l'aide de chacune des autres exp fonctions pour les valeurs à virgule flottante dans l'intervalle [-100, 100]. Depuis la plage de valeurs, je suis intéressé à s'étend de -20 à 0 j'ai aussi explicitement la valeur de la fonction en x = -5. Voici les résultats:

      Math.Exp: 62.525 ms, exp(-5) = 0.00673794699908547
Empty function: 13.769 ms
     ExpNeural: 14.867 ms, exp(-5) = 0.00675211846828461
    ExpSeries8: 15.121 ms, exp(-5) = 0.00641270968867667
   ExpSeries16: 32.046 ms, exp(-5) = 0.00673666189488182
          exp1: 15.062 ms, exp(-5) = -12.3333325982094
          exp2: 15.090 ms, exp(-5) = 13.708332516253
          exp3: 16.251 ms, exp(-5) = -12.3333325982094
          exp4: 17.924 ms, exp(-5) = 728.368055056781
          exp5: 20.972 ms, exp(-5) = -6.13293614238501
          exp6: 24.212 ms, exp(-5) = 3.55518353166184
          exp7: 29.092 ms, exp(-5) = -1.8271053775984
      exp7 +/-: 38.482 ms, exp(-5) = 0.00695945286970704

ExpNeural est l'équivalent de la Exp fonction spécifiée dans le début de ce texte. ExpSeries8 est le formulation que j'ai à l'origine revendiquée n'était pas très efficace .NET; lors de la mise en œuvre exactement comme Neil il était en fait très rapide. ExpSeries16 est l'analogue de la formule, mais avec 16 multiplications au lieu de 8. exp1 par exp7 sont les différentes fonctions de Adriano réponse ci-dessous. La dernière variante de exp7 est une variante où le signe de x est cochée; si le résultat est négatif, la fonction renvoie 1/exp(-x) à la place.

Malheureusement, ni l'un ni l' expN fonctions énumérées par Adriano sont suffisantes dans la plus large de la valeur négative de la gamme que j'envisage. L'extension de la série approche par Neil Coffey semble être plus appropriée dans "ma" plage de valeurs, mais il est trop rapide divergentes avec les plus grandes négatif x, en particulier lors de l'utilisation de "seulement" 8 multiplications.

  • je suis curieux de connaître votre référence à des "ensembles de neurones." actuellement, je suis à la simulation d'un réseau de neurones à l'aide de C++ et face à la même exp goulot d'étranglement des performances que vous avez relevé. existe-il des papiers dans les neurosciences computationnelles qui ont proposé approximative exp fonctions qui sont très vite?