Implement ggml_v_expf() with a fast approximation on AVX/AVX2/AVX512 #10069
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    


The code implements a fast, vectorized approximation to exp(x). This trick should work on most backends, but is implemented only for AVX/AVX2/AVX512 to get some feedback on whether this is actually useful.
The constants used are optimized for explainability rather than minimizing average relative error. You can do a bit better with slightly different values over various input ranges, but the actual accuracy didn't seem particularly important in this context.
How it works
An unvectorized version of how the implementation works:
The implementation works by taking advantage of the standard IEEE-754 float representation:
Because IEEE-754 floats are essentially a log2 representation of values, the instructions that convert to and from integers to floats compute functions very similar to
2^xandlog2(x)respectively. The implementation uses an integer->float conversion to compute the exponential by computing an approximation to2^x, which is equivalent toexp(x)because:e^x = 2^(x * log2(e))However, just multiplying by a factor of log2(e) isn't quite enough. Everything before the conversion is happening in a log-space representation and we have to adjust all the factors by
2^23, the size of the mantissa. Operations on the exponent also need to be re-biased, which we can do by adding an adjusted constant of127. The code wraps these up into a single FMA before casting.The resulting approximation averages less than 10% relative error over the ±88.0f domain of the original exp() function, but differs slightly in out of domain behavior. In order to replicate the behavior of the existing implementation, this implementation clamps values outside the domain. The implementation passes CI tests on my system, but runs somewhat slower than an unclamped implementation which does not pass CI tests.
Testing notes
I've tested this against both the CI tests and interactive use. Nothing I've tested seems broken and I observed a small speed boost over the existing implementation in the interactive case.
Help from someone with more domain expertise in evaluating whether this breaks anything would be greatly appreciated.