2010-08-05 18 views
1

Pour résoudre un problème (et mieux comprendre le multitâche), j'ai écrit une petite implémentation de pool de threads. Ce pool de threads génère un certain nombre de threads de travail qui détachent les tâches d'une file d'attente au fur et à mesure qu'elles sont ajoutées par le client du pool de threads. Pour les besoins de cette question, lorsque la file d'attente de tâches est vide, les threads de travail sont tous terminés. Après avoir effectué une analyse de base, j'ai découvert que l'application consacrait environ 60% de son temps à l'acquisition du verrou de la file d'attente. Vraisemblablement, cela se passe principalement dans les fils de travail.Optimisation de l'utilisation des threads de travail

Est-ce simplement une indication que je ne donne pas assez de travail aux threads de travail, ou quelque chose de plus? Y a-t-il quelque chose de simple que je puisse manquer pour augmenter le débit du fil de travail?

EDIT: Voici un pseudo-code approximatif qui devrait illustrer quelque peu les choses. Ce sont les deux seuls endroits où un verrou est acquis/libéré lors de l'exécution des threads de travail (ce qui est une grande majorité du temps d'exécution de l'application.)

std::list<task_t> task_list; 

// Called by the client to add tasks to the thread pool 
void insert_task(const task_t& task) 
{ 
    lock_type listlock(task_mutex); 

    task_list.push_back(task); 
} 

// The base routine of each thread in the pool. Some details 
// such as lifetime management have been omitted for clarity. 
void worker_thread_base() 
{ 
    while (true) 
    { 
     task_t task; 

     { 
     lock_type listlock(task_mutex); 

     if (task_list.empty()) 
      continue; 

     task = task_list.front(); 

     task_list.pop_front(); 
     } 

     do_task(task); 
    } 
} 
+1

Nous avons besoin de voir du code pour voir pourquoi votre application est bloquée sur le verrou de la file d'attente. Je pense que vos threads devraient être bloqués sur un état "wait" (en utilisant une variable de condition ou quelque chose de similaire) la plupart du temps. – Starkey

Répondre

0

Votre conception est construite là où chaque fil se trouve et "tourne" en essayant d'acquérir le verrou. Cela se produira constamment à moins que chaque thread de travail n'effectue un travail - dans ce cas, le verrou restera inactif et le travail se produira.

Avec tous vos threads simplement assis, tournant sur une serrure, vous allez utiliser un peu de temps processeur en attente. C'est quelque peu attendu, compte tenu de votre conception. Vous constaterez que le pourcentage de temps bloqué diminuera probablement considérablement si vous avez moins de threads de travail - et au moment où vous avez plus d'éléments de travail que de threads, vous passerez très peu de temps à attendre sur ce verrou.

Une conception beaucoup mieux serait d'utiliser une forme de file d'attente sans verrou pour votre file d'attente de travail, car cela pourrait empêcher l'attente à ce stade. De plus, avoir une poignée d'attente qui pourrait bloquer les threads de travail jusqu'à ce qu'il y ait du travail dans la file d'attente empêchera la rotation inutile.

0

Essayez-vous de le faire avec un serrure simple, serrures multiples? Mutexs? Quelle sémantique d'attente utilisez-vous?

Je suppose de votre description (et cela est purement une supposition) que vous avez quelque chose de similaire à:

lock(theLock) { 
// ... do lots of work ... 
} 

Dans votre thread principal qui contient le code pour envoyer les fils légers. Une raison pour laquelle vous pourriez voir des temps d'attente aggrevated sur ceci est parce que vous devez avoir des signaux à partir des threads spun qu'ils ont été mis en file d'attente et attendent l'exécution (encore une fois puisque vous n'avez donné aucun code). Une façon de résoudre ce problème est de passer d'un verrouillage explicite, comme ci-dessus, à l'utilisation d'un mutex signalé qui est pulsé lorsque vous voulez que l'un des threads fonctionne.

Sans voir votre implémentation actuelle, je ne suis pas sûr de pouvoir en faire beaucoup plus.