@@ -44,89 +44,6 @@ namespace ir {
44
44
GET_IR_NODE_FROM_SUBGRAPH (bn_saved_mean, bn_saved_mean, pattern_name); \
45
45
GET_IR_NODE_FROM_SUBGRAPH (bn_saved_variance, bn_saved_variance, pattern_name)
46
46
47
- template <typename UnaryOperation>
48
- LoDTensor tensor_apply (const LoDTensor& vec, UnaryOperation f) {
49
- LoDTensor vec_y;
50
- vec_y.Resize (vec.dims ());
51
- const float * x = vec.data <float >();
52
- float * y = vec_y.mutable_data <float >(platform::CPUPlace ());
53
- for (int64_t i = 0 ; i < vec.numel (); i++) {
54
- y[i] = f (x[i]);
55
- }
56
- return vec_y;
57
- }
58
-
59
- void tensor_apply_inplace (LoDTensor* vec, float (*f)(float )) {
60
- float * data = vec->mutable_data <float >(platform::CPUPlace ());
61
- for (int64_t i = 0 ; i < vec->numel (); i++) {
62
- data[i] = f (data[i]);
63
- }
64
- }
65
-
66
- template <typename BinaryOperation>
67
- LoDTensor tensor_apply_eltwise (const LoDTensor& vec_a, const LoDTensor& vec_b,
68
- BinaryOperation f) {
69
- PADDLE_ENFORCE_EQ (vec_a.dims (), vec_b.dims ());
70
- LoDTensor vec_y;
71
- vec_y.Resize (vec_a.dims ());
72
- const float * a = vec_a.data <float >();
73
- const float * b = vec_b.data <float >();
74
- float * y = vec_y.mutable_data <float >(platform::CPUPlace ());
75
- for (int64_t i = 0 ; i < vec_a.numel (); i++) {
76
- y[i] = f (a[i], b[i]);
77
- }
78
- return vec_y;
79
- }
80
-
81
- template <typename BinaryOperation>
82
- LoDTensor tensor_apply_eltwise_broadcast (const LoDTensor& vec_a,
83
- const LoDTensor& vec_b,
84
- BinaryOperation f) {
85
- PADDLE_ENFORCE_EQ (vec_a.dims ().size (), 2 );
86
- PADDLE_ENFORCE_EQ (vec_b.dims ().size (), 2 );
87
- PADDLE_ENFORCE_EQ (vec_a.dims ()[0 ], vec_b.dims ()[0 ]);
88
- PADDLE_ENFORCE_EQ (vec_b.dims ()[1 ], 1 );
89
- LoDTensor vec_y;
90
- vec_y.Resize (vec_a.dims ());
91
- const float * a = vec_a.data <float >();
92
- const float * b = vec_b.data <float >();
93
- float * y = vec_y.mutable_data <float >(platform::CPUPlace ());
94
- size_t a_height = vec_a.dims ()[0 ];
95
- size_t a_width = vec_a.dims ()[1 ];
96
- for (size_t h = 0 ; h < a_height; h++) {
97
- for (size_t w = 0 ; w < a_width; ++w) {
98
- *(y++) = f (*(a++), b[h]);
99
- }
100
- }
101
- return vec_y;
102
- }
103
-
104
- // reshape to two dimensions {A, B * C * ...}
105
- void make_tensor_2d (LoDTensor* tensor_to_reshape) {
106
- auto dims_count = tensor_to_reshape->dims ().size ();
107
- PADDLE_ENFORCE_GT (dims_count, 0 );
108
-
109
- int size2 = 1 ;
110
- for (int i = 1 ; i < dims_count; i++) {
111
- size2 *= tensor_to_reshape->dims ()[i];
112
- }
113
- tensor_to_reshape->Resize (make_ddim ({tensor_to_reshape->dims ()[0 ], size2}));
114
- }
115
-
116
- void recompute_conv_weights (LoDTensor* weights, LoDTensor* tmp) {
117
- // remember the weights tensor shape {A, B, C, ...}
118
- auto weights_shape = weights->dims ();
119
- // reduce the weights to 2d {A, B * C * ...}
120
- make_tensor_2d (weights);
121
- // make tmp tensor 2d by adding 1 as second dim {A, 1}
122
- make_tensor_2d (tmp);
123
-
124
- *weights =
125
- tensor_apply_eltwise_broadcast (*weights, *tmp, std::multiplies<float >());
126
- // reshape weights to the original dims {A, B, C, ...}
127
- weights->Resize (weights_shape);
128
- }
129
-
130
47
void recompute_bias_and_weights (const Scope* scope,
131
48
ir::Node* conv_weight, //
132
49
const ir::Node& bn_scale, //
@@ -135,6 +52,13 @@ void recompute_bias_and_weights(const Scope* scope,
135
52
const ir::Node& bn_variance, //
136
53
LoDTensor* eltwise_y_in_tensor, //
137
54
float epsilon) {
55
+ using EigenVectorArrayMap =
56
+ Eigen::Map<Eigen::Array<float , Eigen::Dynamic, 1 >>;
57
+ using ConstEigenVectorArrayMap =
58
+ Eigen::Map<const Eigen::Array<float , Eigen::Dynamic, 1 >>;
59
+ using EigenMatrixArrayMap = Eigen::Map<
60
+ Eigen::Array<float , Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>;
61
+
138
62
// Re-compute bias of conv2d from BN
139
63
PADDLE_ENFORCE_EQ (eltwise_y_in_tensor->dims (), bn_bias_tensor.dims ());
140
64
@@ -143,31 +67,38 @@ void recompute_bias_and_weights(const Scope* scope,
143
67
scope->FindVar (bn_variance.Name ())->GetMutable <LoDTensor>();
144
68
auto * mean_tensor = scope->FindVar (bn_mean.Name ())->GetMutable <LoDTensor>();
145
69
146
- auto std_tensor = LoDTensor ();
147
- std_tensor.Resize (bn_bias_tensor.dims ());
148
- std_tensor =
149
- tensor_apply (*variance_tensor, [&](float x) { return x + epsilon; });
70
+ ConstEigenVectorArrayMap scale_array (scale_tensor->data <float >(),
71
+ scale_tensor->numel (), 1 );
72
+ EigenVectorArrayMap variance_array (
73
+ variance_tensor->mutable_data <float >(platform::CPUPlace ()),
74
+ variance_tensor->numel (), 1 );
75
+ ConstEigenVectorArrayMap mean_array (mean_tensor->data <float >(),
76
+ mean_tensor->numel (), 1 );
77
+ ConstEigenVectorArrayMap bn_bias_array (bn_bias_tensor.data <float >(),
78
+ bn_bias_tensor.numel (), 1 );
150
79
151
- using EigenVectorArrayMap =
152
- Eigen::Map<Eigen::Array<float , Eigen::Dynamic, 1 >>;
80
+ // variance will not be used anymore, so make it std_array and then tmp_array
81
+ variance_array += epsilon;
82
+ variance_array = variance_array.sqrt ();
83
+ variance_array = scale_array / variance_array;
84
+
85
+ EigenVectorArrayMap eltwise_y_in_array (
86
+ eltwise_y_in_tensor->mutable_data <float >(platform::CPUPlace ()),
87
+ eltwise_y_in_tensor->numel (), 1 );
153
88
154
- EigenVectorArrayMap std_vec (
155
- std_tensor.mutable_data <float >(platform::CPUPlace ()), std_tensor.numel (),
156
- 1 );
157
- std_vec = std_vec.sqrt ();
158
- auto tmp_tensor =
159
- tensor_apply_eltwise (*scale_tensor, std_tensor, std::divides<float >());
160
- auto tensor_minus = tensor_apply_eltwise (*eltwise_y_in_tensor, *mean_tensor,
161
- std::minus<float >());
162
- auto tensor_mul =
163
- tensor_apply_eltwise (tensor_minus, tmp_tensor, std::multiplies<float >());
164
- *eltwise_y_in_tensor =
165
- tensor_apply_eltwise (tensor_mul, bn_bias_tensor, std::plus<float >());
89
+ eltwise_y_in_array =
90
+ ((eltwise_y_in_array - mean_array) * variance_array) + bn_bias_array;
166
91
167
92
// Re-compute weight of conv2d from BN
168
- auto * current_param =
169
- scope->FindVar (conv_weight->Name ())->GetMutable <LoDTensor>();
170
- recompute_conv_weights (current_param, &tmp_tensor);
93
+ auto * weights = scope->FindVar (conv_weight->Name ())->GetMutable <LoDTensor>();
94
+ auto weights_shape = weights->dims ();
95
+ auto weights_shape_2d = flatten_to_2d (weights_shape, 1 );
96
+
97
+ EigenMatrixArrayMap weights_array_2d (
98
+ weights->mutable_data <float >(platform::CPUPlace ()), weights_shape_2d[0 ],
99
+ weights_shape_2d[1 ]);
100
+
101
+ weights_array_2d.colwise () *= variance_array;
171
102
}
172
103
173
104
std::unique_ptr<ir::Graph> ConvBNFusePass::ApplyImpl (
0 commit comments