|
- from __future__ import absolute_import
- from .Node import Op
- from .._base import DNNL_LIB
- from .Opposite import opposite_op
- from ..cpu_links import matrix_elementwise_divide as\
- cpu_matrix_elementwise_divide
- from ..cpu_links import matrix_elementwise_divide_by_const as\
- cpu_matrix_elementwise_divide_by_const
- from ..gpu_links import matrix_elementwise_divide
- from ..gpu_links import matrix_elementwise_divide_const
-
-
- class DivOp(Op):
- def __init__(self, node_A, node_B, ctx=None):
- super().__init__(DivOp, [node_A, node_B], ctx)
-
- def compute(self, input_vals, output_val, stream_handle=None):
- assert input_vals[0].shape == input_vals[1].shape, \
- "can't do elementwise division between variables of different sizes."
- if self.on_cpu:
- if DNNL_LIB['DnnlMatrixElementwiseDivide']:
- cpu_matrix_elementwise_divide(
- input_vals[0], input_vals[1], output_val)
- else:
- output_val[:] = input_vals[0].asnumpy() / \
- input_vals[1].asnumpy()
- else:
- matrix_elementwise_divide(
- input_vals[0], input_vals[1], output_val, stream_handle)
-
- def gradient(self, output_grad):
- dividend_grad = div_const_op(1, self.inputs[1], ctx=self.raw_ctx)
- divisor_grad = opposite_op(div_op(div_op(
- self.inputs[0], self.inputs[1], ctx=self.raw_ctx), self.inputs[1], ctx=self.raw_ctx))
- return [dividend_grad * output_grad, divisor_grad * output_grad]
-
- def infer_shape(self, input_shapes):
- assert len(input_shapes) == 2
- assert input_shapes[0] == input_shapes[1], \
- "can't do elementwise division between variables of different sizes."
- output = input_shapes[0]
- return output
-
-
- class DivConstOp(Op):
- def __init__(self, const_val, node_A, ctx=None):
- super().__init__(DivConstOp, [node_A], ctx)
- self.const_attr = const_val
-
- def compute(self, input_vals, output_val, stream_handle=None):
- if self.on_cpu:
- if DNNL_LIB['DnnlMatrixElementwiseDivideByConst']:
- cpu_matrix_elementwise_divide_by_const(
- input_vals[0], self.const_attr, output_val)
- else:
- output_val[:] = self.const_attr / input_vals[0].asnumpy()
- else:
- matrix_elementwise_divide_const(
- self.const_attr, input_vals[0], output_val, stream_handle)
-
- def gradient(self, output_grad):
- divisor_grad = div_op(div_const_op(-self.const_attr,
- self.inputs[0], ctx=self.raw_ctx), self.inputs[0], ctx=self.raw_ctx)
- return [divisor_grad * output_grad]
-
- def infer_shape(self, input_shapes):
- assert len(input_shapes) == 1
- return input_shapes[0]
-
-
- def div_op(node_A, node_B, ctx=None):
- """Make a new instance of matrixs elementwise division and call the instance.
-
- Parameters:
- ----
- node_A : Node
- The Node where elements are numerators.
- node_B : Node
- Another Node where elements are denominators.
-
- Returns:
- ----
- A new Node instance created by Op.
-
- """
- return DivOp(node_A, node_B, ctx=ctx)
-
-
- def div_const_op(const_val, node_A, ctx=None):
- """Make a new instance of matrix elementwise devide a constant value and call the instance.
-
- Parameters:
- ----
- const_val: scalar value
- The constant value to be mutiplied.
- node_A : Node
- The Node where elements are denominators.
-
- Returns:
- ----
- A new Node instance created by Op.
-
- """
- return DivConstOp(const_val, node_A, ctx=ctx)
|