The concurrency parameters are now stored in a config file which is handled via boost::program_options.

This commit is contained in:
Clément Jamin 2012-04-12 13:37:15 +00:00
parent 477035c69c
commit ce132eb34a
9 changed files with 251 additions and 83 deletions

2
.gitattributes vendored
View File

@ -2649,6 +2649,7 @@ Mesh_3/demo/Mesh_3/Volume_plane_thread.h -text
Mesh_3/demo/Mesh_3/Volume_planes_plugin.cpp -text
Mesh_3/demo/Mesh_3/cgal_test_with_cmake -text
Mesh_3/demo/Mesh_3/cmake/modules/FindGLEW.cmake -text
Mesh_3/demo/Mesh_3/concurrent_mesher_config.cfg -text
Mesh_3/demo/Mesh_3/resources/about.html svneol=native#text/html
Mesh_3/demo/Mesh_3/resources/check-off.png -text svneol=unset#image/png
Mesh_3/demo/Mesh_3/resources/check-off.svg -text
@ -2707,6 +2708,7 @@ Mesh_3/examples/Mesh_3/mesh_3D_image.cpp -text
Mesh_3/examples/Mesh_3/mesh_polyhedral_domain.cpp -text
Mesh_3/examples/Mesh_3/old_stuff/inputs/cube.mesh -text svneol=unset#application/octet-stream
Mesh_3/examples/Mesh_3/old_stuff/inputs/tangle.mesh -text svneol=unset#application/octet-stream
Mesh_3/include/CGAL/Mesh_3/Concurrent_mesher_config.h -text
Mesh_3/include/CGAL/Mesh_3/Locking_data_structures.h -text
Mesh_3/include/CGAL/Mesh_3/Profiling_tools.h -text
Mesh_3/include/CGAL/Mesh_3/Worksharing_data_structures.h -text

View File

@ -186,6 +186,9 @@ private:
Previous& previous_level; /**< The previous level of the refinement
process. */
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
const int FIRST_GRID_LOCK_RADIUS;
const int MESH_3_REFINEMENT_GRAINSIZE;
const int REFINEMENT_BATCH_SIZE;
Mesh_3::LockDataStructureType *m_lock_ds;
Mesh_3::WorksharingDataStructureType *m_worksharing_ds;
#endif
@ -215,6 +218,12 @@ public:
)
: previous_level(previous)
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
, FIRST_GRID_LOCK_RADIUS(
Concurrent_mesher_config::get_option<int>("first_grid_lock_radius"))
, MESH_3_REFINEMENT_GRAINSIZE(
Concurrent_mesher_config::get_option<int>("first_grid_lock_radius"))
, REFINEMENT_BATCH_SIZE(
Concurrent_mesher_config::get_option<int>("refinement_batch_size"))
, m_lock_ds(p_lock_ds)
, m_worksharing_ds(p_worksharing_ds)
# ifdef CGAL_MESH_3_WORKSHARING_USES_TASKS
@ -603,21 +612,21 @@ public:
# ifdef CGAL_MESH_3_WORKSHARING_USES_PARALLEL_FOR
/*std::pair<Container_quality, Container_element>
raw_elements[ELEMENT_BATCH_SIZE];*/
raw_elements[REFINEMENT_BATCH_SIZE];*/
std::vector<Container_element> container_elements;
container_elements.reserve(ELEMENT_BATCH_SIZE);
container_elements.reserve(REFINEMENT_BATCH_SIZE);
std::vector<Point> circumcenters;
circumcenters.reserve(ELEMENT_BATCH_SIZE);
circumcenters.reserve(REFINEMENT_BATCH_SIZE);
std::vector<std::ptrdiff_t> indices;
indices.reserve(ELEMENT_BATCH_SIZE);
indices.reserve(REFINEMENT_BATCH_SIZE);
/*int batch_size = ELEMENT_BATCH_SIZE;
/*int batch_size = REFINEMENT_BATCH_SIZE;
if (debug_info_class_name() == "Refine_facets_3")
batch_size = 1;*/
size_t iElt = 0;
for( ;
iElt < ELEMENT_BATCH_SIZE && !no_longer_element_to_refine() ;
iElt < REFINEMENT_BATCH_SIZE && !no_longer_element_to_refine() ;
++iElt )
{
//raw_elements[iElt] = derived().get_next_raw_element_impl();
@ -749,7 +758,7 @@ public:
# elif defined(CGAL_MESH_3_WORKSHARING_USES_PARALLEL_DO)
std::vector<Container_element> container_elements;
container_elements.reserve(ELEMENT_BATCH_SIZE);
container_elements.reserve(REFINEMENT_BATCH_SIZE);
while(!no_longer_element_to_refine())
{
@ -831,7 +840,7 @@ public:
# elif defined(CGAL_MESH_3_WORKSHARING_USES_TASKS)
std::vector<Container_element> container_elements;
container_elements.reserve(ELEMENT_BATCH_SIZE);
container_elements.reserve(REFINEMENT_BATCH_SIZE);
while (!no_longer_element_to_refine())
{
@ -1052,8 +1061,8 @@ public:
{
// Lock the element area on the grid
Element element = derivd.extract_element_from_container_value(ce);
bool locked = triangulation().try_lock_element(
element, MESH_3_FIRST_GRID_LOCK_RADIUS);
bool locked = triangulation().try_lock_element(element,
FIRST_GRID_LOCK_RADIUS);
if( locked )
{

View File

@ -27,6 +27,8 @@
//#define CGAL_MESH_3_MESHER_STATUS_ACTIVATED 1
#include <CGAL/Mesh_3/Concurrent_mesher_config.h>
#include <QStringList>
#include <QString>
#include <QSound>
@ -168,7 +170,9 @@ launch()
Cell_criteria(p_.tet_shape,
p_.tet_sizing));
// BP HERE
// So that the config file is reloaded before each refinement
Concurrent_mesher_config::unload_config_file();
// Build mesher and launch refinement process
mesher_ = new Mesher(c3t3_, *domain_, criteria);
mesher_->initialize();

View File

@ -0,0 +1,24 @@
#==========================================
#======== Worksharing strategy ===========
#==========================================
locking_grid_num_cells_per_axis = 35
first_grid_lock_radius = 0
#==========================================
#============= Brute-force ================
#==========================================
#locking_grid_num_cells_per_axis = 30
#first_grid_lock_radius = 2
#==========================================
#============== Common ====================
#==========================================
refinement_grainsize = 10 # for parallel_XXX techniques
refinement_batch_size = 100 # for task-scheduler-based techniques
work_stats_grid_num_cells_per_axis = 5
num_work_items_per_batch = 500

View File

@ -1,6 +1,8 @@
#ifndef CGAL_DEMO_MESH_3_CONFIG_H
#define CGAL_DEMO_MESH_3_CONFIG_H
#include <CGAL/Mesh_3/Concurrent_mesher_config.h>
// #define CGAL_POLYHEDRON_DEMO_NO_NEF
// #define CGAL_POLYHEDRON_DEMO_NO_SURFACE_MESHER
// #define CGAL_POLYHEDRON_DEMO_NO_PARAMETRIZATION
@ -46,39 +48,27 @@
// ==========================================================================
# ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
const char * const CONFIG_FILENAME =
"D:/INRIA/CGAL/workingcopy/Mesh_3/demo/Mesh_3/concurrent_mesher_config.cfg";
//# define CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK
# define CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
//# define CGAL_MESH_3_CONCURRENT_REFINEMENT_LOCK_ADJ_CELLS
//# define CGAL_MESH_3_DO_NOT_LOCK_INFINITE_VERTEX
//# define CGAL_MESH_3_ACTIVATE_GRID_INDEX_CACHE_IN_VERTEX
//# define CGAL_MESH_3_CONCURRENT_REFINEMENT_LOCK_ADJ_CELLS // USELESS, FOR TESTS ONLY
//# define CGAL_MESH_3_DO_NOT_LOCK_INFINITE_VERTEX // DOES NOT WORK YET
//# define CGAL_MESH_3_ACTIVATE_GRID_INDEX_CACHE_IN_VERTEX // DOES NOT WORK YET
# define CGAL_MESH_3_WORKSHARING_USES_TASKS
//# define CGAL_MESH_3_WORKSHARING_USES_PARALLEL_FOR
//# define CGAL_MESH_3_WORKSHARING_USES_PARALLEL_DO
# ifdef CGAL_MESH_3_WORKSHARING_USES_TASKS
const int MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS = 35;
const int MESH_3_FIRST_GRID_LOCK_RADIUS = 0;
const int MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS = 5;
const int MESH_3_WORK_STATS_GRID_NUM_CELLS =
MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS*
MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS*
MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS;
const int NUM_WORK_ITEMS_PER_BATCH = 500;
# else
const int MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS = 30;
const int MESH_3_FIRST_GRID_LOCK_RADIUS = 2;
const int MESH_3_REFINEMENT_GRAINSIZE = 10;
# endif
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK
# include <tbb/recursive_mutex.h>
typedef tbb::recursive_mutex Cell_mutex_type; // CJTODO try others
# endif
# endif
// ==========================================================================
@ -88,12 +78,6 @@
typedef tbb::recursive_mutex Global_mutex_type;
extern Global_mutex_type g_global_mutex; // CJTODO: temporary
// ==========================================================================
// Concurrency Parameters
// ==========================================================================
const size_t ELEMENT_BATCH_SIZE = 100000;
// ==========================================================================
// Profiling
// ==========================================================================

View File

@ -0,0 +1,117 @@
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// You can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Clement Jamin
//
//******************************************************************************
// File Description :
//******************************************************************************
#ifdef CONCURRENT_MESH_3
#ifndef CGAL_MESH_3_CONCURRENT_MESHER_CONFIG_H
#define CGAL_MESH_3_CONCURRENT_MESHER_CONFIG_H
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <iostream>
// class Concurrent_mesher_config
/// Singleton containing config
class Concurrent_mesher_config
{
// Private constructor (singleton)
Concurrent_mesher_config()
: m_loaded(false) {}
public:
static Concurrent_mesher_config &get()
{
static Concurrent_mesher_config singleton;
return singleton;
}
static bool load_config_file(const char *filename)
{
return get().load_file(filename);
}
static void unload_config_file()
{
get().unload_file();
}
template <typename OptionType>
static OptionType get_option(const char *option_name)
{
return get().get_option_value<OptionType>(option_name);
}
protected:
bool load_file(const char *filename)
{
try
{
// Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()
("locking_grid_num_cells_per_axis", po::value<int>(), "")
("first_grid_lock_radius", po::value<int>(), "")
("work_stats_grid_num_cells_per_axis", po::value<int>(), "")
("num_work_items_per_batch", po::value<int>(), "")
("refinement_grainsize", po::value<int>(), "")
("refinement_batch_size", po::value<int>(), "");
po::store(po::parse_config_file<char>(filename, desc), m_variables_map);
po::notify(m_variables_map);
}
catch (std::exception &e)
{
std::cerr << "Config file error: " << e.what() << std::endl;
return false;
}
m_loaded = true;
return true;
}
void unload_file()
{
m_loaded = false;
}
template <typename OptionType>
OptionType get_option_value(const char *option_name)
{
if (!m_loaded)
load_file(CONFIG_FILENAME);
if (m_loaded && m_variables_map.count(option_name))
return m_variables_map[option_name].as<OptionType>();
else
return OptionType();
}
bool m_loaded;
po::variables_map m_variables_map;
};
#endif // CGAL_MESH_3_CONCURRENT_MESHER_CONFIG_H
#endif // CONCURRENT_MESH_3

View File

@ -22,8 +22,12 @@
#ifndef CGAL_MESH_3_LOCKING_DATA_STRUCTURES_H
#define CGAL_MESH_3_LOCKING_DATA_STRUCTURES_H
#include <CGAL/Mesh_3/Concurrent_mesher_config.h>
#include <CGAL/Bbox_3.h>
#include <boost/bind.hpp>
#include <tbb/tbb.h>
#include <tbb/compat/thread>
#include <tbb/enumerable_thread_specific.h>
@ -39,6 +43,16 @@ namespace Mesh_3 {
// (Uses Curiously recurring template pattern)
//******************************************************************************
bool *init_TLS_grid(int num_cells_per_axis)
{
int num_cells = num_cells_per_axis*
num_cells_per_axis*num_cells_per_axis;
bool *local_grid = new bool[num_cells];
for (int i = 0 ; i < num_cells ; ++i)
local_grid[i] = false;
return local_grid;
}
template <typename Derived>
class Grid_locking_ds_base
{
@ -227,17 +241,7 @@ protected:
Grid_locking_ds_base(const Bbox_3 &bbox,
int num_grid_cells_per_axis)
: m_num_grid_cells_per_axis(num_grid_cells_per_axis),
m_tls_grids(
[=]() -> bool* // CJTODO: lambdas OK?
{
int num_cells = num_grid_cells_per_axis*
num_grid_cells_per_axis*num_grid_cells_per_axis;
bool *local_grid = new bool[num_cells];
for (int i = 0 ; i < num_cells ; ++i)
local_grid[i] = false;
return local_grid;
}
)
m_tls_grids(boost::bind(init_TLS_grid, num_grid_cells_per_axis))
{
// Keep mins and resolutions
m_xmin = bbox.xmin();
@ -298,8 +302,8 @@ public:
// Constructors
Simple_grid_locking_ds(const Bbox_3 &bbox,
int num_grid_cells_per_axis = MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS)
: Grid_locking_ds_base(bbox, num_grid_cells_per_axis)
int num_grid_cells_per_axis)
: Grid_locking_ds_base(bbox, num_grid_cells_per_axis)
{
int num_cells =
num_grid_cells_per_axis*num_grid_cells_per_axis*num_grid_cells_per_axis;
@ -342,16 +346,16 @@ class Simple_grid_locking_ds_with_thread_ids
public:
// Constructors
Simple_grid_locking_ds_with_thread_ids(const Bbox_3 &bbox,
int num_grid_cells_per_axis = MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS)
: Grid_locking_ds_base(bbox, num_grid_cells_per_axis),
m_tls_thread_ids(
[=]() -> unsigned int // CJTODO: lambdas OK?
{
static unsigned int last_id = 0;
return ++last_id;
}
)
Simple_grid_locking_ds_with_thread_ids(const Bbox_3 &bbox,
int num_grid_cells_per_axis)
: Grid_locking_ds_base(bbox, num_grid_cells_per_axis),
m_tls_thread_ids(
[=]() -> unsigned int // CJTODO: lambdas OK?
{
static unsigned int last_id = 0;
return ++last_id;
}
)
{
int num_cells =
num_grid_cells_per_axis*num_grid_cells_per_axis*num_grid_cells_per_axis;
@ -415,8 +419,8 @@ public:
// Constructors
Simple_grid_locking_ds_with_mutex(const Bbox_3 &bbox,
int num_grid_cells_per_axis = MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS)
: Grid_locking_ds_base(bbox, num_grid_cells_per_axis)
int num_grid_cells_per_axis)
: Grid_locking_ds_base(bbox, num_grid_cells_per_axis)
{
int num_cells =
num_grid_cells_per_axis*num_grid_cells_per_axis*num_grid_cells_per_axis;

View File

@ -36,6 +36,10 @@
#include <CGAL/Surface_mesher/Surface_mesher_visitor.h>
#endif
#ifdef CONCURRENT_MESH_3
# include <CGAL/Mesh_3/Concurrent_mesher_config.h>
#endif
#include <CGAL/Timer.h>
#ifdef MESH_3_PROFILING
@ -173,7 +177,9 @@ Mesher_3<C3T3,MC,MD>::Mesher_3(C3T3& c3t3,
const MC& criteria)
:
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
m_lock_ds(c3t3.bbox()), // CJTODO: this is the bbox of the first 20 points => enlarge it?
m_lock_ds(c3t3.bbox(), // CJTODO: this is the bbox of the first 20 points => enlarge it?
Concurrent_mesher_config::get_option<int>(
"locking_grid_num_cells_per_axis")),
m_worksharing_ds(c3t3.bbox()), // CJTODO: this is the bbox of the first 20 points => enlarge it?
#endif
null_mesher_()

View File

@ -22,6 +22,8 @@
#ifndef CGAL_MESH_3_WORKSHARING_DATA_STRUCTURES_H
#define CGAL_MESH_3_WORKSHARING_DATA_STRUCTURES_H
#include <CGAL/Mesh_3/Concurrent_mesher_config.h>
#include <CGAL/Bbox_3.h>
#include <tbb/concurrent_queue.h>
@ -209,7 +211,6 @@ public:
}
protected:
int m_num_grid_cells_per_axis;
double m_xmin;
double m_ymin;
double m_zmin;
@ -217,6 +218,7 @@ protected:
double m_resolution_y;
double m_resolution_z;
int m_num_grid_cells_per_axis;
int m_num_cells;
tbb::atomic<int> * m_occupation_grid;
tbb::atomic<int> * m_num_batches_grid;
@ -356,15 +358,27 @@ class Dynamic_load_based_worksharing_ds
public:
// Constructors
Dynamic_load_based_worksharing_ds(const Bbox_3 &bbox)
: m_stats(bbox, MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS)
: m_num_cells_per_axis(Concurrent_mesher_config::get_option<int>(
"work_stats_grid_num_cells_per_axis")),
m_stats(bbox, m_num_cells_per_axis),
m_num_cells(m_num_cells_per_axis*m_num_cells_per_axis*m_num_cells_per_axis),
NUM_WORK_ITEMS_PER_BATCH(
Concurrent_mesher_config::get_option<int>("num_work_items_per_batch"))
{
for (int i = 0 ; i < MESH_3_WORK_STATS_GRID_NUM_CELLS ; ++i)
m_tls_work_buffers = new TLS_WorkBuffer[m_num_cells];
m_work_batches = new tbb::concurrent_queue<WorkBatch>[m_num_cells];
m_num_batches = new tbb::atomic<int>[m_num_cells];
for (int i = 0 ; i < m_num_cells ; ++i)
m_num_batches[i] = 0;
}
/// Destructor
~Dynamic_load_based_worksharing_ds()
{
delete [] m_tls_work_buffers;
delete [] m_work_batches;
delete [] m_num_batches;
}
template <typename P3, typename Func>
@ -386,7 +400,7 @@ public:
bool flush_work_buffers(tbb::task &parent_task)
{
bool some_items_were_flushed = false;
for (int i = 0 ; i < MESH_3_WORK_STATS_GRID_NUM_CELLS ; ++i)
for (int i = 0 ; i < m_num_cells ; ++i)
{
for (TLS_WorkBuffer::iterator it_buffer = m_tls_work_buffers[i].begin() ;
it_buffer != m_tls_work_buffers[i].end() ;
@ -417,7 +431,7 @@ public:
// Look for an non-empty queue
for (index = 0 ; !popped ; ++index)
{
CGAL_assertion(index < MESH_3_WORK_STATS_GRID_NUM_CELLS);
CGAL_assertion(index < m_num_cells);
popped = m_work_batches[index].try_pop(wb);
}
@ -454,31 +468,31 @@ protected:
void add_occupation(int cell_index, int to_add, int occupation_radius = 1)
{
int index_z = cell_index/(MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS*
MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS);
int index_z = cell_index/(m_num_cells_per_axis*
m_num_cells_per_axis);
cell_index -= index_z*
MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS*
MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS;
int index_y = cell_index/MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS;
cell_index -= index_y*MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS;
m_num_cells_per_axis*
m_num_cells_per_axis;
int index_y = cell_index/m_num_cells_per_axis;
cell_index -= index_y*m_num_cells_per_axis;
int index_x = cell_index;
// For each cell inside the square
for (int i = std::max(0, index_x-occupation_radius) ;
i <= std::min(MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS - 1, index_x+occupation_radius) ;
i <= std::min(m_num_cells_per_axis - 1, index_x+occupation_radius) ;
++i)
{
for (int j = std::max(0, index_y-occupation_radius) ;
j <= std::min(MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS - 1, index_y+occupation_radius) ;
j <= std::min(m_num_cells_per_axis - 1, index_y+occupation_radius) ;
++j)
{
for (int k = std::max(0, index_z-occupation_radius) ;
k <= std::min(MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS - 1, index_z+occupation_radius) ;
k <= std::min(m_num_cells_per_axis - 1, index_z+occupation_radius) ;
++k)
{
int index =
k*MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS*MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS
+ j*MESH_3_WORK_STATS_GRID_NUM_CELLS_PER_AXIS
k*m_num_cells_per_axis*m_num_cells_per_axis
+ j*m_num_cells_per_axis
+ i;
int weight =
@ -493,10 +507,14 @@ protected:
}
const int NUM_WORK_ITEMS_PER_BATCH;
int m_num_cells_per_axis;
int m_num_cells;
Work_statistics m_stats;
TLS_WorkBuffer m_tls_work_buffers[MESH_3_WORK_STATS_GRID_NUM_CELLS];
tbb::concurrent_queue<WorkBatch> m_work_batches[MESH_3_WORK_STATS_GRID_NUM_CELLS];
tbb::atomic<int> m_num_batches [MESH_3_WORK_STATS_GRID_NUM_CELLS];
TLS_WorkBuffer *m_tls_work_buffers;
tbb::concurrent_queue<WorkBatch> *m_work_batches;
tbb::atomic<int> *m_num_batches;
// CJTODO TEST
tbb::queuing_mutex m_mutex;