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.

Reshape.py 4.5 kB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. from __future__ import absolute_import
  2. import ctypes
  3. from .Node import Op
  4. from .. import ndarray
  5. from .._base import DNNL_LIB
  6. from ..cpu_links import reshape as cpu_reshape
  7. from ..gpu_links import array_reshape
  8. class Array_ReshapeOp(Op):
  9. def __init__(self, node_A, output_shape, ctx=None):
  10. super().__init__(Array_ReshapeOp, [node_A], ctx)
  11. self.output_shape = output_shape
  12. def compute(self, input_vals, output_val, stream_handle=None):
  13. assert(len(input_vals) == 1)
  14. input_size = 1
  15. for i in range(len(input_vals[0].shape)):
  16. input_size *= input_vals[0].shape[i]
  17. # check if there exists -1 in output_shape
  18. idx = -1
  19. cnt = 0
  20. output_size = 1
  21. output_shape = list(self.output_shape)
  22. for i in range(len(output_shape)):
  23. if(output_shape[i] == -1):
  24. idx = i
  25. cnt = cnt + 1
  26. assert(cnt != 2)
  27. output_size *= output_shape[i]
  28. if(idx == -1):
  29. assert input_size == output_size
  30. else:
  31. output_size = output_size * (-1)
  32. assert (input_size % output_size == 0)
  33. output_shape[idx] = input_size // output_size
  34. output_shape = tuple(output_shape)
  35. if self.on_cpu:
  36. if DNNL_LIB['cpu_Reshape']:
  37. cpu_reshape(input_vals[0], output_val)
  38. else:
  39. output_val[:] = input_vals[0].asnumpy().reshape(output_shape)
  40. else:
  41. if self.inplace:
  42. input_vals[0].reshape(output_shape, output_val)
  43. else:
  44. array_reshape(input_vals[0], output_val, stream_handle)
  45. def gradient(self, output_grad):
  46. return [array_reshape_gradient_op(self.inputs[0], output_grad, ctx=self.raw_ctx)]
  47. def infer_shape(self, input_shapes):
  48. assert (len(input_shapes) == 1)
  49. input_size = 1
  50. input_shape = input_shapes[0]
  51. for i in range(len(input_shape)):
  52. input_size *= input_shape[i]
  53. # check if there exists -1 in output_shape
  54. idx = -1
  55. cnt = 0
  56. output_size = 1
  57. output_shape = list(self.output_shape)
  58. for i in range(len(output_shape)):
  59. if(output_shape[i] == -1):
  60. idx = i
  61. cnt = cnt + 1
  62. assert(cnt != 2)
  63. output_size *= output_shape[i]
  64. if(idx == -1):
  65. assert input_size == output_size
  66. else:
  67. output_size = output_size * (-1)
  68. assert (input_size % output_size == 0)
  69. output_shape[idx] = input_size // output_size
  70. output_shape = tuple(output_shape)
  71. return output_shape
  72. def backward_hook(self, config):
  73. self.inplace = config.enable_lazy and self not in config.eval_node_list
  74. class Array_Reshape_GradientOp(Op):
  75. def __init__(self, node_in, node_out, ctx=None):
  76. super().__init__(Array_Reshape_GradientOp, [node_in, node_out], ctx)
  77. def compute(self, input_vals, output_val, stream_handle=None):
  78. # the size of input_array
  79. shapeIn = input_vals[0].shape
  80. if self.on_cpu:
  81. if DNNL_LIB['cpu_Reshape']:
  82. cpu_reshape(input_vals[1], output_val)
  83. else:
  84. output_val[:] = input_vals[1].asnumpy().reshape(shapeIn)
  85. else:
  86. if self.inplace:
  87. input_vals[1].reshape(shapeIn, output_val)
  88. else:
  89. array_reshape(input_vals[1], output_val, stream_handle)
  90. def gradient(self, output_grad):
  91. raise NotImplementedError
  92. def infer_shape(self, input_shapes):
  93. return input_shapes[0]
  94. def backward_hook(self, config):
  95. self.inplace = config.enable_lazy and self not in config.eval_node_list
  96. def array_reshape_op(node, output_shape, ctx=None):
  97. """Reshapes an input array without copy.
  98. Parameters:
  99. ----
  100. node : Node
  101. Input variable.
  102. output_shape: tuple(int)
  103. Expected shape of the output array.
  104. Returns:
  105. ----
  106. A new Node instance created by Op.
  107. """
  108. return Array_ReshapeOp(node, output_shape, ctx=ctx)
  109. def array_reshape_gradient_op(node_in, node_out, ctx=None):
  110. """Gradient of reshape operation.
  111. Parameters:
  112. ----
  113. node_in : Node
  114. Input node of reshape operation.
  115. node_out: Node
  116. Previous gradient node.
  117. Returns:
  118. ----
  119. A new Node instance created by Op.
  120. """
  121. return Array_Reshape_GradientOp(node_in, node_out, ctx=ctx)