From: Denis Davydov Date: Wed, 6 Feb 2019 13:18:56 +0000 (+0100) Subject: use binary search in BlockIndices::global_to_local() X-Git-Tag: v9.1.0-rc1~367^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F7699%2Fhead;p=dealii.git use binary search in BlockIndices::global_to_local() --- diff --git a/doc/news/changes/minor/20190206DenisDavydov b/doc/news/changes/minor/20190206DenisDavydov new file mode 100644 index 0000000000..73aa3ed586 --- /dev/null +++ b/doc/news/changes/minor/20190206DenisDavydov @@ -0,0 +1,4 @@ +Improved: Use binary search in BlockIndices::global_to_local() to improve performance +for large number of blocks. +
+(Denis Davydov, 2019/02/06) diff --git a/include/deal.II/lac/block_indices.h b/include/deal.II/lac/block_indices.h index 6ada38375a..ef81f81c6e 100644 --- a/include/deal.II/lac/block_indices.h +++ b/include/deal.II/lac/block_indices.h @@ -333,11 +333,11 @@ BlockIndices::global_to_local(const size_type i) const Assert(i < total_size(), ExcIndexRangeType(i, 0, total_size())); Assert(n_blocks > 0, ExcLowerRangeType(i, size_type(1))); - unsigned int block = n_blocks - 1; - while (i < start_indices[block]) - --block; + // start_indices[0] == 0 so we might as well start from the next one + const auto it = + --std::upper_bound(++start_indices.begin(), start_indices.end(), i); - return {block, i - start_indices[block]}; + return {std::distance(start_indices.begin(), it), i - *it}; } diff --git a/tests/lac/block_indices_02.cc b/tests/lac/block_indices_02.cc new file mode 100644 index 0000000000..0d2cc2c4bd --- /dev/null +++ b/tests/lac/block_indices_02.cc @@ -0,0 +1,60 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2019 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE.md at +// the top level directory of deal.II. +// +// --------------------------------------------------------------------- + + +// Test BlockIndices::global_to_local() for very large number of blocks + +#include + +#include "../tests.h" + + + +void +test() +{ + constexpr unsigned int n_blocks = 10000; + constexpr types::global_dof_index block_size = 3; + constexpr types::global_dof_index size = n_blocks * block_size; + BlockIndices idx(n_blocks, block_size); + + const std::vector is = {{0, + 1, + block_size * 500 + 2, + block_size * 600, + block_size * 701 - 1, + size - 1}}; + + deallog << "n_blocks: " << n_blocks << std::endl + << "block_size: " << block_size << std::endl + << "size: " << idx.size() << std::endl; + for (auto i : is) + { + const auto p = idx.global_to_local(i); + AssertDimension(p.first, i / block_size); + AssertDimension(p.second, i % block_size); + deallog << i << " -> (" << p.first << "," << p.second << ")" << std::endl; + } + + deallog << std::endl; +} + + +int +main() +{ + initlog(); + test(); +} diff --git a/tests/lac/block_indices_02.output b/tests/lac/block_indices_02.output new file mode 100644 index 0000000000..6265aaf466 --- /dev/null +++ b/tests/lac/block_indices_02.output @@ -0,0 +1,11 @@ + +DEAL::n_blocks: 10000 +DEAL::block_size: 3 +DEAL::size: 10000 +DEAL::0 -> (0,0) +DEAL::1 -> (0,1) +DEAL::1502 -> (500,2) +DEAL::1800 -> (600,0) +DEAL::2102 -> (700,2) +DEAL::29999 -> (9999,2) +DEAL::