| 69 | } |
| 70 | |
| 71 | struct BNOps : public NodeOps |
| 72 | { |
| 73 | BNOps() |
| 74 | { |
| 75 | name_ = "arm_batchnorm_fp32"; |
| 76 | } |
| 77 | |
| 78 | bool OnBind(Node* node) |
| 79 | { |
| 80 | // set the inplace feature |
| 81 | inplace_t io_map; |
| 82 | |
| 83 | io_map[0] = 0; |
| 84 | |
| 85 | node->SetAttr(ATTR_INPLACE, io_map); |
| 86 | |
| 87 | return true; |
| 88 | } |
| 89 | |
| 90 | bool Prerun(Node* node) |
| 91 | { |
| 92 | const Tensor* mean_tensor = node->GetInputTensor(3); |
| 93 | const TShape& shape = mean_tensor->GetShape(); |
| 94 | |
| 95 | const std::vector<int> dims = shape.GetDim(); |
| 96 | |
| 97 | int channel_num = dims[0]; |
| 98 | |
| 99 | float* scale_mean = ( float* )mem_alloc(channel_num * sizeof(float)); |
| 100 | float* scale_var_inv = ( float* )mem_alloc(channel_num * sizeof(float)); |
| 101 | |
| 102 | const Tensor* var_tensor = node->GetInputTensor(4); |
| 103 | const float* mean = ( const float* )get_tensor_mem(mean_tensor); |
| 104 | const float* var = ( const float* )get_tensor_mem(var_tensor); |
| 105 | |
| 106 | BatchNorm* bn_op = dynamic_cast<BatchNorm*>(node->GetOp()); |
| 107 | BatchNormParam* param = bn_op->GetParam(); |
| 108 | |
| 109 | float rescale_factor; |
| 110 | float eps = param->eps; |
| 111 | |
| 112 | rescale_factor = param->rescale_factor ? 1 / param->rescale_factor : 0; |
| 113 | for(int c = 0; c < channel_num; c++) |
| 114 | { |
| 115 | float tmp = std::sqrt(var[c] * rescale_factor + eps); |
| 116 | scale_var_inv[c] = (float)(1.f / tmp); |
| 117 | tmp = rescale_factor * scale_var_inv[c]; |
| 118 | scale_mean[c] = (float)(-mean[c] * tmp); |
| 119 | } |
| 120 | if(!param->caffe_flavor) |
| 121 | { |
| 122 | const Tensor* gamma_tensor = node->GetInputTensor(1); |
| 123 | const Tensor* beta_tensor = node->GetInputTensor(2); |
| 124 | const float* gamma = ( const float* )get_tensor_mem(gamma_tensor); |
| 125 | const float* beta = ( const float* )get_tensor_mem(beta_tensor); |
| 126 | for(int c = 0; c < channel_num; c++) |
| 127 | { |
| 128 | scale_var_inv[c] *= gamma[c]; |
nothing calls this directly
no outgoing calls
no test coverage detected