@@ -44,87 +44,16 @@ 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
47
// 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 ();
48
+ DDim make_dims_2d (DDim dims ) {
49
+ auto dims_count = dims.size ();
107
50
PADDLE_ENFORCE_GT (dims_count, 0 );
108
51
109
52
int size2 = 1 ;
110
53
for (int i = 1 ; i < dims_count; i++) {
111
- size2 *= tensor_to_reshape-> dims () [i];
54
+ size2 *= dims[i];
112
55
}
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);
56
+ return make_ddim ({dims[0 ], size2});
128
57
}
129
58
130
59
void recompute_bias_and_weights (const Scope* scope,
@@ -135,6 +64,13 @@ void recompute_bias_and_weights(const Scope* scope,
135
64
const ir::Node& bn_variance, //
136
65
LoDTensor* eltwise_y_in_tensor, //
137
66
float epsilon) {
67
+ using EigenVectorArrayMap =
68
+ Eigen::Map<Eigen::Array<float , Eigen::Dynamic, 1 >>;
69
+ using ConstEigenVectorArrayMap =
70
+ Eigen::Map<const Eigen::Array<float , Eigen::Dynamic, 1 >>;
71
+ using EigenMatrixArrayMap = Eigen::Map<
72
+ Eigen::Array<float , Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>;
73
+
138
74
// Re-compute bias of conv2d from BN
139
75
PADDLE_ENFORCE_EQ (eltwise_y_in_tensor->dims (), bn_bias_tensor.dims ());
140
76
@@ -143,31 +79,38 @@ void recompute_bias_and_weights(const Scope* scope,
143
79
scope->FindVar (bn_variance.Name ())->GetMutable <LoDTensor>();
144
80
auto * mean_tensor = scope->FindVar (bn_mean.Name ())->GetMutable <LoDTensor>();
145
81
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; });
82
+ ConstEigenVectorArrayMap scale_array (scale_tensor->data <float >(),
83
+ scale_tensor->numel (), 1 );
84
+ EigenVectorArrayMap variance_array (
85
+ variance_tensor->mutable_data <float >(platform::CPUPlace ()),
86
+ variance_tensor->numel (), 1 );
87
+ ConstEigenVectorArrayMap mean_array (mean_tensor->data <float >(),
88
+ mean_tensor->numel (), 1 );
89
+ ConstEigenVectorArrayMap bn_bias_array (bn_bias_tensor.data <float >(),
90
+ bn_bias_tensor.numel (), 1 );
150
91
151
- using EigenVectorArrayMap =
152
- Eigen::Map<Eigen::Array<float , Eigen::Dynamic, 1 >>;
92
+ // variance will not be used anymore, so make it std_array and then tmp_array
93
+ variance_array += epsilon;
94
+ variance_array = variance_array.sqrt ();
95
+ variance_array = scale_array / variance_array;
96
+
97
+ EigenVectorArrayMap eltwise_y_in_array (
98
+ eltwise_y_in_tensor->mutable_data <float >(platform::CPUPlace ()),
99
+ eltwise_y_in_tensor->numel (), 1 );
153
100
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 >());
101
+ eltwise_y_in_array =
102
+ ((eltwise_y_in_array - mean_array) * variance_array) + bn_bias_array;
166
103
167
104
// 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);
105
+ auto * weights = scope->FindVar (conv_weight->Name ())->GetMutable <LoDTensor>();
106
+ auto weights_shape = weights->dims ();
107
+ auto weights_shape_2d = make_dims_2d (weights_shape);
108
+
109
+ EigenMatrixArrayMap weights_array_2d (
110
+ weights->mutable_data <float >(platform::CPUPlace ()), weights_shape_2d[0 ],
111
+ weights_shape_2d[1 ]);
112
+
113
+ weights_array_2d.colwise () *= variance_array;
171
114
}
172
115
173
116
std::unique_ptr<ir::Graph> ConvBNFusePass::ApplyImpl (
0 commit comments