T'CHATTE | Salut à tous,
Voici mon problème : j'ai des conteneurs 3D dans lesquels je stocke des données quelconque sur lesquelles je souhaite appliquer divers filtres, morphologies mathématiques, etc... Donc jusqu'ici, pour paralléliser ces opérations, je faisais une fonction pour l'opération elle-même et une fonction qui s'occupait de créer mes threads et de leur répartir le travail (chaque thread traite une partie du volume). Le truc c'est cette seconde fonction est en fait tout le temps la même à l'exception du nom de la fonction que celle-ci appelle et des paramètres de la fonction appelée. Je cherche donc un moyen d'écrire une fonction générique qui pourrait m'appeler n'importe qu'elle fonction. Donc jusqu'ici je suis parvenu à appeler une fonction quelconque en passant un pointeur sur fonction à ma fonction générique mais le hic c'est que toutes les fonctions qu'elle peut potentiellement appeler doivent avoir les mêmes paramètres (ce qui n'est évidemment pas le cas de mes fonctions). J'ai solutionné le problème en passant à mes fonctions un vector de pointeurs. Ça marche alors très bien mais je suis obligé de faire plein de static_cast au début de mes fonctions pour utiliser mes pointeurs et en plus je me retrouve à manipuler des pointeurs partout et c'est un peu ch***t .... Je cherche donc un moyen plus joli de faire ça, qui m'éviterai de passer par un vector de pointeurs
Pour la partie threads, j'utilise Boost::threads.
Merci d'avance
PS : Voici le code actuel (faites pas attention aux fonctions Run,affiche_test et test_thread:
Code :
- #include "Mes_Fonctions.hpp"
- #ifndef threadbool
- #define threadbool 0
- #ifdef THREAD
- #include <boost/thread/thread.hpp>
- #undef threadbool
- #define threadbool 1
- #endif
- #endif
- using namespace std;
- // ===================================================================
- class erode_class{
- public:
- erode_class(vector<void*> args_):ptrs_(args_){};
- void Run(vector<void* > &truc){
- cout<<"Paramètres :"<<endl;
- for(size_t i=0;i<ptrs_.size();++i){
- cout<<"\t"<<*(static_cast<int *> (ptrs_[i]))<<endl;
- }
- cout<<"Paramètre additionel :"<<endl;
- for(size_t i=0;i<truc.size();++i){
- int *temp=static_cast<int *> (truc[i]);
- cout<<"\t"<<(*temp)<<endl;
- }
- cout<<endl<<endl;
- };
- template<class T>
- void thread_erode_b(vector<void *> &arguments_,vector<bool> &traites){
- if(arguments_.size()!=5){cout<<"Erode arguments are incorrect"<<endl<<"End program"<<endl;exit(0);}
- T *volume=static_cast<T *> (arguments_[0]);
- T *volume2=static_cast<T *> (arguments_[1]);
- int ordre=*(static_cast<int *> (arguments_[2]));
- int planstart=*(static_cast<int *> (arguments_[3]));
- int planstop=*(static_cast<int *> (arguments_[4]));
- const int dim1=(*volume).dim1(),dim2=(*volume).dim2(),dim3=(*volume).dim3();
- // Traitement proprement dit
- }
- private:
- vector<void*> ptrs_;
- };
- typedef void (erode_class::*traitement)(vector<void *> &arguments_,vector<bool> &traites);
- typedef void (erode_class::*Run_test)(vector<void *> &truc);
- // =========================================================================
- template <class T>
- void GenericThreadedFunction_2Volumes(T &volume1,T &volume2,const size_t nb_threads,vector<void* > &args,erode_class &test,int &planstart,int &planstop,vector<bool> &traites, traitement fonction){
- volume2.resize(volume1.dim1(),volume1.dim2(),volume1.dim3());
- #if threadbool
- boost::thread_group threads1;
- size_t box_size=volume1.dim1();
- for (std::size_t n=0; n<nb_threads; ++n){
- size_t nb_plans=(int)((double)box_size/(double)nb_threads);
- if(n<box_size%nb_threads)nb_plans++;
- if(n>=box_size%nb_threads){
- planstart=n*nb_plans+box_size%nb_threads;
- }
- else {
- planstart=n*nb_plans;
- }
- planstop=planstart-1+nb_plans;
- // Ici je sais que ce n'est pas la meilleure façon de répartir les taches mais j'optimiserai ça plus tard :-P
- args[3]=&planstart;
- args[4]=&planstop;
- cout<<n<<" : "<<*(static_cast<int*> (args[3]))<<" to "<<*(static_cast<int*> (args[4]))<<endl;
- threads1.create_thread(boost::bind(fonction,boost::ref(test),boost::ref(args),boost::ref(traites)));
- }
- threads1.join_all();
- #else
- size_t planstart=0,planstop=volume1.dim1()-1;
- fonction(volume1,volume2,ordre,planstart,planstop);
- #endif
- }
- template<typename T>
- void affiche_test(double i){
- cout<<"Affiche_test = "<<T(i)<<endl;
- }
- template<typename T>
- void test_thread(T j,void (*f)(T k)){
- boost::thread_group threads1;
- for(int i=0;i<2;++i){
- threads1.create_thread(boost::bind(f,j));
- sleep(1);}
- threads1.join_all();
- }
- int main(int argc, char *argv[])
- {
- size_t nb_threads;
- #if threadbool
- nb_threads=boost::thread::hardware_concurrency();
- #else
- nb_threads=1;
- #endif
- slip::RegularVector3dField3d<double> volume1b;
- read_slip_data(volume1b,"volume_lif_00005.abe" );
- slip::Volume<double> volume1(volume1b.dim1(),volume1b.dim2(),volume1b.dim3()),volume2;
- slip::RegularVector3dField3d<double>::const_iterator iter1=volume1b.begin();
- slip::Volume<double>::iterator iter2=volume1.begin();
- for( ;
- iter1!=volume1b.end()&&
- iter2!=volume1.end();
- ++iter1,++iter2)
- (*iter2)=(*iter1)[0];
- vector<void*> args,tmp;
- erode_class test(args);
- int planstart=0,planstop=(int)volume1.dim1(),ordre=3;
- // Création du vector de poiteurs sur les paramètres ... ce que je voudrai éviter
- tmp.push_back(&volume1);
- tmp.push_back(&volume2);
- tmp.push_back(&ordre);
- tmp.push_back(&planstart);
- tmp.push_back(&planstop);
- vector<bool> traites(volume1.dim1());
- traitement f = &erode_class::thread_erode_b<slip::Volume<double> >;
- GenericThreadedFunction_2Volumes(volume1,volume2,nb_threads,tmp,test,planstart,planstop,traites,f);
- return 0;
- }
|
|