multithreading: comment les données de processus dans un vecteur, tandis que le vecteur est peuplé?

StackOverflow https://stackoverflow.com/questions/3681823

Question

J'ai une application linux single-thread que je voudrais faire en parallèle. Il lit un fichier de données, crée des objets, et les place dans un vecteur. Ensuite, il appelle une méthode de calcul intensif (+ 0,5 secondes) sur chaque objet. Je veux appeler la méthode en parallèle avec la création d'objets. Pendant que je l'ai regardé qt et TBB, je suis ouvert à d'autres options.

Je comptais commencer le fil (s) tandis que le vecteur était vide. Chacun appellerait makeSolids (ci-dessous), qui a une boucle while qui irait jusqu'à interpDone de vrais et tous les objets dans le vecteur ont été traités. Cependant, je suis un n00b quand il s'agit de filetage, et j'ai cherché une solution prête à l'emploi.

QtConcurrent::map(Iter begin,Iter end,function()) semble très facile, mais je ne peux pas l'utiliser sur un vecteur qui change de taille, puis-je? Et comment pourrais-je dire d'attendre plus de données?

J'ai aussi regardé le TBB de intel, mais il avait l'air comme mon thread principal serait arrêter si je parallel_for ou parallel_while. Qui pue, puisque leur gestionnaire de mémoire a été recommandé (la mmgt de cascade ouverte a des performances médiocres lorsque multithread).

/**intended to be called by a thread
\param start the first item to get from the vector
\param skip how many to skip over (4 for 4 threads)
*/
void g2m::makeSolids(uint start, uint incr) {
  uint curr = start;
  while ((!interpDone) || (lineVector.size() > curr)) {
    if (lineVector.size() > curr) {
      if (lineVector[curr]->isMotion()) {
        ((canonMotion*)lineVector[curr])->setSolidMode(SWEPT);
        ((canonMotion*)lineVector[curr])->computeSolid();
      }
      lineVector[curr]->setDispMode(BEST);
      lineVector[curr]->display();

      curr += incr;
    } else {
      uio::sleep(); //wait a little bit for interp
    }
  }
}

EDIT: En résumé, quelle est la façon la plus simple de traiter un vecteur en même temps que le fil principal est peuplait le vecteur

Était-ce utile?

La solution

Il est difficile de dire si vous avez pensé à ce problème profondément et il est plus que vous laissez sur, ou si vous pensez juste au-dessus, ou si vous êtes juste méfier de filetage.

Lecture du fichier et la création d'objets est rapide; une méthode est lente. La dépendance est chaque cteur consécutive dépend de l'issue du cteur précédent - un peu bizarre - mais sinon il n'y a pas de problèmes d'intégrité des données afin qu'il ne semble pas être quelque chose qui doit être protégé par mutex et comme

.

Pourquoi est-ce plus compliqué que quelque chose comme ça (en pseudo-code brut):

while (! eof)
{
    readfile;
    object O(data);
    push_back(O);
    pthread_create(...., O, makeSolid);
}


while(x < vector.size())
{
    pthread_join();
    x++;
}

Si vous ne voulez pas faire une boucle sur les jointures dans votre principale frayer un fil alors hors d'attendre sur eux en passant un vecteur de TID.

Si le nombre d'objets / threads créés est fou, utiliser un pool de threads. Ou mettre un compteur est la boucle de création pour limiter le nombre de threads qui peuvent être créés avant les cours d'exécution sont jointes.

Autres conseils

Tout d'abord, pour bénéficier de filetage dont vous avez besoin de trouver de la même tâches lentes pour chaque thread à faire. Vous avez dit que votre traitement par objet prend .5s +, combien de temps votre fichier lecture / objet de prendre la création? Il pourrait facilement être un dixième ou un millième de ce moment-là, dans ce cas, votre approche multithreading va produire un bénéfice neglegible. Si tel est le cas, (oui, je vais répondre à votre question initiale bientôt Incase ce n'est pas) alors pensez à traiter simultanément plusieurs objets. Compte tenu de votre traitement prend tout à fait un certain temps, la création de fil est en tête pas très importante, de sorte que vous pouvez simplement avoir votre thread principal de création lecture / objet fichier spawn un nouveau thread et le diriger à l'objet nouvellement créé. Le fil conducteur se poursuit ensuite la lecture / la création d'objets ultérieurs. Une fois que tous les objets sont lus / créé et tous les fils de traitement lancé, le thread principal « joint » (attend) les threads de travail. Si cela va créer trop de threads (en milliers), puis mettre une limite sur la distance avant le thread principal est autorisé à obtenir: il peut lire / créer 10 objets puis rejoindre 5, puis lire / créer 10, rejoindre 10, en lecture / création 10, rejoindre 10 etc. jusqu'à la fin.

Maintenant, si vous voulez vraiment la lecture / créer pour être en parallèle avec le traitement, mais le traitement à sérialisé, vous pouvez toujours utiliser l'approche ci-dessus, mais après chaque objet se joindre. C'est un peu bizarre si vous concevez ce avec seulement cette approche à l'esprit, mais bien parce que vous pouvez facilement expérimenter avec le parallélisme de traitement des objets ci-dessus ainsi.

Vous pouvez utiliser une approche plus complexe qui implique que le thread principal (que le système d'exploitation crée au démarrage de votre programme), et un seul thread de travail que le thread principal doit commencer. Ils devraient être coordonnés au moyen d'un mutex (une variable assurant mutuellement exclusif, ce qui signifie non simultanée, l'accès aux données), et une variable de condition qui permet au thread de travail pour bloquer efficacement jusqu'à ce que le thread principal a fourni plus de travail. Les termes - mutex et variable état -. Sont les termes standard dans le filetage Posix que les utilisations Linux, doivent donc être utilisés dans l'explication des bibliothèques particulières qui vous intéressent Sommairement, le thread de travail jusqu'à ce que la lecture / créer thread principal le diffuse un signal de réveil indiquant un autre objet est prêt pour le traitement. Vous voudrez peut-être avoir un compteur avec l'index du dernier entièrement créé, l'objet prête à traiter, de sorte que le thread de travail peut maintenir son nombre d'objets traités et se déplacer le long les prêts avant de vérifier une nouvelle fois la variable de condition.

@Caleb: tout à fait - peut-être je devrais avoir mis l'accent sur actifs fils . Le fil de l'interface doit toujours être considéré comme l'un.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top