From: Martin Kronbichler <kronbichler@lnm.mw.tum.de> Date: Wed, 31 Aug 2016 13:40:00 +0000 (+0200) Subject: Fix bad complexity in copy of sparsity pattern. X-Git-Tag: v8.5.0-rc1~720^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=02ed7aca6ea07e5ca7d0d42bab564ba3fee1e758;p=dealii.git Fix bad complexity in copy of sparsity pattern. --- diff --git a/doc/news/changes.h b/doc/news/changes.h index 690883db30..cfef367ed0 100644 --- a/doc/news/changes.h +++ b/doc/news/changes.h @@ -236,15 +236,15 @@ inconvenience this causes. <li> New: Added a new PolarManifold descriptor, that uses a polar coordinate - system to compute new points, and modified the existing SphericalManifold - descriptor to use geodesics on the surface of the sphere. + system to compute new points, and modified the existing SphericalManifold + descriptor to use geodesics on the surface of the sphere. <br> (Luca Heltai, Mauro Bardelloni, 2016/08/04) </li> <li> - New: Added Python bindings to generate and manipulate a Triangulation from - Python. The Triangulation generated in Python can be saved and later, loaded + New: Added Python bindings to generate and manipulate a Triangulation from + Python. The Triangulation generated in Python can be saved and later, loaded inside a C++ code. <br> (Bruno Turcksin, 2016/08/03) @@ -495,6 +495,14 @@ inconvenience this causes. <h3>Specific improvements</h3> <ol> + <li> Improved: SparsityPattern::copy_from() copying from a + DynamicSparsityPattern argument had quadratic complexity in the number of + rows for sparsity patterns where most of the rows are of length zero. The bad + algorithm has been replaced by a linear complexity one. + <br> + (Dustin Kumor, Martin Kronbichler, 2016/08/31) + </li> + <li> New: Rank-4 symmetric tensors of type SymmetricTensor can now be converted to rank-4 tensors of type Tensor. <br> diff --git a/source/lac/sparsity_pattern.cc b/source/lac/sparsity_pattern.cc index 501b4878ed..80fe41db7b 100644 --- a/source/lac/sparsity_pattern.cc +++ b/source/lac/sparsity_pattern.cc @@ -523,6 +523,46 @@ SparsityPattern::copy_from (const SparsityPatternType &dsp) +// Use a special implementation for DynamicSparsityPattern where we can use +// the column_number method to gain faster access to the +// entries. DynamicSparsityPattern::iterator can show quadratic complexity in +// case many rows are empty and the begin() method needs to jump to the next +// free row. Otherwise, the code is exactly the same as above. +template <> +void +SparsityPattern::copy_from (const DynamicSparsityPattern &dsp) +{ + const bool do_diag_optimize = (dsp.n_rows() == dsp.n_cols()); + std::vector<unsigned int> row_lengths (dsp.n_rows()); + for (size_type i=0; i<dsp.n_rows(); ++i) + { + row_lengths[i] = dsp.row_length(i); + if (do_diag_optimize && !dsp.exists(i,i)) + ++row_lengths[i]; + } + reinit (dsp.n_rows(), dsp.n_cols(), row_lengths); + + if (n_rows() != 0 && n_cols() != 0) + for (size_type row = 0; row<dsp.n_rows(); ++row) + { + size_type *cols = &colnums[rowstart[row]] + (do_diag_optimize ? 1 : 0); + const unsigned int row_length = dsp.row_length(row); + for (unsigned int index=0; index < row_length; ++index) + { + const size_type col = dsp.column_number(row, index); + if ((col!=row) || !do_diag_optimize) + *cols++ = col; + } + } + + // do not need to compress the sparsity pattern since we already have + // allocated the right amount of data, and the SparsityPatternType data is sorted, + // too. + compressed = true; +} + + + template <typename number> void SparsityPattern::copy_from (const FullMatrix<number> &matrix) { @@ -998,7 +1038,6 @@ SparsityPattern::memory_consumption () const // explicit instantiations template void SparsityPattern::copy_from<SparsityPattern> (const SparsityPattern &); -template void SparsityPattern::copy_from<DynamicSparsityPattern> (const DynamicSparsityPattern &); template void SparsityPattern::copy_from<float> (const FullMatrix<float> &); template void SparsityPattern::copy_from<double> (const FullMatrix<double> &);