more optimizations, using boost any and factoring out kd tree, adding metis check

This commit is contained in:
Dmitry Anisimov 2021-05-05 13:17:23 +02:00
parent fb8538393d
commit 3c0fc281e8
3 changed files with 73 additions and 30 deletions

View File

@ -1,6 +1,7 @@
if(METIS_FOUND AND NOT TARGET CGAL::METIS_support) if(METIS_FOUND AND NOT TARGET CGAL::METIS_support)
add_library(CGAL::METIS_support INTERFACE IMPORTED) add_library(CGAL::METIS_support INTERFACE IMPORTED)
set_target_properties(CGAL::METIS_support PROPERTIES set_target_properties(CGAL::METIS_support PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "CGAL_METIS_ENABLED"
INTERFACE_INCLUDE_DIRECTORIES "${METIS_INCLUDE_DIRS}" INTERFACE_INCLUDE_DIRECTORIES "${METIS_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${METIS_LIBRARIES}") INTERFACE_LINK_LIBRARIES "${METIS_LIBRARIES}")
endif() endif()

View File

@ -123,6 +123,14 @@ if(OpenMesh_FOUND)
PRIVATE ${OPENMESH_LIBRARIES}) PRIVATE ${OPENMESH_LIBRARIES})
endif(OpenMesh_FOUND) endif(OpenMesh_FOUND)
find_package(METIS)
include(CGAL_METIS_support)
if(TARGET CGAL::METIS_support)
target_link_libraries(hausdorff_bounded_error_distance_example PUBLIC CGAL::METIS_support)
else()
message(STATUS "Tests, which use the METIS library will not be compiled.")
endif()
find_package(TBB) find_package(TBB)
include(CGAL_TBB_support) include(CGAL_TBB_support)
if(TARGET CGAL::TBB_support) if(TARGET CGAL::TBB_support)

View File

@ -31,8 +31,10 @@
#include <CGAL/spatial_sort.h> #include <CGAL/spatial_sort.h>
#include <CGAL/Real_timer.h> #include <CGAL/Real_timer.h>
#include <CGAL/boost/graph/partition.h> // METIS related
#include <CGAL/boost/graph/Face_filtered_graph.h> #include <CGAL/boost/graph/Face_filtered_graph.h>
#if defined(CGAL_METIS_ENABLED)
#include <CGAL/boost/graph/partition.h>
#endif // CGAL_METIS_ENABLED
#ifdef CGAL_LINKED_WITH_TBB #ifdef CGAL_LINKED_WITH_TBB
#include <tbb/parallel_reduce.h> #include <tbb/parallel_reduce.h>
@ -41,6 +43,7 @@
#endif // CGAL_LINKED_WITH_TBB #endif // CGAL_LINKED_WITH_TBB
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include <boost/any.hpp>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
@ -1656,31 +1659,48 @@ double bounded_error_Hausdorff_impl(
return hdist; return hdist;
} }
// TODO: && METIS! #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_METIS_ENABLED)
#if defined(CGAL_LINKED_WITH_TBB)
template< class TriangleMesh1, template<class TriangleMesh, class VPM, class TMTree>
class VPM1, struct Triangle_mesh_wrapper {
class TM1Tree,
class Kernel> const TriangleMesh& tm; const VPM& vpm;
const bool is_tm2; TMTree& tm_tree;
Triangle_mesh_wrapper(
const TriangleMesh& tm, const VPM& vpm,
const bool is_tm2, TMTree& tm_tree) :
tm(tm), vpm(vpm), is_tm2(is_tm2), tm_tree(tm_tree) { }
void build_tree() {
tm_tree.insert(faces(tm).begin(), faces(tm).end(), tm, vpm);
tm_tree.build();
if (is_tm2) tm_tree.accelerate_distance_queries();
else tm_tree.do_not_accelerate_distance_queries();
}
};
template<class TM1Wrapper, class TM2Wrapper>
struct Bounded_error_preprocessing { struct Bounded_error_preprocessing {
using Timer = CGAL::Real_timer; using Timer = CGAL::Real_timer;
const std::vector<TriangleMesh1>& tm1_parts; std::vector<boost::any>& tm_wrappers;
const VPM1& vpm1; std::vector<TM1Tree>& tm1_trees;
// Constructor. // Constructor.
Bounded_error_preprocessing( Bounded_error_preprocessing(
const std::vector<TriangleMesh1>& tm1_parts, const VPM1& vpm1, std::vector<boost::any>& tm_wrappers) :
std::vector<TM1Tree>& tm1_trees) : tm_wrappers(tm_wrappers) { }
tm1_parts(tm1_parts), vpm1(vpm1), tm1_trees(tm1_trees) {
CGAL_assertion(tm1_parts.size() == tm1_trees.size());
}
// Split constructor. // Split constructor.
Bounded_error_preprocessing( Bounded_error_preprocessing(
Bounded_error_preprocessing& s, tbb::split) : Bounded_error_preprocessing& s, tbb::split) :
tm1_parts(s.tm1_parts), vpm1(s.vpm1), tm1_trees(s.tm1_trees) { tm_wrappers(s.tm_wrappers) { }
CGAL_assertion(tm1_parts.size() == tm1_trees.size());
bool is_tm1_wrapper(const boost::any& operand) const {
return operand.type() == typeid(TM1Wrapper);
}
bool is_tm2_wrapper(const boost::any& operand) const {
return operand.type() == typeid(TM2Wrapper);
} }
void operator()(const tbb::blocked_range<std::size_t>& range) { void operator()(const tbb::blocked_range<std::size_t>& range) {
@ -1688,12 +1708,17 @@ struct Bounded_error_preprocessing {
timer.reset(); timer.reset();
timer.start(); timer.start();
for (std::size_t i = range.begin(); i != range.end(); ++i) { for (std::size_t i = range.begin(); i != range.end(); ++i) {
CGAL_assertion(i < tm1_parts.size()); CGAL_assertion(i < tm_wrappers.size());
CGAL_assertion(i < tm1_trees.size()); auto& tm_wrapper = tm_wrappers[i];
const auto& tm1 = tm1_parts[i]; if (is_tm1_wrapper(tm_wrapper)) {
auto& tm1_tree = tm1_trees[i]; TM1Wrapper& object = boost::any_cast<TM1Wrapper&>(tm_wrapper);
tm1_tree.insert(faces(tm1).begin(), faces(tm1).end(), tm1, vpm1); object.build_tree();
tm1_tree.build(); } else if (is_tm2_wrapper(tm_wrapper)) {
TM2Wrapper& object = boost::any_cast<TM2Wrapper&>(tm_wrapper);
object.build_tree();
} else {
CGAL_assertion_msg(false, "Error: wrong boost any type!");
}
} }
timer.stop(); timer.stop();
// std::cout << "* time operator() preprocessing (sec.): " << timer.time() << std::endl; // std::cout << "* time operator() preprocessing (sec.): " << timer.time() << std::endl;
@ -1817,19 +1842,23 @@ double bounded_error_one_sided_Hausdorff_impl(
using Timer = CGAL::Real_timer; using Timer = CGAL::Real_timer;
using TM1_wrapper = Triangle_mesh_wrapper<TMF, VPM1, TMF_tree>;
using TM2_wrapper = Triangle_mesh_wrapper<TM2, VPM2, TM2_tree>;
Timer timer; Timer timer;
std::cout.precision(20); std::cout.precision(20);
const int nb_cores = 4; // TODO: add to NP! const int nb_cores = 4; // TODO: add to NP!
std::cout << "* num cores: " << nb_cores << std::endl;
TM1_tree tm1_tree; TM1_tree tm1_tree;
TM2_tree tm2_tree; TM2_tree tm2_tree;
std::vector<TMF> tm1_parts; std::vector<TMF> tm1_parts;
std::vector<TMF_tree> tm1_trees; std::vector<TMF_tree> tm1_trees;
std::vector<boost::any> tm_wrappers;
FT infinity_value = -FT(1); FT infinity_value = -FT(1);
// TODO: && METIS! #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_METIS_ENABLED)
#if defined(CGAL_LINKED_WITH_TBB)
if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value && nb_cores > 1) { if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value && nb_cores > 1) {
// (1) -- Create partition of tm1. // (1) -- Create partition of tm1.
@ -1872,10 +1901,16 @@ double bounded_error_one_sided_Hausdorff_impl(
Point_3(bb.xmax(), bb.ymax(), bb.zmax())); Point_3(bb.xmax(), bb.ymax(), bb.zmax()));
infinity_value = CGAL::approximate_sqrt(sq_dist) * FT(2); infinity_value = CGAL::approximate_sqrt(sq_dist) * FT(2);
Bounded_error_preprocessing<TMF, VPM1, TMF_tree, Kernel> bep(tm1_parts, vpm1, tm1_trees); CGAL_assertion(tm1_trees.size() == tm1_parts.size());
tbb::parallel_reduce(tbb::blocked_range<std::size_t>(0, tm1_parts.size()), bep); tm_wrappers.reserve(tm1_parts.size() + 1);
tm2_tree.insert(faces(tm2).begin(), faces(tm2).end(), tm2, vpm2); for (std::size_t i = 0; i < tm1_parts.size(); ++i) {
tm2_tree.build(); tm_wrappers.push_back(TM1_wrapper(tm1_parts[i], vpm1, false, tm1_trees[i]));
}
tm_wrappers.push_back(TM2_wrapper(tm2, vpm2, true, tm2_tree));
CGAL_assertion(tm_wrappers.size() == tm1_parts.size() + 1);
Bounded_error_preprocessing<TM1_wrapper, TM2_wrapper> bep(tm_wrappers);
tbb::parallel_reduce(tbb::blocked_range<std::size_t>(0, tm_wrappers.size()), bep);
timer.stop(); timer.stop();
const double time3 = timer.time(); const double time3 = timer.time();
@ -1914,8 +1949,7 @@ double bounded_error_one_sided_Hausdorff_impl(
timer.reset(); timer.reset();
timer.start(); timer.start();
// TODO: && METIS! #if defined(CGAL_LINKED_WITH_TBB) && defined(CGAL_METIS_ENABLED)
#if defined(CGAL_LINKED_WITH_TBB)
if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value && nb_cores > 1) { if (boost::is_convertible<Concurrency_tag, CGAL::Parallel_tag>::value && nb_cores > 1) {
std::cout << "* executing parallel version " << std::endl; std::cout << "* executing parallel version " << std::endl;