2010-04-30 4 views
1

Je cherche une approche qui me permettra d'assigner des nombres ordinaux 0 .. (N-1) à N O/S threads, de sorte que les threads sont dans un ordre numérique. C'est-à-dire que le thread qui obtient aura un ID de thread O/S inférieur au thread avec un ordinal 1.algorithme de commande de fil rapide sans atomique CAS

Pour ce faire, les threads communiquent via un espace mémoire partagé. Le modèle d'ordre de mémoire est tel que les écritures seront atomiques (si deux threads simultanés écrivent un emplacement mémoire en même temps, le résultat sera l'un ou l'autre). La plate-forme ne prendra pas en charge les opérations de comparaison et de définition atomiques. Je recherche un algorithme qui soit efficace en termes de nombre d'écritures dans la mémoire partagée, et qui se termine rapidement avec des dizaines de milliers de threads, sans aucune mauvaise situation d'arrivée de thread.

Le système d'exploitation attribuera des numéros de thread dans un ordre arbitraire dans un espace de 32 bits. Il peut y avoir des retards de création de threads arbitraires - l'algorithme peut être considéré comme terminé lorsque tous les N threads sont présents. Je suis incapable d'utiliser la solution évidente de rassembler tous les threads, puis de les trier - sans opération atomique, je n'ai aucun moyen de collecter en toute sécurité tous les threads individuels (un autre thread pourrait réécrire le slot) .

Répondre

1

Si j'ai ce droit, vous voulez mapper Integer-> Integer où l'entrée dans un nombre arbitraire de 32 bits, et la sortie est un nombre de 0-N où N est le nombre de threads?

Dans ce cas, chaque fois que vous créez un nouvel appel de fil cette méthode, la valeur retournée est l'ID:

integer nextId = 0; 
integer GetInteger() 
{ 
    return AtomicIncrement(nextId); 
} 

Cet algorithme est évidemment O (N)

En supposant plusieurs choses:

  1. fils ne meurent jamais
  2. Vous avez une sorte d'incrément atomique qui incrémente un nombre et retourne l'ancienne valeur ou ne w valeur, la différence se situe entre 0 et 1 à base ID basés
  3. threads appellent une méthode demande ce que leur identité est juste une fois quand ils sont créés
+0

Où puis-je trouver une implémentation d'AtomicIncrement qui ne repose pas sur des primitives atomiques? Atomic Compare-and-Set semble nécessaire pour implémenter AtomicIncrement. – caffiend

+0

Certaines plates-formes ont un opérateur intrinsèque AtomicIncrement, sinon, vous devez le construire avec CAS et vous êtes bourré. – Martin

+0

Parce que cela ne s'exécute qu'une seule fois pour chaque thread, vous pouvez simplement utiliser un spinlock. Dans la plupart des cas, il ne tournera pas du tout, dans certains cas cela prendra un peu plus de temps mais même pas très longtemps à moins que vous ne créiez des centaines de threads par seconde. – Martin

4

Sans prétention d'être optimale dans tous les sens (il y a des méthodes nettement plus rapides pour faire cela avec des opérations atomiques de comparaison et d'ensemble, ou comme Martin l'indique, incrément atomique) ...

En supposant que N est connu de tous les threads, et que chaque thread a une valeur d'ID unique non nulle , comme son adresse de pile dans l'espace de 32 bits ...

Utilisez un tableau de taille N dans l'espace partagé; assurez-vous que ce tableau est initialisé à zéro.

Chaque thread possède le premier emplacement du tableau qui contient un ID inférieur ou égal à l'ID du thread; le fil écrit son ID là. Cela continue jusqu'à ce que le tableau soit plein de valeurs non nulles, et toutes les valeurs sont dans l'ordre décroissant.

À la fin de l'algorithme, l'indice de l'emplacement du thread dans le tableau est son nombre ordinal.

+0

Je ne suis pas sûr de comprendre complètement cela - en faisant des suppositions, il semble que vous pourriez avoir un scénario où tous les threads mais le plus bas ont des slots. Le bas arrive, écrase le plus bas actuel. Le 2ème au plus bas écrase maintenant le 3ème, et cette chaîne continue jusqu'à ce que tous les threads se soient déplacés d'une unité? – caffiend

+0

@caffiend, oui, vous pourriez certainement obtenir le comportement que vous décrivez; c'est bien, mais le pire des cas de comportement. C'est bien parce que les slots ne sont pas définitifs jusqu'à ce que l'algorithme se termine; c'est le pire des cas puisque chaque thread doit "recommencer" quand un nouveau thread à faible ID entre dans la partie. En pensant au pire des cas, chaque thread déplacerait son identifiant dans le tableau au plus N fois, donc c'est un algorithme O (N-carré) [Notez que les threads seulement besoin de regarder les fentes à ou au-delà de leur emplacement actuel le tableau, donc ils ne traversent le tableau qu'une seule fois]. –

+0

O (N ** 2) est très effrayant avec le nombre potentiel de threads - pire le manque de réponse est important, et je pense que cet algorithme doit fonctionner jusqu'à ce que tous les threads ont des nombres .. En pensant au tableau, il semble que soluble dans O (log N) en utilisant des techniques de tri? – caffiend

Questions connexes