Commit 40f33c9b authored by COULAUD Olivier's avatar COULAUD Olivier
Browse files

Add distributed tree

parent 3e969814
......@@ -14,8 +14,8 @@
#include "scalfmm/matrix_kernels/laplace.hpp"
#include "scalfmm/tree/cell.hpp"
#include "scalfmm/tree/dist_group_tree.hpp"
#include "scalfmm/tree/group_let.hpp"
#include "scalfmm/tree/group_tree.hpp"
#include "scalfmm/tree/leaf.hpp"
#include "scalfmm/utils/parallel_manager.hpp"
......@@ -25,10 +25,38 @@
/// \return
///
///
/// ./examples/RelWithDebInfo/test-build-let --input-file ../data/prolate.fma --order 3 --tree-height 4 --group-size 3
/// mpirun --oversubscribe -np 3 ./examples/RelWithDebInfo/test-build-let --input-file ../buildMPI/prolate.fma --order
/// 3 --tree-height 3 --group-size 3
/// ./examples/RelWithDebInfo/test-build-let --input-file ../data/prolate.fma
/// --order 3 --tree-height 4 --group-size 3
/// mpirun --oversubscribe -np 3 ./examples/RelWithDebInfo/test-build-let
/// --input-file ../buildMPI/prolate.fma --order 3 --tree-height 3
/// --group-size 3
namespace local_args
{
struct PartDistrib
{
/// Unused type, mandatory per interface specification
using type = bool;
/// The parameter is a flag, it doesn't expect a following value
enum
{
flagged
};
inria::tcli::str_vec flags = {"--dist_part"};
std::string description = "Use the particle distribution to distribute the tree";
};
struct PartLeafDistrib
{
/// Unused type, mandatory per interface specification
using type = bool;
/// The parameter is a flag, it doesn't expect a following value
enum
{
flagged
};
inria::tcli::str_vec flags = {"--dist_part_leaf"};
std::string description = "Use two distribution one for the particle and one for the tree";
};
} // namespace local_args
auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
{
parallel_manager para;
......@@ -58,13 +86,14 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
using cell_type = scalfmm::component::cell<typename interpolator_type::storage_type>;
using leaf_type = scalfmm::component::leaf<particle_type>;
using box_type = scalfmm::component::box<position_type>;
using group_tree_type = scalfmm::component::group_tree<cell_type, leaf_type, box_type>;
using group_tree_type = scalfmm::component::dist_group_tree<cell_type, leaf_type, box_type>;
//
// Parameter handling
auto parser = inria::tcli::make_parser(inria::tcli::help{}, args::input_file(), args::output_file(),
args::tree_height{}, args::order{}, // args::thread_count{},
args::block_size{}, args::log_file{}, args::log_level{});
args::block_size{}, args::log_file{}, args::log_level{},
local_args::PartDistrib{}, local_args::PartLeafDistrib{});
parser.parse(argc, argv);
// Getting command line parameters
const int tree_height{parser.get<args::tree_height>()};
......@@ -86,6 +115,11 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
<< '\n';
}
const auto order{parser.get<args::order>()};
bool use_particle_distribution{parser.exists<local_args::PartDistrib>()};
bool use_leaf_distribution{!use_particle_distribution};
bool use_both_distribution{parser.exists<local_args::PartLeafDistrib>()};
//
//
......@@ -146,6 +180,11 @@ auto main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) -> int
#ifdef SCALFMM_USE_MPI
para.get_communicator().barrier();
if(para.io_master())
{
letGroupTree->print_distrib(std::cout);
}
std::this_thread::sleep_for(std::chrono::seconds(2));
#endif
......
// --------------------------------
// See LICENCE file at project root
// File : group_tree.hpp
// --------------------------------
#ifndef SCALFMM_TREE_DIST_GROUP_TREE_HPP
#define SCALFMM_TREE_DIST_GROUP_TREE_HPP
#include <array>
#include <bits/c++config.h>
#include <fstream>
#include <iostream>
#include <vector>
#include "scalfmm/tree/box.hpp"
#include <scalfmm/tree/group_let.hpp>
#include <scalfmm/tree/group_tree.hpp>
#include <scalfmm/utils/io_helpers.hpp>
namespace scalfmm::component
{
template<typename Cell, typename Leaf, typename Box = box<typename Leaf::position_type>>
class dist_group_tree : public group_tree<Cell, Leaf, Box>
{
public:
using morton_type = std::int64_t;
using data_distrib_type = std::array<morton_type, 2>;
using base_type = group_tree<Cell, Leaf, Box>;
/// Constructor
template<typename ParticleContainer>
explicit dist_group_tree(std::size_t tree_height, std::size_t order, Box const& box,
std::size_t number_of_component_per_group, ParticleContainer const& particle_container,
bool particles_are_sorted = false, int in_top_level = 2, int in_left_limit = -1)
: base_type(tree_height, order, box, number_of_component_per_group, particle_container, particles_are_sorted,
in_top_level, in_left_limit)
{
m_cell_distrib.resize(tree_height);
}
void set_leaf_distribution(const std::vector<data_distrib_type>& in_leaf_distrib)
{
m_leaf_distrib = in_leaf_distrib;
}
void set_cell_distribution(const int in_level, const std::vector<data_distrib_type>& in_cell_distrib)
{
m_cell_distrib[in_level] = in_cell_distrib;
}
void print_distrib(std::ostream& out, bool verbose = true)
{
std::string header;
if(verbose)
{
header = "leaf distribution: \n";
}
out::print(out, std::move(header), m_leaf_distrib);
for(int l = base_type::leaf_level(); l >= base_type::top_level(); --l)
{
std::cout << " print " << l << std::endl;
if(verbose)
{
header = "Level " + std::to_string(l) + " cell distribution: \n";
}
out::print(out, std::move(header), m_cell_distrib[l]);
}
}
private:
std::vector<std::vector<data_distrib_type>> m_cell_distrib;
std::vector<data_distrib_type> m_leaf_distrib;
};
} // namespace scalfmm::component
#endif
......@@ -1512,6 +1512,8 @@ namespace scalfmm::tree
///
/// Find and add the leaves to add at the leaves level
build_let_leaves(manager, *localGroupTree, leafMortonIdx, particles_distrib, leaves_distrib);
localGroupTree->set_leaf_distribution(leaves_distrib);
/// If the distribution is not the same for the leaf and the cell we have to redistribute the
/// morton index according to the good distribution
/// Todo inria::dist::distribute()
......@@ -1532,7 +1534,7 @@ namespace scalfmm::tree
/// Find and add the cells to add at the leaves level
build_let_at_level(manager, *localGroupTree, leafMortonIdx, leaves_distrib, level_dist[leaf_level],
leaf_level);
localGroupTree->set_cell_distribution(leaf_level, leaves_distrib);
for(int l = leaf_level - 1; l >= localGroupTree->top_level(); --l)
{
std::cout << "level: " << l << " leaf_level " << leaf_level << "ttp" << localGroupTree->top_level()
......@@ -1541,6 +1543,7 @@ namespace scalfmm::tree
std::move(distrib::build_upper_distribution(manager, l, leafMortonIdx, level_dist[l + 1]));
out::print("rank(" + std::to_string(rank) + ") leafMortonIdx: ", leafMortonIdx);
build_let_at_level(manager, *localGroupTree, leafMortonIdx, leaves_distrib, level_dist[l], l);
localGroupTree->set_cell_distribution(l, level_dist[l]);
}
}
#ifdef SCALFMM_USE_MPI
......
......@@ -5,7 +5,8 @@
#include "inria/ostream_joiner.hpp"
#include <array>
#include <ostream>
#include <fstream>
#include <iostream>
#include <tuple>
namespace scalfmm
......@@ -120,6 +121,14 @@ namespace scalfmm
std::cout << i << ' ';
std::cout << '\n';
};
template<typename Vector_type>
void print(std::ostream& out, const std::string&& title, Vector_type& v)
{
out << title << " (" << v.size() << ") ";
for(auto& i: v)
out << i << ' ';
out << '\n';
};
template<typename Iterator_type>
///
/// \brief print print a vector and its size starting at first and endig at end
......@@ -140,6 +149,15 @@ namespace scalfmm
std::cout << *it << ' ';
std::cout << '\n';
};
template<typename Iterator_type>
void print(std::ofstream& out, const std::string&& title, Iterator_type first, Iterator_type last)
{
out << title << " (" << std::distance(first, last) << ") ";
for(Iterator_type it = first; it != last; ++it)
out << *it << ' ';
out << '\n';
};
} // namespace out
} // namespace scalfmm
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment