fused_bias_gelu.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. # coding=utf-8
  2. # Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import torch
  16. torch._C._jit_set_profiling_mode(False)
  17. torch._C._jit_set_profiling_executor(False)
  18. torch._C._jit_override_can_fuse_on_cpu(True)
  19. torch._C._jit_override_can_fuse_on_gpu(True)
  20. ###### BIAS GELU FUSION/ NO AUTOGRAD ################
  21. # 1/sqrt(2*pi)-> 0.3989423
  22. # 1/sqrt(2) -> 0.70710678
  23. # sqrt(2/pi) -> 0.79788456
  24. # this function is tanh approximation of gelu
  25. # actual gelu is:
  26. # x * 0.5 * (1.0 + torch.erf(x * 0.70710678))
  27. @torch.jit.script
  28. def bias_gelu(bias, y):
  29. x = bias + y
  30. return x * 0.5 * (1.0 + torch.tanh(0.79788456 * x * (1 + 0.044715 * x * x)))
  31. # gradient of tanh approximation of gelu
  32. # gradient of actual gelu is:
  33. # 0.5 * (1. + torch.erf(x * 0.70710678)) + 0.3989423 * x * torch.exp(-0.5 * x * x)
  34. @torch.jit.script
  35. def bias_gelu_back(g, bias, y):
  36. x = bias + y
  37. tanh_out = torch.tanh(0.79788456 * x * (1 + 0.044715 * x * x))
  38. # sqrt(2/pi) * 3 * 0.044715 -> 0.1070322243
  39. ff = 0.5 * x * ((1 - tanh_out * tanh_out) * (0.79788456 + 0.1070322243 * x * x)) + 0.5 * (1 + tanh_out)
  40. return ff*g
  41. class GeLUFunction(torch.autograd.Function):
  42. @staticmethod
  43. # bias is an optional argument
  44. def forward(ctx, input, bias):
  45. ctx.save_for_backward(input, bias)
  46. return bias_gelu(bias, input)
  47. @staticmethod
  48. def backward(ctx, grad_output):
  49. input, bias = ctx.saved_tensors
  50. tmp = bias_gelu_back(grad_output, bias, input)
  51. return tmp, tmp
  52. bias_gelu_impl = GeLUFunction.apply