Unverified Commit 0460fba9 authored by Peter Doak's avatar Peter Doak Committed by GitHub
Browse files

Merge pull request #192 from gbalduzz/rb_tree

Unify CT-INT vertex selection with RB tree
parents af70bd20 89bcab05
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -174,6 +174,8 @@ separate_arguments(MPIEXEC_PREFLAGS UNIX_COMMAND ${MPIEXEC_PREFLAGS})

set(gtest_dir "${PROJECT_SOURCE_DIR}/libs/googletest-1.8.0" CACHE PATH "Path to Google Test.")
mark_as_advanced(gtest_dir)
set(benchmark_dir "${PROJECT_SOURCE_DIR}/libs/benchmark" CACHE PATH "Path to Google Benchmark.")
mark_as_advanced(benchmark_dir)

if (DCA_WITH_TESTS_FAST OR DCA_WITH_TESTS_EXTENSIVE OR  DCA_WITH_TESTS_STOCHASTIC OR
    DCA_WITH_TESTS_PERFORMANCE)
@@ -186,16 +188,20 @@ if (DCA_WITH_TESTS_FAST OR DCA_WITH_TESTS_EXTENSIVE OR DCA_WITH_TESTS_STOCHASTI
    message(WARNING "Tests are built with NDEBUG defined!")
  endif()

  if (DCA_WITH_TESTS_PERFORMANCE AND NOT (CMAKE_BUILD_TYPE STREQUAL "Release"))
  set(BENCHMARK_ENABLE_TESTING OFF)
  add_subdirectory(${gtest_dir})
  add_subdirectory(${PROJECT_SOURCE_DIR}/test)

  if (DCA_WITH_TESTS_PERFORMANCE)
    if(NOT (CMAKE_BUILD_TYPE STREQUAL "Release"))
      message(WARNING "Performance tests are only built in release mode.")
    endif()
    add_subdirectory(${benchmark_dir})
  endif()

  if (DCA_HAVE_MPI AND (TEST_RUNNER STREQUAL ""))
    message(FATAL_ERROR "TEST_RUNNER needs to be set to the command for executing MPI programs, e.g. mpiexec, mpirun, aprun or srun.")
  endif()

  add_subdirectory(${gtest_dir})
  add_subdirectory(${PROJECT_SOURCE_DIR}/test)
endif()

################################################################################
+31 −0
Original line number Diff line number Diff line
################################################################################
# Author: Urs R. Haehner (haehneru@itp.phys.ethz.ch)
#         Giovanni Balduzzi (gbalduzz@itp.phys.ethz.ch)
#
# Enables testing.
# References: - https://github.com/ALPSCore/ALPSCore
@@ -140,3 +141,33 @@ function(dca_add_gtest name)
  endif()

endfunction()

# Adds a performance test written with the Google benchmark.
#
# dca_add_gtest(name
#               [INCLUDE_DIRS dir1 [dir2 ...]]
#               [LIBS lib1 [lib2 ...]])
#
# If DCA_WITH_TESTS_PERFORMANCE is defined, adds a test called 'name', the source is assumed to be
# 'name.cpp'.

function(dca_add_perftest name)
  set(multiValueArgs INCLUDE_DIRS LIBS)
  cmake_parse_arguments(DCA_ADD_GTEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

  if (NOT DCA_WITH_TESTS_PERFORMANCE)
    return()
  endif()

  add_executable(${name} ${name}.cpp)

  target_include_directories(${name} PRIVATE ${benchmark_dir}/include ${PROJECT_SOURCE_DIR}/include
                             ${DCA_ADD_PERFTEST_INCLUDE_DIRS})


  target_link_libraries(${name} PRIVATE ${DCA_ADD_PERFTEST_LIBS};gtest benchmark_main benchmark)

  target_compile_definitions(${name} PRIVATE DCA_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\")
endfunction()

+13 −63
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "dca/phys/dca_step/cluster_solver/ctint/structs/interaction_vertices.hpp"
#include "dca/phys/dca_step/cluster_solver/ctint/structs/utils.hpp"
#include "dca/linalg/device_type.hpp"
#include "dca/util/containers/random_access_map.hpp"

namespace dca {
namespace phys {
@@ -50,11 +51,12 @@ public:
  void insertRandom(RngType& rng);

  // Returns the indices of the removal candidates. -1 stands for a missing candidate.
  template <class RngType>
  std::array<int, 2> randomRemovalCandidate(RngType& rng);

  // Similar to the above method, but sample vertices irrespective of their order.
  std::array<int, 2> randomRemovalCandidateSlow(const std::array<double, 3>& rng_vals);
  std::array<int, 2> randomRemovalCandidate(const std::array<double, 3>& rvals);
  // Similar to the method above.
  // Precondition: no double moves are proposed.
  std::array<int, 2> randomRemovalCandidate(double rval) {
    return randomRemovalCandidate({rval, -1, -1});
  }

  // Out: indices. Appends the result of the search to indices.
  template <class Alloc>
@@ -130,16 +132,17 @@ private:
  std::array<std::vector<ConfigRef>, 2> matrix_config_indices_;

  using BaseClass::H_int_;
  std::vector<std::vector<std::size_t>> existing_;

  // TODO: use a structure with fast (log N?) removal/insertion and random access.
  // Or sample randomly from std::unordered_set using its hash function, if it's good enough.
  std::vector<const std::vector<std::size_t>*> partners_lists_;
  std::vector<details::VertexTypeList> existing_;

  // Temporary storage for the removal candidate method.
  std::vector<const details::VertexTypeList*> partners_lists_;

  unsigned short last_insertion_size_ = 1;
  const double max_tau_ = 0;
  const int n_bands_ = 0;

  unsigned n_annihilatable_ = 0;
  dca::util::RandomAccessMap<std::size_t, unsigned> anhilatable_indices_;
  std::uint64_t current_tag_ = 0;
};

@@ -165,59 +168,6 @@ void SolverConfiguration::insertRandom(Rng& rng) {
  assert(2 * size() == getSector(0).size() + getSector(1).size());
}

template <class RngType>
std::array<int, 2> SolverConfiguration::randomRemovalCandidate(RngType& rng) {
  std::array<int, 2> candidates{-1, -1};
  if (n_annihilatable_ == 0)
    return candidates;

  // Note:
  // When sampling by retrying in case of failure, the probability of success is p_s n /
  // n_annihlatable, with n = size(). This translates to an expected cost of \sum_l l p_s (1 -
  // p_s)^(l - 1) = 1 / p_s. Therefore this algorithm is faster than a read on all the
  // vertices when n_annihlatable > cost(random _number) / cost(vertex_read).

  // Lets assume cost(random _number) / cost(vertex_read) =~ 10
  // This also helps when testing on a small configuration as we need only one random number.
  constexpr unsigned threshold = 10;

  if (n_annihilatable_ >= threshold) {
    do {
      candidates[0] = rng() * size();
    } while (!vertices_[candidates[0]].annihilatable);
  }
  else {
    unsigned annihilatable_idx = rng() * n_annihilatable_;
    unsigned annihilatable_found = 0;
    for (int i = 0; i < vertices_.size(); ++i) {
      if (vertices_[i].annihilatable) {
        if (annihilatable_found == annihilatable_idx) {
          candidates[0] = i;
          break;
        }
        ++annihilatable_found;
      }
    }
  }

  if (doDoubleUpdate(rng) &&
      (*H_int_)[vertices_[candidates[0]].interaction_id].partners_id.size()) {  // Double removal.
    partners_lists_.clear();
    for (const auto& partner_id : (*H_int_)[vertices_[candidates[0]].interaction_id].partners_id)
      partners_lists_.push_back(&existing_[partner_id]);

    const auto tag = details::getRandomElement(partners_lists_, rng());
    if (tag != -1) {
      candidates[1] = findTag(tag);
      assert(candidates[1] < int(size()) && candidates[1] >= 0);
      assert(vertices_[candidates[1]].annihilatable);
    }
  }

  assert(candidates[0] < int(size()));
  return candidates;
}  // namespace ctint

template <class Rng>
bool SolverConfiguration::doDoubleUpdate(Rng& rng) const {
  if (double_insertion_prob_ == 0)
+6 −2
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <stdexcept>
#include <vector>

#include "dca/util/containers/random_access_set.hpp"

namespace dca {
namespace phys {
namespace solver {
@@ -22,8 +24,10 @@ namespace ctint {
namespace details {
// dca::phys::solver::ctint::details::

unsigned getRandomElement(const std::vector<const std::vector<std::size_t>*>& v_ptrs,
                          const double rand) noexcept;
using VertexTypeList = dca::util::RandomAccessSet<std::size_t, 16>;

std::size_t getRandomElement(const std::vector<const VertexTypeList*>& v_ptrs,
                          double rand) noexcept;

}  // namespace details
}  // namespace ctint
+2 −2
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ struct CtintWalkerChoicheSelector;

template <class Parameters, typename Real>
struct CtintWalkerChoicheSelector<linalg::CPU, Parameters, true, Real> {
  using type = CtintWalkerSubmatrixCpu<Parameters, Real, false>;
  using type = CtintWalkerSubmatrixCpu<Parameters, Real>;
};
template <class Parameters, typename Real>
struct CtintWalkerChoicheSelector<linalg::CPU, Parameters, false, Real> {
@@ -41,7 +41,7 @@ struct CtintWalkerChoicheSelector<linalg::CPU, Parameters, false, Real> {
#ifdef DCA_HAVE_CUDA
template <class Parameters, typename Real>
struct CtintWalkerChoicheSelector<linalg::GPU, Parameters, true, Real> {
  using type = CtintWalkerSubmatrixGpu<Parameters, Real, false>;
  using type = CtintWalkerSubmatrixGpu<Parameters, Real>;
};

template <class Parameters, typename Real>
Loading