Pool de threads pour l'exécution arbitraire de tâches avec des priorités différentes

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

  •  09-06-2019
  •  | 
  •  

Question

J'essaie de venir avec un design pour un pool de threads avec beaucoup d'exigences de conception pour mon travail.C'est un réel problème pour le logiciel de travail, et c'est une tâche difficile.J'ai un travail de mise en œuvre, mais je voudrais jeter de la SORTE et voir ce que les idées intéressantes, les gens peuvent venir avec, de sorte que je puisse comparer à mon application et voir comment il empile.J'ai essayé d'être la plus précise les exigences que je peux.

Le pool de threads doit exécuter une série de tâches.Les tâches peuvent être de courte durée (<1sec) ou longues (heures ou jours).Chaque tâche est associée à une priorité (de 1 = très faible à 5 = très élevé).Les tâches peuvent arriver à tout moment, tandis que les autres tâches en cours d'exécution, afin qu'ils arrivent le pool de threads besoin d'aller les chercher et de les planifier les fils deviennent disponibles.

La priorité de la tâche est totalement indépendant de la durée de la tâche.En fait, il est impossible de dire combien de temps une tâche pourrait prendre pour exécuter sans l'exécuter.

Certaines tâches sont en CPU, alors que certains sont grandement IO lié.Il est impossible de dire à l'avance ce qu'est une tâche donnée serait (bien que je suppose qu'il pourrait être possible de détecter alors que les tâches sont en cours d'exécution).

Le principal objectif du pool de threads est de maximiser le débit.Le pool de threads doit utiliser efficacement les ressources de l'ordinateur.Idéalement, pour les CPU, les tâches, le nombre de threads actifs serait égal au nombre de Processeurs.Pour les IO des tâches limitées, plus de threads doit être attribuée qu'il y a de Processeurs de sorte que le blocage ne pas trop affecter le débit.La minimisation de l'utilisation des écluses et l'utilisation de thread-safe/rapide conteneurs est important.

En général, vous devez exécuter plus élevé de priorité des tâches avec un CPU plus prioritaires (réf.:SetThreadPriority).Priorité inférieure de tâches ne doit pas "bloquer" de plus en plus la priorité des tâches en cours d'exécution, si une tâche plus urgente vient, alors que toutes les tâches prioritaires sont en cours d'exécution, la tâche une priorité plus élevée aurez à exécuter.

Les tâches ont un "max tâches en cours d'exécution" paramètre associé avec eux.Chaque type de tâche est uniquement autorisé à exécuter au plus ce nombre d'instances simultanées de la tâche à un moment.Par exemple, nous pourrions avoir les tâches suivantes dans la file d'attente:

  • Une - 1000 cas de faible priorité - max tâches 1
  • B - 1000 cas de faible priorité - max tâches 1
  • C - 1000 cas de faible priorité - max tâches 1

Un travail de mise en œuvre ne pouvait exécuter (au plus) 1 A, 1 B et 1 C à la même heure.

Il doit être exécuté sur Windows XP, Server 2003, Vista et Server 2008 (derniers service packs).


Pour référence, nous pourrions utiliser l'interface suivante:

namespace ThreadPool
{
    class Task
    {
    public:
        Task();     
        void run();
    };

    class ThreadPool
    {    
    public:
        ThreadPool();
        ~ThreadPool();

        void run(Task *inst);
        void stop();
    };
}
Était-ce utile?

La solution

Alors, qu'allons-nous choisir en tant que bloc de construction de base pour cela.Windows dispose de deux blocs de construction qui semblent prometteuses :- I/O Ports d'Achèvement (IOCPs) et les Appels de Procédure Asynchrone (Apc).Ces deux nous donner des files d'attente FIFO sans avoir à effectuer explicite de verrouillage, et avec un certain montant de l'intégré dans le support de l'OS dans des endroits comme le planificateur (par exemple, IOCPs peut éviter certains changements de contexte).

Les apc sont peut-être un peu plus en forme, mais nous allons être un peu prudent avec eux, parce qu'ils ne sont pas assez "transparent".Si l'élément de travail effectue une alertable attendre (::SleepEx, ::WaitForXxxObjectEx, etc.) et nous avons accidentellement envoi un APC le thread nouvellement distribué APC de reprendre le fil, la suspension de la déjà de l'exécution de l'APC jusqu'à ce que la nouvelle APC est fini.Cela est mauvais pour notre simultanéité exigences et peut faire des débordements de pile de plus en plus probable.

Autres conseils

Il doit être exécuté sur Windows XP, Server 2003, Vista et Server 2008 (derniers service packs).

Quelle est la caractéristique du système intégré de pools de threads de les rendre impropres à votre tâche?Si vous souhaitez cibler XP et 2003, vous ne pouvez pas utiliser le nouveau brillant Vista/2008 piscines, mais vous pouvez toujours utiliser QueueUserWorkItem et amis.

@DrPizza - c'est une très bonne question, et celui qui frappe droit au cœur du problème.Il ya quelques raisons pour lesquelles QueueUserWorkItem et Windows NT pool de thread a été exclu (bien que le Vista on n'a pas l'air intéressant, peut-être que dans quelques années).

Tout d'abord, nous voulions avoir plus de contrôle sur le moment où il commence et cesse de threads.Nous avons entendu dire que le NT pool de threads est réticent à lancer un nouveau fil de discussion, si elle estime que les tâches sont de courte durée.Nous pourrions utiliser la WT_EXECUTELONGFUNCTION, mais nous avons vraiment aucune idée de si la tâche est longue ou courte

Deuxièmement, si le pool de threads était déjà rempli avec de long en cours d'exécution, des tâches de faible priorité, il n'y aurait aucune chance d'une tâche hautement prioritaire arriver à exécuter dans un temps opportun.Le NT pool n'a pas de réelle notion de priorités des tâches, de sorte que nous ne pouvons pas faire QueueUserWorkItem et de dire "oh, en passant, d'exécuter tout de suite".

Troisièmement, selon MSDN) NT le pool de threads n'est pas compatible avec le personnel de l'appartement modèle.Je ne suis pas sûr de tout ce que cela signifie, mais l'ensemble de nos threads de s'exécuter dans un STA.

@DrPizza - c'est une très bonne question, et celui qui frappe droit au cœur du problème.Il ya quelques raisons pour lesquelles QueueUserWorkItem et Windows NT pool de thread a été exclu (bien que le Vista on n'a pas l'air intéressant, peut-être que dans quelques années).

Ouais, on dirait que c'est devenu assez étoffé dans Vista, assez polyvalent maintenant.

OK, je suis encore un peu confus au sujet de la façon dont vous souhaitez les priorités de travail.Si la piscine est actuellement en cours d'exécution d'une tâche de type A avec un maximum de simultanéité de 1 et de faible priorité, et il obtient une nouvelle tâche de type A (et maximale de la simultanéité 1), mais cette fois avec une priorité élevée, que doit-elle faire?

La suspension de l'exécution actuelle est poilue (il pourrait tenir un verrou que la nouvelle tâche doit prendre, blocage du système).Il ne peut pas générer un deuxième thread et le laisser courir à côté (le permis de simultanéité n'est que de 1).Mais il ne peut pas attendre jusqu'à ce que le faible degré de priorité de la tâche est terminée, parce que le runtime est illimitée, et cela permettrait à un faible priorité de la tâche de bloquer une grande priorité de la tâche.

Ma présomption, c'est que c'est ce comportement que vous êtes après?

@DrPizza:

OK, je suis encore un peu confus au sujet de la façon dont vous souhaitez les priorités de travail.Si la piscine est actuellement en cours d'exécution d'une tâche de type A avec un maximum de simultanéité de 1 et la faible priorité, et il obtient donné une nouvelle tâche également de type A (et maximale la simultanéité 1), mais cette fois avec une haute priorité, que doit-elle faire?

Celui-ci est un peu délicate, mais dans ce cas je pense que je serais heureux avec le fait qu'elle permet la faible priorité de la tâche à exécuter jusqu'à la fin.Habituellement, nous ne voyons pas beaucoup de les mêmes types de tâches avec des priorités différentes pour les threads.Dans notre modèle, il est effectivement possible en toute sécurité d'arrêter et de redémarrer plus tard des tâches à certains points bien définis (pour des raisons différentes que cela) bien que les complications que cela introduirait ne sont probablement pas la peine le risque.

Normalement, seules les différents types de tâches ont des priorités différentes.Par exemple:

  • Une tâche - 1000 cas de faible priorité
  • B tâche - 1000 cas - haute priorité

En supposant que l'Une des tâches était venu le long et ont été en cours d'exécution, puis le B tâches étaient arrivés, et nous voulons le B tâches pour être en mesure de fonctionner plus ou moins tout de suite.

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