Commit 31c9ff1a authored by Sylvain Thery's avatar Sylvain Thery

ajout de la parallelisation:

multithreading des algos
parallelisation des foreach
parent 1b96b9f3
......@@ -4,6 +4,8 @@ project(Tutos)
#SET (COMMON_LIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} ${GLEW_LIBRARY} ${DEVIL_LIBRARIES} ${ZLIB_LIBRARIES} ${LIBXML2_LIBRARIES} gzstream AntTweakBar openctm)
#SET (CMAKE_BUILD_TYPE Debug)
SET(CMAKE_BUILD_TYPE Release)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTOPOWARNING")
......@@ -49,3 +51,8 @@ target_link_libraries( tuto_subdivision
add_executable( tp_master tp_master.cpp)
target_link_libraries( tp_master
container topology utils algo ${COMMON_LIBS} )
add_executable( tuto_mt tuto_mt.cpp)
target_link_libraries( tuto_mt
# containerD topologyD utilsD algoD ${COMMON_LIBS} boost_thread)
container topology utils algo ${COMMON_LIBS} boost_thread)
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps *
* version 0.1 *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg *
* *
* This library is free software; you can 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. *
* *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this library; if not, write to the Free Software Foundation, *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
* Web site: https://iggservis.u-strasbg.fr/CGoGN/ *
* Contact information: cgogn@unistra.fr *
* *
*******************************************************************************/
#include <iostream>
#include "Utils/glutwin.h"
#include "Topology/generic/parameters.h"
#include "Topology/map/map2.h"
#include "Topology/generic/embeddedMap2.h"
#include "Geometry/vector_gen.h"
#include "Algo/Import/import.h"
#include "Algo/Geometry/boundingbox.h"
#include "Algo/Render/vbo_MapRender.h"
#include "Algo/Geometry/area.h"
#include "Algo/Geometry/normal.h"
#include "Algo/Parallel/parallel_foreach.h"
#include <GL/glx.h>
using namespace CGoGN ;
/**
* Struct that contains some informations about the types of the manipulated objects
* Mainly here to be used by the algorithms that are parameterized by it
*/
struct PFP: public PFP_STANDARD
{
// definition of the map
typedef EmbeddedMap2<Map2> MAP;
};
/**
* A class for a little interface and rendering
*/
class MyGlutWin: public Utils::SimpleGlutWin
{
public:
void myRedraw();
PFP::REAL gWidthObj;
PFP::VEC3 gPosObj;
Algo::Render::VBO::MapRender_VBO* m_render;
MyGlutWin(int* argc, char **argv, int winX, int winY) : SimpleGlutWin(argc, argv, winX, winY) {}
~MyGlutWin()
{
delete m_render ;
}
};
// Routine d'affichage
void MyGlutWin::myRedraw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
// center the object
float sc = 50.0f / gWidthObj;
glScalef(sc, sc, sc);
glTranslatef(-gPosObj[0], -gPosObj[1], -gPosObj[2]);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_LIGHTING);
// draw the lines
glColor3f(1.0f, 1.0f, 0.0f);
m_render->draw(Algo::Render::VBO::LINES);
// draw the faces
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0f, 1.0f);
glColor3f(0.0f, 0.5f, 0.0f);
m_render->draw(Algo::Render::VBO::TRIANGLES);
glDisable(GL_POLYGON_OFFSET_FILL);
glPopMatrix();
}
AttributeHandler<PFP::VEC3> position;
AttributeHandler<PFP::VEC3> facesnormals;
//
//template<typename PFP>
//void fonction_exemple(typename PFP::MAP& map, const AttributeHandler<typename PFP::VEC3>& position, Dart d)
//{
// std::cout << "Position brin"<<d.index<< " = "<< position[d]<< std::endl;
//}
// NEED VERTEX_THREAD
template<typename XXX>
class Thread1
{
protected:
typename XXX::MAP& m_map;
unsigned int m_th;
public:
Thread1(typename XXX::MAP& map, unsigned int th):
m_map(map), m_th(th) {}
void operator()()
{
typename XXX::VEC3 total(0.);
unsigned int nb=0;
{
CellMarker mv(m_map,VERTEX_CELL, m_th);
for (Dart d = m_map.begin(); d != m_map.end(); m_map.next(d))
{
if (! mv.isMarked(d)) // si d non marque:
{
typename XXX::VEC3 p = position[d];
total+=p;
nb++;
mv.mark(d);
}
}
}
{
CellMarker mv(m_map,VERTEX_CELL, m_th);
for (Dart d = m_map.begin(); d != m_map.end(); m_map.next(d))
{
if (! mv.isMarked(d)) // si d non marque:
{
typename XXX::VEC3 p = position[d];
total+=p;
nb++;
mv.mark(d);
}
}
}
{
CellMarker mv(m_map,VERTEX_CELL, m_th);
for (Dart d = m_map.begin(); d != m_map.end(); m_map.next(d))
{
if (! mv.isMarked(d)) // si d non marque:
{
typename XXX::VEC3 p = position[d];
total+=p;
nb++;
mv.mark(d);
}
}
}
{
CellMarker mv(m_map,VERTEX_CELL, m_th);
for (Dart d = m_map.begin(); d != m_map.end(); m_map.next(d))
{
if (! mv.isMarked(d)) // si d non marque:
{
typename XXX::VEC3 p = position[d];
total+=p;
nb++;
mv.mark(d);
}
}
}
total /= typename XXX::REAL(nb);
std::cout << "Thread "<< m_th << "-> median pos: "<<total<< std::endl;
}
};
// NEED DART_THREAD
template<typename XXX>
class Thread2
{
protected:
typename XXX::MAP& m_map;
unsigned int m_th;
SelectorTrue m_selt;
float area;
public:
Thread2(typename XXX::MAP& map, unsigned int th):
m_map(map), m_th(th) {}
void operator()()
{
area = Algo::Geometry::totalArea<XXX>(m_map,position,m_selt,m_th);
area = Algo::Geometry::totalArea<XXX>(m_map,position,m_selt,m_th);
area = Algo::Geometry::totalArea<XXX>(m_map,position,m_selt,m_th);
area = Algo::Geometry::totalArea<XXX>(m_map,position,m_selt,m_th);
std::cout << "Thread "<< m_th<<" Total Area= "<< area<< std::endl;
}
};
// NEED FACE_THREAD
template<typename XXX>
class Thread3
{
protected:
typename XXX::MAP& m_map;
unsigned int m_th;
SelectorTrue m_selt;
public:
Thread3(typename XXX::MAP& map, unsigned int th):
m_map(map), m_th(th) {}
void operator()()
{
Algo::Geometry::computeNormalFaces<XXX>(m_map,position,facesnormals,m_selt,m_th);
typename XXX::VEC3 total(0.);
unsigned int nb=0;
for (unsigned int i=facesnormals.begin(); i != facesnormals.end(); facesnormals.next(i))
{
typename XXX::VEC3 f = facesnormals[i]/10000.0f;
total+=f;
nb++;
}
for (unsigned int i=facesnormals.begin(); i != facesnormals.end(); facesnormals.next(i))
{
typename XXX::VEC3 f = facesnormals[i]/10000.0f;
total+=f;
nb++;
}
for (unsigned int i=facesnormals.begin(); i != facesnormals.end(); facesnormals.next(i))
{
typename XXX::VEC3 f = facesnormals[i]/10000.0f;
total+=f;
nb++;
}
for (unsigned int i=facesnormals.begin(); i != facesnormals.end(); facesnormals.next(i))
{
typename XXX::VEC3 f = facesnormals[i]/10000.0f;
total+=f;
nb++;
}
total /= typename XXX::REAL(nb);
std::cout << "Thread "<< m_th<<" Face normal :"<<total << std::endl;
}
};
// NEED DART_THREAD
template<typename XXX>
class Thread0
{
protected:
typename XXX::MAP& m_map;
MyGlutWin& m_mgw;
unsigned int m_th;
SelectorTrue m_selt;
public:
Thread0(typename XXX::MAP& map,MyGlutWin& mgw, unsigned int th):
m_map(map), m_mgw(mgw), m_th(th) {}
void operator()()
{
std::cout << "Begin render init"<<std::endl;
m_mgw.useContext();
// instanciation of the renderer (here using VBOs)
m_mgw.m_render = new Algo::Render::VBO::MapRender_VBO();
// update the renderer (geometry and primitives)
m_mgw.m_render->updateData(Algo::Render::VBO::POSITIONS, position);
m_mgw.m_render->initPrimitives<PFP>(m_map, m_selt, Algo::Render::VBO::TRIANGLES,m_th);
m_mgw.m_render->initPrimitives<PFP>(m_map, m_selt, Algo::Render::VBO::LINES,m_th);
m_mgw.releaseContext();
std::cout<< "Render OK "<< std::endl;
}
};
boost::mutex mutexio;
unsigned int cpt1=0;
unsigned int cpt2=0;
//class ThreadFunc
//{
//protected:
// FunctorType& m_functor;
// std::vector<Dart>& m_darts;
// boost::mutex& m_exclu;
//
//public:
// ThreadFunc(FunctorType& func, std::vector<Dart>& vd, boost::mutex& mut ):
// m_functor(func), m_darts(vd), m_exclu(mut) {}
//
// void operator()()
// {
// bool m_finished=false;
//
// while(!m_finished)
// {
// Dart d;
// bool ok=false;
// do
// {
// m_exclu.lock();
// if (!m_darts.empty())
// {
// d = m_darts.back();
// m_darts.pop_back();
// std::cout << "Lecture "<< " = "<< m_darts.size()<< std::endl;
// ok=true;
// }
// else std::cout << "PB vecteur vide"<< std::endl;
// m_exclu.unlock();
// } while (!ok);
//
// if (!d.isNil())
// m_functor(d);
// else
// m_finished=true;
// }
//// std::cout << "Finished "<< std::endl;
// }
//};
//#define NBTH 7
//template <typename PFP>
//void parallel_foreach_orbit(typename PFP::MAP& map, unsigned int orbit, FunctorType& func)
//{
// std::vector<Dart> vd[NBTH];
//
// boost::thread* threads[NBTH];
// boost::mutex muts[NBTH];
//
//
// DartMarker dm(map);
//
// Dart d=map.begin();
//
// // NBTH new functions, new thread (with good darts !)
// for (unsigned int i=0; i<NBTH; ++i)
// {
// while (dm.isMarked(d))
// map.next(d);
// dm.markOrbit(orbit,d);
// vd[i].reserve(16);
// vd[i].push_back(d);
//// threads[i] = new boost::thread(ThreadFunc(func, vd[i], muts[i]));
// map.next(d);
// }
//// std::cout << "OK1" << std::endl;
//
// while ( d != map.end())
// {
// // store thre NBTH next darts in tempo v2d
// for (unsigned int i=0; i<NBTH; ++i)
// {
// while ((d !=map.end()) && (dm.isMarked(d)))
// map.next(d);
//
// if (d !=map.end())
// {
// dm.markOrbit(orbit,d);
//// muts[i].lock();
// vd[i].push_back(d);
//// std::cout << "Size of"<< i << " = "<< vd[i].size()<< std::endl;
//// muts[i].unlock();
// map.next(d);
// }
// else
// {
//// muts[i].lock();
// vd[i].push_back(Dart::nil());
//// muts[i].unlock();
// }
// }
// }
//
//
// //wait for all theads to be finished
// for (unsigned int i=0; i< NBTH; ++i)
// {
//// threads[i]->join();
//// delete threads[i];
// }
// std::cout << "------------------------"<<std::endl;
//}
//
//class ThreadFunc
//{
//protected:
// FunctorType& m_functor;
// const std::vector<Dart>& m_darts;
//
//public:
// ThreadFunc(FunctorType& func, const std::vector<Dart>& vd):
// m_functor(func), m_darts(vd) {}
//
// void operator()()
// {
// for (std::vector<Dart>::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it)
// m_functor(*it);
// }
//};
//template <typename PFP>
//void parallel_foreach_orbit(typename PFP::MAP& map, unsigned int orbit, FunctorType& func)
//{
// std::vector<Dart> vd[NBTH];
// boost::thread* threads[NBTH];
//
// DartMarker dm(map);
// Dart d=map.begin();
//
// // NBTH new functions, new thread (with good darts !)
// for (unsigned int i=0; i<NBTH; ++i)
// vd[i].reserve(4096);
//
//
// while ( d != map.end())
// {
// for (unsigned int i=0; i<NBTH; ++i)
// {
// while ((d !=map.end()) && (dm.isMarked(d)))
// map.next(d);
//
// if (d !=map.end())
// {
// dm.markOrbit(orbit,d);
// vd[i].push_back(d);
// map.next(d);
// }
// }
// }
//
// for (unsigned int i=0; i<NBTH; ++i)
// {
// threads[i] = new boost::thread(ThreadFunc(func, vd[i]));
// }
//
//
// //wait for all theads to be finished
// for (unsigned int i=0; i< NBTH; ++i)
// {
// threads[i]->join();
// delete threads[i];
// }
//}
//
//class ThreadFunc
//{
//protected:
// FunctorType& m_functor;
// const std::vector<Dart>& m_darts;
// boost::barrier& m_sync1;
// boost::barrier& m_sync2;
// bool& m_finished;
//public:
// ThreadFunc(FunctorType& func, const std::vector<Dart>& vd, boost::barrier& s1, boost::barrier& s2, bool& finished):
// m_functor(func), m_darts(vd), m_sync1(s1), m_sync2(s2), m_finished(finished) {}
//
// void operator()()
// {
// while (!m_finished)
// {
// for (std::vector<Dart>::const_iterator it = m_darts.begin(); it != m_darts.end(); ++it)
// m_functor(*it);
// m_sync1.wait();
// m_sync2.wait();
// }
// }
//};
//
//#define SZBUFF 2048
//
//template <typename PFP, int NBTH >
//void parallel_foreach_orbit(typename PFP::MAP& map, const FunctorSelect& good, unsigned int orbit, FunctorType& func)
//{
// std::vector<Dart> vd[NBTH];
// boost::thread* threads[NBTH];
//
// DartMarker dm(map);
// Dart d=map.begin();
//
// // NBTH new functions, new thread (with good darts !)
// for (unsigned int i=0; i<NBTH; ++i)
// vd[i].reserve(SZBUFF);
//
// // fill each vd buffers with 4096 darts
// unsigned int nb =0;
// while (( d != map.end()) && (nb < NBTH*SZBUFF) )
// {
// if (good(d) && (!dm.isMarked(d)))
// {
// dm.markOrbit(orbit,d);
// vd[nb%NBTH].push_back(d);
// nb++;
// }
// map.next(d);
// }
//
// boost::barrier sync1(NBTH+1);
// boost::barrier sync2(NBTH+1);
// bool finished=false;
// // lauch threads
// for (unsigned int i=0; i<NBTH; ++i)
// threads[i] = new boost::thread(ThreadFunc(func, vd[i],sync1,sync2, finished));
//
// // and continue to traverse the map
// std::vector<Dart> tempo[NBTH];
// for (unsigned int i=0; i<NBTH; ++i)
// tempo[i].reserve(SZBUFF);
//
// while ( d != map.end())
// {
// for (unsigned int i=0; i<NBTH; ++i)
// tempo[i].clear();
//
// unsigned int nb =0;
// while (( d != map.end()) && (nb < NBTH*SZBUFF) )
// {
// if (good(d) && (!dm.isMarked(d)))
// {
// dm.markOrbit(orbit,d);
// tempo[nb%NBTH].push_back(d);
// nb++;
// }
// map.next(d);
// }
//
// sync1.wait();
// for (unsigned int i=0; i<NBTH; ++i)
// vd[i].swap(tempo[i]);
// sync2.wait();
// }
//
// sync1.wait();
// finished = true;
// sync2.wait();
//
// //wait for all theads to be finished
// for (unsigned int i=0; i< NBTH; ++i)
// {
// threads[i]->join();
// delete threads[i];
// }
//}
//
//
//template <typename PFP, int NBTH >
//void parallel_foreach_cell(typename PFP::MAP& map, const FunctorSelect& good, unsigned int cell, FunctorType& func, unsigned int szbuff)
//{
// std::vector<Dart> vd[NBTH];
// boost::thread* threads[NBTH];
//
// CellMarker cm(map,cell);
// Dart d=map.begin();
//
// // NBTH new functions, new thread (with good darts !)
// for (unsigned int i=0; i<NBTH; ++i)
// vd[i].reserve(szbuff);
//
// // fill each vd buffers with 4096 darts
// unsigned int nb =0;
// while (( d != map.end()) && (nb < NBTH*szbuff) )
// {
// if (good(d) && (!cm.isMarked(d)))
// {
// cm.mark(d);
// vd[nb%NBTH].push_back(d);
// nb++;
// }
// map.next(d);
// }
//
// boost::barrier sync1(NBTH+1);
// boost::barrier sync2(NBTH+1);
// bool finished=false;
// // lauch threads
// for (unsigned int i=0; i<NBTH; ++i)
// threads[i] = new boost::thread(ThreadFunc(func, vd[i],sync1,sync2, finished));
//
// // and continue to traverse the map
// std::vector<Dart> tempo[NBTH];
// for (unsigned int i=0; i<NBTH; ++i)
// tempo[i].reserve(SZBUFF);
//
// while ( d != map.end())
// {
// for (unsigned int i=0; i<NBTH; ++i)
// tempo[i].clear();
//
// unsigned int nb =0;
// while (( d != map.end()) && (nb < NBTH*szbuff) )
// {
// if (good(d) && (!cm.isMarked(d)))
// {
// cm.mark(d);
// tempo[nb%NBTH].push_back(d);
// nb++;
// }
// map.next(d);
// }
//
// sync1.wait();
// for (unsigned int i=0; i<NBTH; ++i)
// vd[i].swap(tempo[i]);
// sync2.wait();
// }
//
// sync1.wait();
// finished = true;
// sync2.wait();
//
// //wait for all theads to be finished
// for (unsigned int i=0; i< NBTH; ++i)
// {
// threads[i]->join();
// delete threads[i];
// }
//}
template <typename PFP>
class TestFunctor : public FunctorMap<typename PFP::MAP>
{
protected:
typename PFP::TVEC3& m_positions;
typename PFP::TVEC3& m_normals;
public:
TestFunctor( typename PFP::MAP& map, typename PFP::TVEC3& pos, typename PFP::TVEC3& norm):
FunctorMap<typename PFP::MAP>(map), m_positions(pos), m_normals(norm) {}
bool operator()(Dart d)
{
typename PFP::VEC3 n1 = Algo::Geometry::vertexNormal<PFP>(this->m_map, d, m_positions);
typename PFP::VEC3 n2 = Algo::Geometry::vertexNormal<PFP>(this->m_map, this->m_map.phi1(d), m_positions);
typename PFP::VEC3 n3 = Algo::Geometry::vertexNormal<PFP>(this->m_map, this->m_map.phi_1(d), m_positions);
typename PFP::VEC3 n = n1+n2+n3;
n.normalize();
m_normals[d] = n;
// m_normals[d] = Algo::Geometry::vertexNormal<PFP>(this->m_map, d, m_positions);
return false;
}
};