Multithread d'emploi gestionnaire de file d'attente

j'ai besoin de gérer les travaux multitâches lourds CPU dans une application interactive. Tout comme background, mon application spécifique est une interface de conception d'ingénierie. Lorsqu'un utilisateur modifie différents paramètres et options d'un modèle, plusieurs simulations sont exécutées en arrière-plan et les résultats sont affichés au fur et à mesure qu'ils sont terminés, probablement même si l'utilisateur est encore en train d'éditer des valeurs. Comme les simulations multiples prennent du temps variable (certaines sont des millisecondes, d'autres prennent 5 secondes, d'autres 10 minutes), c'est fondamentalement une question d'obtenir des commentaires affichés aussi vite que possible, mais souvent l'annulation des travaux qui ont commencé auparavant mais ne sont plus nécessaires en raison des changements de l'utilisateur ont déjà invalidé. Des changements d'utilisateur différents peuvent invalider des calculs différents donc à tout moment je peux avoir 10 simulations différentes en cours d'exécution. Certaines simulations ont plusieurs parties qui ont des dépendances (les simulations A et B peuvent être calculées séparément, mais j'ai besoin de leurs résultats pour lancer la simulation C donc j'ai besoin de attendre que A et B terminent avant de commencer C.)

je me sens assez confiant que la méthode de niveau de code pour traiter ce genre d'application est une sorte de file d'attente multithreaded emploi. Cela inclurait des fonctionnalités de soumission de travaux pour l'exécution, la définition des priorités des tâches, l'attente de la fin des travaux, la spécification des dépendances (faire ce travail, mais seulement après que job X et job Y ont terminé), l'annulation des sous-ensembles de travaux qui correspondent à certains critères, la question de ce qu'il reste de travaux, travailleurs nombre de threads et les priorités, et ainsi de suite. Et le support multiplateforme est également très utile.

ce ne sont pas des idées nouvelles ou des désirs dans le logiciel, mais je suis au début de la phase de conception de mon application où je dois faire un choix au sujet de la bibliothèque à utiliser pour gérer de telles tâches. J'ai écrit mes propres directeurs de fil brut dans le passé en C (je pense que c'est un rite de passage) mais je veux utiliser des outils modernes pour baser mon travail sur, pas mes propres précédents hacks.

La première pensée est de courir à OpenMP mais je ne suis pas sûr que c'est ce que je veux. OpenMP est idéal pour la parallélisation à un niveau fin, déroulage automatique des boucles et autres. Bien que multiplateformes, il envahit également votre code avec #pragmas. Mais surtout, il n'est pas conçu pour gérer de grandes tâches.. en particulier l'annulation des travaux en attente ou la spécification des dépendances. Possible, oui, mais ce n'est pas élégant.

j'ai remarqué que Google Chrome utilise un tel directeur de travail pour même les tâches les plus insignifiantes. le but de la conception semble être de garder le fil d'interaction utilisateur aussi léger et agile que possible, de sorte que tout ce qui peut être engendré hors asynchrone, devrait être. En regardant la source de Chrome, cela ne semble pas être une bibliothèque générique, mais il est quand même intéressant de voir comment le design utilise des lancements asynchrones pour maintenir une interaction rapide. Ça devient similaire à ce que je fais.

Il ya un encore d'autres options:

Surge.Loi: une bibliothèque de type Boost pour définir les emplois. Il s'appuie sur OpenMP, mais autorise le chaînage des dépendances, ce qui est bien. Il ne semble pas avoir l'impression d'avoir un gestionnaire qui peut être interrogé, des emplois annulés, etc. C'est un projet vétuste, ça fait peur d'en dépendre.

job Queue est assez proche de ce que je pense, mais c'est un article de 5 ans, pas un soutien bibliothèque.

coup de pouce.threads a la synchronisation indépendante plate-forme nice, mais ce n'est pas un gestionnaire de tâches. POCO a des conceptions très propres pour le lancement des tâches, mais encore une fois pas un gestionnaire complet pour les tâches de chaînage. (Peut-être que je sous-estime POCO cependant).

donc bien qu'il y ait des options disponibles, Je ne suis pas satisfait et je ressens l'envie de lancer ma propre bibliothèque à nouveau. Mais je préfère utiliser quelque chose qui est déjà dans l'existence. Même après avoir cherché (ici sur tel et sur le net) je n'ai rien trouvé qui me semble juste, bien que j'imagine que ce doit être une sorte d'outil qui est souvent nécessaire, donc sûrement il ya une bibliothèque communautaire ou au moins un design commun. Sur ainsi il y a eu quelques postes à propos de Files d'attente d'emploi , mais rien qui semble correspondre.

mon post ici est de vous demander tous les outils existants que j'ai manqué, et/ou comment vous avez roulé votre propre ces multithread file d'attente de travail.

31
demandé sur Community 2009-02-19 15:40:16
la source

10 ответов

nous avons dû construire notre propre système de file d'attente d'emploi pour répondre à des exigences similaires à la vôtre ( le fil D'UI doit toujours répondre dans les 33M, les emplois peuvent courir de 15-15000m ), parce qu'il n'y avait vraiment rien là-bas qui répond tout à fait nos besoins, et encore moins était performant.

malheureusement, notre code est à peu près aussi propriétaire que propriétaire obtient, mais je peux vous donner quelques-unes des caractéristiques les plus saillantes:

  • nous démarrons un thread par coeur à la début du programme. Chacun tire son travail d'une file d'attente mondiale. Les tâches consistent en un objet de fonction et un ensemble de données associées (en fait une élaboration sur un func_ptr et un void *). Thread 0, la boucle client rapide, n'est pas autorisé à travailler sur les travaux, mais le reste saisir comme ils le peuvent.
  • la file d'attente de travail elle-même devrait être une structure de données sans serrure, telle qu'une liste sans serrure à un seul lien (studio visuel livré avec un ). Évitez d'utiliser un mutex; la querelle pour la file d'attente est étonnamment élevée, et saisir des Mutex est coûteux.
  • empaquetez toutes les données nécessaires pour le travail dans l'objet de travail lui-même -- évitez d'avoir pointeur du travail de nouveau dans le tas principal, où vous aurez à faire face à la discorde entre les travaux et les serrures et tous les autres lents, ennuyeux trucs. Par exemple, tous les paramètres de simulation doivent être introduits dans le blob local de données du travail. La structure des résultats doit évidemment être quelque chose qui survit au travail: vous pouvez gérer cela soit en a) accrochant aux objets de travail même après qu'ils ont fini d'exécuter (de sorte que vous pouvez utiliser leur contenu à partir du fil principal), ou b) allouant une structure de résultats spécialement pour chaque travail et en mettant un pointeur dans l'objet de données du travail. Même si les résultats eux-mêmes ne vivront pas dans le travail, cela donne effectivement l'accès exclusif du travail à sa mémoire de sortie de sorte que vous n'avez pas besoin de muss avec des serrures.

  • en fait je simplifie un peu plus haut, car nous avons besoin de chorégraphier exactement quels travaux fonctionnent sur quels noyaux, donc chaque noyau obtient sa propre file d'attente de travail, mais c'est probablement inutile pour vous.

17
répondu Crashworks 2009-02-20 06:14:08
la source

j'ai roulé le mien, basé sur Boost.threads. J'ai été assez surpris par la quantité de bang que j'ai eu en écrivant si peu de code. Si vous ne trouvez pas quelque chose de pré-fait, n'ayez pas peur de rouler le vôtre. Entre Coup De Pouce.fils et votre expérience depuis l'écriture de votre propre, il pourrait être plus facile que vous vous souvenez.

pour les options premade, n'oubliez pas que Chrome est sous licence très convivial, de sorte que vous pouvez être en mesure de rouler votre propre bibliothèque Générique autour de son code.

5
répondu Ryan Graham 2009-02-19 17:01:37
la source

Microsoft travaille sur un ensemble de technologies pour la prochaine Version de Visual Studio 2010 appelée la Concurrency Runtime, la bibliothèque parallèle de motifs et la bibliothèque asynchrone des Agents qui aidera probablement. L'exécution simultanée offrira une programmation basée sur la Politique, c'est-à-dire vous permettant de gérer et de composer plusieurs instances d'ordonnanceur (similaire à thread pools mais avec affinitisation et équilibrage de charge entre les instances), la bibliothèque de patterns parallèle offrira une programmation basée sur les tâches programmation et boucles parallèles avec un modèle de programmation de type STL. La bibliothèque D'Agents offre un modèle de programmation basé sur les acteurs et a le soutien pour construire des pipelines de flux de données concurrents, c.-à-d. Gérer les dépendances décrites ci-dessus. Malheureusement, ce N'est pas encore publié, de sorte que vous pouvez lire à ce sujet sur notre team blog ou regarder certaines des vidéos sur le canal 9 Il ya aussi un très grand CTP qui est disponible en téléchargement ainsi.

si vous cherchez une solution aujourd'hui, les blocs de construction de threads D'Intel et la bibliothèque de threading de boost sont à la fois de bonnes bibliothèques et disponibles dès maintenant. JustSoftwareSolutions a publié une implémentation de std::thread qui correspond au projet C++0x et bien sûr OpenMP est largement disponible si vous êtes à la recherche de parallélisme en boucle à grain fin.

le vrai défi auquel d'autres personnes ont fait allusion est d'identifier et de décomposer correctement travailler dans des tâches convenant à l'exécution simultanée (c.-à-d. pas d'état partagé non protégé), comprendre les dépendances entre elles et minimiser la prétention qui peut se produire sur les goulots d'étranglement (si le goulot d'étranglement est protéger l'état partagé ou assurer la boucle de régulation d'une file d'attente de travail est faible prétention ou sans verrouillage)... et de le faire sans que les détails de la mise en œuvre de la planification ne fuient dans le reste de votre code.

- Rick

4
répondu Rick 2009-02-20 10:18:17
la source

est-ce que quelque chose comme threadpool vous serait utile? Il est basé sur boost::threads et implémente essentiellement une simple file d'attente de tâches de threads qui passe les fonctions de worker aux threads groupés.

3
répondu greyfade 2009-02-19 20:29:18
la source

vous pourriez vouloir regarder " Flow-Based Programming - il est basé sur des morceaux de données de flux entre les composants asynchrones. Il existe des versions Java et C# du pilote, plus un certain nombre de composants précodés. Il est intrinsèquement multithreaded - en fait, le seul code monofiltre se trouve dans les composants, bien que vous puissiez ajouter des contraintes de temps aux règles d'ordonnancement standard. Bien qu'il puisse être à un niveau trop fin pour ce que vous avez besoin, il peut-être des trucs ici, vous pouvez l'utiliser.

2
répondu Paul Morrison 2009-02-20 00:33:41
la source

jetez un coup d'oeil à boost::future (mais Voir Aussi cette discussion et proposition ) qui ressemble à une base vraiment agréable pour le parallélisme (en particulier, il semble offrir un excellent soutien pour C-depends-on-a-and-B Type situations).

J'ai un peu regardé OpenMP mais (comme vous) je n'étais pas convaincu qu'il fonctionnerait bien pour tout sauf Fortran/C code numérique. Le filetage d'Intel Les blocs de construction m'ont paru plus intéressants.

S'il vient, il n'est pas trop dur à rouler propre sur le dessus de boost::thread. [Explication: un fil farm (la plupart des gens l'appellerait un pool) tire son travail d'un fil-safe file de foncteurs (tâches ou emplois). Voir les tests et benchmark pour des exemples d'utilisation. J'ai quelques extra complication (éventuellement) des tâches de support avec des priorités, et le cas où l'exécution de tâches peuvent engendrer encore plus de tâches dans la file d'attente de travail (ce qui fait de savoir quand tout le travail est fait terminée un peu plus problématique; les références à "en attente" sont ceux qui peuvent traiter le cas). Ça pourrait te donner des idées de toute façon.]

1
répondu timday 2009-02-19 17:01:46
la source

vous pouvez regarder Intel Thread Building Blocks . Je crois qu'il fait ce que vous voulez et avec la version 2 C'est Open Source.

1
répondu Shane Powell 2009-02-20 09:04:38
la source

il y a beaucoup de gestionnaires de ressources distribués. Le logiciel qui répond à presque tous vos besoins est Sun Grid Engine . SGE est utilisé sur certains des plus grands supercalculateurs mondiaux et est en cours de développement.

il y a aussi des solutions similaires dans Torque , plate-forme LSF , et Condor .

il semble que vous pourriez vouloir roulez votre propre, mais il ya beaucoup de fonctionnalité dans tout ce qui précède.

1
répondu AdamK 2009-02-20 11:38:21
la source

Je ne sais pas si vous cherchez une bibliothèque C++ (ce que je pense que vous êtes), mais le Fork/Join framework de Doug Lea pour Java 7 est assez astucieux, et fait exactement ce que vous voulez. Vous pourrez probablement l'implémenter en C++ ou trouver une bibliothèque pré-implémentée.

plus d'informations ici: http://artisans-serverintellect-com.si-eioswww6.com/default.asp?W1

0
répondu Itay 2009-02-20 05:54:39
la source

un peu tard pour le punch peut-être, mais jetez un oeil aussi à ThreadWeaver: http://en.wikipedia.org/wiki/ThreadWeaver

0
répondu 2009-08-08 02:39:34
la source