You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Division.py 3.7 kB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from __future__ import absolute_import
  2. from .Node import Op
  3. from .._base import DNNL_LIB
  4. from .Opposite import opposite_op
  5. from ..cpu_links import matrix_elementwise_divide as\
  6. cpu_matrix_elementwise_divide
  7. from ..cpu_links import matrix_elementwise_divide_by_const as\
  8. cpu_matrix_elementwise_divide_by_const
  9. from ..gpu_links import matrix_elementwise_divide
  10. from ..gpu_links import matrix_elementwise_divide_const
  11. class DivOp(Op):
  12. def __init__(self, node_A, node_B, ctx=None):
  13. super().__init__(DivOp, [node_A, node_B], ctx)
  14. def compute(self, input_vals, output_val, stream_handle=None):
  15. assert input_vals[0].shape == input_vals[1].shape, \
  16. "can't do elementwise division between variables of different sizes."
  17. if self.on_cpu:
  18. if DNNL_LIB['DnnlMatrixElementwiseDivide']:
  19. cpu_matrix_elementwise_divide(
  20. input_vals[0], input_vals[1], output_val)
  21. else:
  22. output_val[:] = input_vals[0].asnumpy() / \
  23. input_vals[1].asnumpy()
  24. else:
  25. matrix_elementwise_divide(
  26. input_vals[0], input_vals[1], output_val, stream_handle)
  27. def gradient(self, output_grad):
  28. dividend_grad = div_const_op(1, self.inputs[1], ctx=self.raw_ctx)
  29. divisor_grad = opposite_op(div_op(div_op(
  30. self.inputs[0], self.inputs[1], ctx=self.raw_ctx), self.inputs[1], ctx=self.raw_ctx))
  31. return [dividend_grad * output_grad, divisor_grad * output_grad]
  32. def infer_shape(self, input_shapes):
  33. assert len(input_shapes) == 2
  34. assert input_shapes[0] == input_shapes[1], \
  35. "can't do elementwise division between variables of different sizes."
  36. output = input_shapes[0]
  37. return output
  38. class DivConstOp(Op):
  39. def __init__(self, const_val, node_A, ctx=None):
  40. super().__init__(DivConstOp, [node_A], ctx)
  41. self.const_attr = const_val
  42. def compute(self, input_vals, output_val, stream_handle=None):
  43. if self.on_cpu:
  44. if DNNL_LIB['DnnlMatrixElementwiseDivideByConst']:
  45. cpu_matrix_elementwise_divide_by_const(
  46. input_vals[0], self.const_attr, output_val)
  47. else:
  48. output_val[:] = self.const_attr / input_vals[0].asnumpy()
  49. else:
  50. matrix_elementwise_divide_const(
  51. self.const_attr, input_vals[0], output_val, stream_handle)
  52. def gradient(self, output_grad):
  53. divisor_grad = div_op(div_const_op(-self.const_attr,
  54. self.inputs[0], ctx=self.raw_ctx), self.inputs[0], ctx=self.raw_ctx)
  55. return [divisor_grad * output_grad]
  56. def infer_shape(self, input_shapes):
  57. assert len(input_shapes) == 1
  58. return input_shapes[0]
  59. def div_op(node_A, node_B, ctx=None):
  60. """Make a new instance of matrixs elementwise division and call the instance.
  61. Parameters:
  62. ----
  63. node_A : Node
  64. The Node where elements are numerators.
  65. node_B : Node
  66. Another Node where elements are denominators.
  67. Returns:
  68. ----
  69. A new Node instance created by Op.
  70. """
  71. return DivOp(node_A, node_B, ctx=ctx)
  72. def div_const_op(const_val, node_A, ctx=None):
  73. """Make a new instance of matrix elementwise devide a constant value and call the instance.
  74. Parameters:
  75. ----
  76. const_val: scalar value
  77. The constant value to be mutiplied.
  78. node_A : Node
  79. The Node where elements are denominators.
  80. Returns:
  81. ----
  82. A new Node instance created by Op.
  83. """
  84. return DivConstOp(const_val, node_A, ctx=ctx)