Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2958 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Multithread générique

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Multithread générique

n°2080342
T'CHATTE
Posté le 04-06-2011 à 10:47:57  profilanswer
 

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 :
  1. #include "Mes_Fonctions.hpp"
  2. #ifndef threadbool
  3. #define threadbool 0
  4. #ifdef THREAD
  5. #include <boost/thread/thread.hpp>
  6. #undef threadbool
  7. #define threadbool 1
  8. #endif
  9. #endif
  10. using namespace std;
  11. // ===================================================================
  12. class erode_class{
  13. public:
  14. erode_class(vector<void*> args_):ptrs_(args_){};
  15. void Run(vector<void* > &truc){
  16. cout<<"Paramètres :"<<endl;
  17. for(size_t i=0;i<ptrs_.size();++i){
  18.  cout<<"\t"<<*(static_cast<int *> (ptrs_[i]))<<endl;
  19.  }
  20. cout<<"Paramètre additionel :"<<endl;
  21. for(size_t i=0;i<truc.size();++i){
  22.  int *temp=static_cast<int *> (truc[i]);
  23.  cout<<"\t"<<(*temp)<<endl;
  24.  }
  25.  cout<<endl<<endl;
  26. };
  27. template<class T>
  28. void thread_erode_b(vector<void *> &arguments_,vector<bool> &traites){
  29. if(arguments_.size()!=5){cout<<"Erode arguments are incorrect"<<endl<<"End program"<<endl;exit(0);}
  30. T *volume=static_cast<T *> (arguments_[0]);
  31. T *volume2=static_cast<T *> (arguments_[1]);
  32. int ordre=*(static_cast<int *> (arguments_[2]));
  33. int planstart=*(static_cast<int *> (arguments_[3]));
  34. int planstop=*(static_cast<int *> (arguments_[4]));
  35. const int dim1=(*volume).dim1(),dim2=(*volume).dim2(),dim3=(*volume).dim3();
  36. // Traitement proprement dit
  37. }
  38. private:
  39. vector<void*> ptrs_;
  40. };
  41. typedef void (erode_class::*traitement)(vector<void *> &arguments_,vector<bool> &traites);
  42. typedef void (erode_class::*Run_test)(vector<void *> &truc);
  43. // =========================================================================
  44. template <class T>
  45. 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){
  46. volume2.resize(volume1.dim1(),volume1.dim2(),volume1.dim3());
  47. #if threadbool
  48. boost::thread_group threads1;
  49. size_t box_size=volume1.dim1();
  50. for (std::size_t n=0; n<nb_threads; ++n){
  51. size_t nb_plans=(int)((double)box_size/(double)nb_threads);
  52. if(n<box_size%nb_threads)nb_plans++;
  53. if(n>=box_size%nb_threads){
  54.  planstart=n*nb_plans+box_size%nb_threads;
  55.  }
  56. else {
  57.  planstart=n*nb_plans;
  58.  }
  59. planstop=planstart-1+nb_plans;
  60. // Ici je sais que ce n'est pas la meilleure façon de répartir les taches mais j'optimiserai ça plus tard :-P
  61. args[3]=&planstart;
  62. args[4]=&planstop;
  63. cout<<n<<" : "<<*(static_cast<int*> (args[3]))<<" to "<<*(static_cast<int*> (args[4]))<<endl;
  64. threads1.create_thread(boost::bind(fonction,boost::ref(test),boost::ref(args),boost::ref(traites)));
  65. }
  66. threads1.join_all();
  67. #else
  68. size_t planstart=0,planstop=volume1.dim1()-1;
  69. fonction(volume1,volume2,ordre,planstart,planstop);
  70. #endif
  71. }
  72. template<typename T>
  73. void affiche_test(double i){
  74. cout<<"Affiche_test = "<<T(i)<<endl;
  75. }
  76. template<typename T>
  77. void test_thread(T j,void (*f)(T k)){
  78. boost::thread_group threads1;
  79. for(int i=0;i<2;++i){
  80. threads1.create_thread(boost::bind(f,j));
  81. sleep(1);}
  82. threads1.join_all();
  83. }
  84. int main(int argc, char *argv[])
  85. {
  86. size_t nb_threads;
  87. #if threadbool
  88. nb_threads=boost::thread::hardware_concurrency();
  89. #else
  90. nb_threads=1;
  91. #endif
  92. slip::RegularVector3dField3d<double> volume1b;
  93. read_slip_data(volume1b,"volume_lif_00005.abe" );
  94. slip::Volume<double> volume1(volume1b.dim1(),volume1b.dim2(),volume1b.dim3()),volume2;
  95. slip::RegularVector3dField3d<double>::const_iterator iter1=volume1b.begin();
  96. slip::Volume<double>::iterator iter2=volume1.begin();
  97. for( ;
  98. iter1!=volume1b.end()&&
  99. iter2!=volume1.end();
  100. ++iter1,++iter2)
  101. (*iter2)=(*iter1)[0];
  102. vector<void*> args,tmp;
  103. erode_class test(args);
  104. int planstart=0,planstop=(int)volume1.dim1(),ordre=3;
  105. // Création du vector de poiteurs sur les paramètres ... ce que je voudrai éviter
  106. tmp.push_back(&volume1);
  107. tmp.push_back(&volume2);
  108. tmp.push_back(&ordre);
  109. tmp.push_back(&planstart);
  110. tmp.push_back(&planstop);
  111. vector<bool> traites(volume1.dim1());
  112. traitement f = &erode_class::thread_erode_b<slip::Volume<double> >;
  113. GenericThreadedFunction_2Volumes(volume1,volume2,nb_threads,tmp,test,planstart,planstop,traites,f);
  114. return 0;
  115. }

mood
Publicité
Posté le 04-06-2011 à 10:47:57  profilanswer
 

n°2080389
T'CHATTE
Posté le 04-06-2011 à 17:55:24  profilanswer
 

Ça y est, j'ai trouvé une manière faire proche de ce que j'imaginai.
Je crée des classes contenant ma fonction et ses paramètres puis j'ai juste à balancer la fonction dans un thread.
Donc au lieu d'avoir une fonction par traitement j'ai maintenant une classe mais ça ne change pas grand chose :)
 
Merci quand même !  :jap:  
A+  :hello:  
 
 
Le code pour ceux que ça intéresserait :
 

Code :
  1. #include "Mes_Fonctions.hpp"
  2. #ifndef threadbool
  3. #define threadbool 0
  4. #ifdef THREAD
  5. #include <boost/thread/thread.hpp>
  6. #undef threadbool
  7. #define threadbool 1
  8. #endif
  9. #endif
  10. using namespace std;
  11. #if threadbool
  12. boost::mutex mutexTraitement;
  13. #endif
  14. int next_plane(vector<bool> &indices,int k){
  15. for(int i=k+1;i<(int)indices.size();++i){
  16. if(!indices[i])return i;
  17. }
  18. for(int i=k-1;i>0;--i){
  19. if(!indices[i])return i;
  20. }
  21. return -10;
  22. }
  23. // ===================================================================
  24. template<class T>
  25. class erode_class{
  26. public:
  27. erode_class(T &vol1,T &vol2, int ord,int plan1):volume(vol1),volume2(vol2),ordre(ord),planstart(plan1){};
  28. void treatment(vector<bool> &indices){
  29. int k=next_plane(indices,planstart);
  30. const int dim1=volume.dim1(),dim2=volume.dim2(),dim3=volume.dim3();
  31. // Traitements ...
  32. }
  33. private:
  34. T &volume;
  35. T &volume2;
  36. int ordre;
  37. int planstart;
  38. };
  39. // =========================================================================
  40. template <class T,class TT>
  41. void GenericThreadedFunction_2Volumes(T &volume1,T &volume2,const size_t nb_threads,TT &Treatment_Type,int &planstart,vector<bool> &indices){
  42. volume2.resize(volume1.dim1(),volume1.dim2(),volume1.dim3());
  43. #if threadbool
  44. boost::thread_group threads1;
  45. size_t box_size=volume1.dim1();
  46. for (std::size_t n=0; n<nb_threads; ++n){
  47. size_t nb_plans=(int)((double)box_size/(double)nb_threads);
  48. if(n<box_size%nb_threads)nb_plans++;
  49. if(n>=box_size%nb_threads){
  50.  planstart=n*nb_plans+box_size%nb_threads;
  51.  }
  52. else {
  53.  planstart=n*nb_plans;
  54.  }
  55. threads1.create_thread(boost::bind(&TT::treatment,boost::ref(Treatment_Type),boost::ref(indices)));
  56. }
  57. threads1.join_all();
  58. #else
  59. planstart=0;
  60. Treatment_Type.treatment(indices);
  61. #endif
  62. }
  63. int main(int argc, char *argv[])
  64. {
  65. size_t nb_threads;
  66. #if threadbool
  67. nb_threads=boost::thread::hardware_concurrency();
  68. #else
  69. nb_threads=1;
  70. #endif
  71. slip::RegularVector3dField3d<double> volume1b;
  72. read_slip_data(volume1b,"volume_lif_00005.abe" );
  73. slip::Volume<double> volume1(volume1b.dim1(),volume1b.dim2(),volume1b.dim3()),volume2;
  74. slip::RegularVector3dField3d<double>::const_iterator iter1=volume1b.begin();
  75. slip::Volume<double>::iterator iter2=volume1.begin();
  76. for( ;
  77. iter1!=volume1b.end()&&
  78. iter2!=volume1.end();
  79. ++iter1,++iter2)
  80. (*iter2)=(*iter1)[0];
  81. int planstart=0,ordre=3;
  82. vector<bool> indices(volume1.dim1());
  83. erode_class<slip::Volume<double> > erosion1(volume1,volume2,ordre,planstart);
  84. GenericThreadedFunction_2Volumes(volume1,volume2,nb_threads,erosion1,planstart,indices);
  85. return 0;
  86. }


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Multithread générique

 

Sujets relatifs
[prog réseaux]serveur multithread et variable globalesFTP multithread
Multithread/core avec Qt[JAVA] Caster un objet a une classe generique ?
SpinnerAdapter génériqueQuelles opérations courantes sont sûres en multithread ?
Templates et tableau génériquequestion sur static et multithread
Linker sur la lib générique et pas sur une version spécifiquePaquetage en paramètre de paquetage générique
Plus de sujets relatifs à : Multithread générique


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)