Small Beamformer optimization
* Don't use ConjugateDotProduct to calculate the norm.
* Only resize Matrix when needed.
This makes the Beamformer run in 93.6% the original time.
The error between the new and original output is really small and is caused by the new norm calculation.
R=andrew@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/37339004
Cr-Commit-Position: refs/heads/master@{#8438}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8438 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_processing/beamformer/beamformer.cc b/webrtc/modules/audio_processing/beamformer/beamformer.cc
index ced14d7..99fe846 100644
--- a/webrtc/modules/audio_processing/beamformer/beamformer.cc
+++ b/webrtc/modules/audio_processing/beamformer/beamformer.cc
@@ -95,9 +95,7 @@
for (int i = 0; i < norm_mat.num_columns(); ++i) {
for (int j = 0; j < norm_mat.num_columns(); ++j) {
- complex<float> cur_norm_element = conj(norm_mat_els[0][j]);
- complex<float> cur_mat_element = mat_els[j][i];
- first_product += cur_norm_element * cur_mat_element;
+ first_product += conj(norm_mat_els[0][j]) * mat_els[j][i];
}
second_product += first_product * norm_mat_els[0][i];
first_product = 0.f;
@@ -140,6 +138,19 @@
return sum_abs;
}
+// Calculates the sum of squares of a complex matrix.
+float SumSquares(const ComplexMatrix<float>& mat) {
+ float sum_squares = 0.f;
+ const complex<float>* const* mat_els = mat.elements();
+ for (int i = 0; i < mat.num_rows(); ++i) {
+ for (int j = 0; j < mat.num_columns(); ++j) {
+ float abs_value = std::abs(mat_els[i][j]);
+ sum_squares += abs_value * abs_value;
+ }
+ }
+ return sum_squares;
+}
+
} // namespace
Beamformer::Beamformer(const std::vector<Point>& array_geometry)
@@ -332,8 +343,7 @@
// angle.
for (int i = low_average_start_bin_; i < high_average_end_bin_; ++i) {
eig_m_.CopyFromColumn(input, i, num_input_channels_);
- float eig_m_norm_factor =
- std::sqrt(ConjugateDotProduct(eig_m_, eig_m_)).real();
+ float eig_m_norm_factor = std::sqrt(SumSquares(eig_m_));
if (eig_m_norm_factor != 0.f) {
eig_m_.Scale(1.f / eig_m_norm_factor);
}
diff --git a/webrtc/modules/audio_processing/beamformer/matrix.h b/webrtc/modules/audio_processing/beamformer/matrix.h
index e1891b6..3778fdb 100644
--- a/webrtc/modules/audio_processing/beamformer/matrix.h
+++ b/webrtc/modules/audio_processing/beamformer/matrix.h
@@ -76,7 +76,7 @@
// Copies |data| into the new Matrix.
Matrix(const T* data, int num_rows, int num_columns)
- : num_rows_(num_rows), num_columns_(num_columns) {
+ : num_rows_(0), num_columns_(0) {
CopyFrom(data, num_rows, num_columns);
scratch_data_.resize(num_rows_ * num_columns_);
scratch_elements_.resize(num_rows_);
@@ -91,15 +91,8 @@
// Copy |data| into the Matrix. The current data is lost.
void CopyFrom(const T* const data, int num_rows, int num_columns) {
- num_rows_ = num_rows;
- num_columns_ = num_columns;
- size_t size = num_rows_ * num_columns_;
-
- data_.assign(data, data + size);
- elements_.resize(num_rows_);
- for (int i = 0; i < num_rows_; ++i) {
- elements_[i] = &data_[i * num_columns_];
- }
+ Resize(num_rows, num_columns);
+ memcpy(&data_[0], data, num_rows_ * num_columns_ * sizeof(data_[0]));
}
Matrix& CopyFromColumn(const T* const* src, int column_index, int num_rows) {
@@ -112,9 +105,11 @@
}
void Resize(int num_rows, int num_columns) {
- num_rows_ = num_rows;
- num_columns_ = num_columns;
- Resize();
+ if (num_rows != num_rows_ || num_columns != num_columns_) {
+ num_rows_ = num_rows;
+ num_columns_ = num_columns;
+ Resize();
+ }
}
// Accessors and mutators.
@@ -136,8 +131,7 @@
// Matrix Operations. Returns *this to support method chaining.
Matrix& Transpose() {
CopyDataToScratch();
- std::swap(num_rows_, num_columns_);
- Resize();
+ Resize(num_columns_, num_rows_);
return Transpose(scratch_elements());
}
@@ -278,8 +272,7 @@
CHECK_EQ(num_columns_, rhs.num_rows_);
CopyDataToScratch();
- num_columns_ = rhs.num_columns_;
- Resize();
+ Resize(num_rows_, rhs.num_columns_);
return Multiply(scratch_elements(), rhs.num_rows_, rhs.elements());
}