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.

reduce_cpu_kernel.cc 6.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /**
  2. * Copyright 2020 Huawei Technologies Co., Ltd
  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. */
  16. #include <map>
  17. #include <string>
  18. #include <vector>
  19. #include "kernel/cpu/reduce_cpu_kernel.h"
  20. #include "device/cpu/cpu_device_address.h"
  21. namespace mindspore {
  22. namespace kernel {
  23. const size_t kReduceTypeMax = 0;
  24. const size_t kReduceTypeMean = 1;
  25. const size_t kReduceTypeSum = 2;
  26. const size_t kMaxDim = 100;
  27. void ReduceCPUKernel::InitKernel(const CNodePtr &kernel_node) {
  28. MS_EXCEPTION_IF_NULL(kernel_node);
  29. std::string kernel_name = AnfAlgo::GetCNodeName(kernel_node);
  30. if (kernel_name == "ReduceMax") {
  31. reduce_type_ = kReduceTypeMax;
  32. } else if (kernel_name == "ReduceMean") {
  33. reduce_type_ = kReduceTypeMean;
  34. } else if (kernel_name == "ReduceSum") {
  35. reduce_type_ = kReduceTypeSum;
  36. } else {
  37. MS_LOG(EXCEPTION) << "Array reduce kernel type " << kernel_name << " is not supported.";
  38. }
  39. shape_ = AnfAlgo::GetInputDeviceShape(kernel_node, 0);
  40. auto axis_addr = AnfAlgo::GetCNodePrimitive(kernel_node)->GetAttr(AXIS);
  41. if (axis_addr->isa<ValueTuple>()) {
  42. auto attr_axis = AnfAlgo::GetNodeAttr<std::vector<int>>(kernel_node, AXIS);
  43. if (attr_axis.size() > shape_.size()) {
  44. MS_LOG(EXCEPTION) << "invalid axis size: " << axis_.size();
  45. } else if (attr_axis.empty()) {
  46. axis_.push_back(shape_.size() - 1);
  47. } else {
  48. for (auto axis : attr_axis) {
  49. if (IntToSize(axis) >= (shape_.size())) {
  50. MS_LOG(EXCEPTION) << "axis value is oversize.";
  51. }
  52. axis < 0 ? axis_.push_back(axis + shape_.size()) : axis_.push_back(axis);
  53. }
  54. }
  55. } else if (axis_addr->isa<Int32Imm>()) {
  56. int axis = AnfAlgo::GetNodeAttr<int>(kernel_node, AXIS);
  57. if (axis >= 0 && IntToSize(axis) >= shape_.size()) {
  58. MS_LOG(EXCEPTION) << "axis value is oversize.";
  59. }
  60. axis < 0 ? axis_.push_back(axis + shape_.size()) : axis_.push_back(axis);
  61. } else {
  62. MS_LOG(EXCEPTION) << "Attribute axis type is invalid.";
  63. }
  64. for (size_t i = 0; i < shape_.size(); ++i) {
  65. if (shape_[i] <= 0) {
  66. MS_LOG(EXCEPTION) << "shape value is invalid.";
  67. }
  68. left_dims_ *= shape_[i];
  69. }
  70. for (size_t i = 0; i < axis_.size(); ++i) {
  71. stride_ *= shape_[axis_[i]];
  72. }
  73. if (stride_ <= 0) {
  74. MS_LOG(EXCEPTION) << "stride_ must greater than zero.";
  75. }
  76. left_dims_ = left_dims_ / stride_;
  77. }
  78. bool ReduceCPUKernel::Launch(const std::vector<kernel::AddressPtr> &inputs,
  79. const std::vector<kernel::AddressPtr> & /*workspaces*/,
  80. const std::vector<kernel::AddressPtr> &outputs) {
  81. if (inputs.empty() || outputs.empty()) {
  82. MS_LOG(EXCEPTION) << "input or output empty!";
  83. }
  84. size_t out_float_size = left_dims_ * sizeof(float);
  85. size_t in_float_size = stride_ * out_float_size;
  86. if (inputs[0]->size != in_float_size || outputs[0]->size != out_float_size) {
  87. MS_LOG(EXCEPTION) << "invalid input or output data size!";
  88. }
  89. auto input = reinterpret_cast<float *>(inputs[0]->addr);
  90. auto output = reinterpret_cast<float *>(outputs[0]->addr);
  91. int size = inputs[0]->size / sizeof(float);
  92. std::vector<float> new_input(IntToSize(size), 0.0);
  93. std::vector<size_t> transpose_axis;
  94. for (size_t i = 0; i < shape_.size(); ++i) {
  95. bool insert = true;
  96. for (size_t j = 0; j < axis_.size(); ++j) {
  97. if (axis_[j] == i) {
  98. insert = false;
  99. break;
  100. }
  101. }
  102. if (insert) {
  103. transpose_axis.push_back(i);
  104. }
  105. }
  106. (void)transpose_axis.insert(transpose_axis.end(), axis_.begin(), axis_.end());
  107. Transpose(size, input, shape_, transpose_axis, SizeToInt(shape_.size()), &new_input[0]);
  108. if (reduce_type_ == kReduceTypeMax) {
  109. for (size_t i = 0; i < left_dims_; ++i) {
  110. float value = new_input[i * stride_];
  111. for (size_t k = 0; k < stride_; ++k) {
  112. if (value < new_input[i * stride_ + k]) {
  113. value = new_input[i * stride_ + k];
  114. }
  115. }
  116. output[i] = value;
  117. }
  118. } else {
  119. for (size_t i = 0; i < left_dims_; ++i) {
  120. float value = 0.0;
  121. for (size_t k = 0; k < stride_; ++k) {
  122. value += new_input[i * stride_ + k];
  123. }
  124. if (reduce_type_ == kReduceTypeMean) {
  125. output[i] = value / stride_;
  126. } else {
  127. output[i] = value;
  128. }
  129. }
  130. }
  131. return true;
  132. }
  133. void ReduceCPUKernel::Transpose(const int size, const float *input, const std::vector<size_t> &input_shape,
  134. const std::vector<size_t> &input_axis, const int shape_size, float *output) {
  135. int pos_array[kMaxDim];
  136. int size_offset[kMaxDim];
  137. size_offset[0] = size / SizeToInt(input_shape[0]);
  138. for (int i = 1; i < shape_size; i++) {
  139. size_offset[i] = size_offset[i - 1] / SizeToInt(input_shape[i]);
  140. }
  141. for (int position = 0; position < size; position += 1) {
  142. int temp_position = position;
  143. pos_array[0] = temp_position / size_offset[0];
  144. for (int i = 1; i < shape_size; i++) {
  145. temp_position -= pos_array[i - 1] * size_offset[i - 1];
  146. pos_array[i] = temp_position / size_offset[i];
  147. }
  148. int new_position = pos_array[SizeToInt(input_axis[shape_size - 1])];
  149. int new_position_size = 1;
  150. for (int j = shape_size - 2; j >= 0; j--) {
  151. new_position_size *= SizeToInt(input_shape[SizeToInt(input_axis[j + 1])]);
  152. new_position += pos_array[SizeToInt(input_axis[j])] * new_position_size;
  153. }
  154. output[new_position] = input[position];
  155. }
  156. return;
  157. }
  158. } // namespace kernel
  159. } // namespace mindspore