Y at-il implémentation C++ (codes sources) de "optmistic approach to lock-free FIFO queues" algorithm?Une implémentation de file d'attente FIFO sans verrouillage optimiste existe-t-elle?
Répondre
Herb Sutter couvert une telle file d'attente dans le cadre de sa colonne efficace Concurency dans Dr. Dobbs Journal.
Si vous re à la recherche d'une bonne mise en œuvre de la file d'attente verrouillée à la fois Microsoft Visual Studio 2010 & Les blocs de création de threads d'Intel contiennent une bonne file d'attente LF qui est similaire au papier
Je veux conclure la réponse donnée par greyfade, qui est basé sur http://www.drdobbs.com/high-performance-computing/212201163 (la dernière partie de l'article), le code optimisé serait (avec quelques modifications en fonction de ma dénomination et convention de codage) : `
template <typename T> class LFQueue {
private:
struct LFQNode {
LFQNode(T* val) : value(val), next(nullptr) { }
T* value;
AtomicPtr<LFQNode> next;
char pad[CACHE_LINE_SIZE - sizeof(T*) - sizeof(AtomicPtr<LFQNode>)];
};
char pad0[CACHE_LINE_SIZE];
LFQNode* first; // for one consumer at a time
char pad1[CACHE_LINE_SIZE - sizeof(LFQNode*)];
InterlockedFlag consumerLock; // shared among consumers
char pad2[CACHE_LINE_SIZE - sizeof(InterlockedFlag)];
LFQNode* last; // for one producer at a time
char pad3[CACHE_LINE_SIZE - sizeof(LFQNode*)];
InterlockedFlag producerLock; // shared among producers
char pad4[CACHE_LINE_SIZE - sizeof(InterlockedFlag)];
public:
LFQueue() {
first = last = new LFQNode(nullptr); // no more divider
producerLock = consumerLock = false;
}
~LFQueue() {
while(first != nullptr) {
LFQNode* tmp = first;
first = tmp->next;
delete tmp;
}
}
bool pop(T& result) {
while(consumerLock.set(true))
{ } // acquire exclusivity
if(first->next != nullptr) { // if queue is nonempty
LFQNode* oldFirst = first;
first = first->next;
T* value = first->value; // take it out
first->value = nullptr; // of the Node
consumerLock = false; // release exclusivity
result = *value; // now copy it back
delete value; // and clean up
delete oldFirst; // both allocations
return true; // and report success
}
consumerLock = false; // release exclusivity
return false; // queue was empty
}
bool push(const T& t) {
LFQNode* tmp = new LFQNode(t); // do work off to the side
while(producerLock.set(true))
{ } // acquire exclusivity
last->next = tmp; // A: publish the new item
last = tmp; // B: not "last->next"
producerLock = false; // release exclusivity
return true;
}
};
`
une autre question est de savoir comment définissez-vous CACHE_LINE_SIZE? cela varie sur les processeurs jamais à droite?
Un bon nombre à choisir serait être '64' octets, je pense. Mais vous voudrez probablement l'équilibrer avec la taille, donc je vous suggère de regarder vos processeurs cibles et de choisir une taille qui correspond aux plus communs que vous prévoyez de cibler. – greyfade
Juste un petit mot: ce n'est pas un forum, donc les gens ne peuvent pas supposer "parcourir le fil". Si vous souhaitez poser une autre question, vous devriez mieux utiliser le champ «Poser une question» plutôt que le champ «Votre réponse». –
Je suis en effet re-répondre à la question, mais j'avais tort de demander dans le champ de réponse, je devrais ajouter un nouveau commentaire sous ma propre nouvelle réponse. Désolé pour ça. – uray
Voici ma mise en œuvre d'un FIFO sans verrouillage.
Assurez-vous que chaque élément de T est un multiple de 64 octets (la taille de la ligne de cache dans les processeurs Intel) afin d'éviter un faux partage.
Ce code est compilé avec gcc/mingw et doit être compilé avec clang. Il est optimisé pour 64 bits, donc pour l'exécuter sur 32 bits, il faudrait un refactoring.
https://github.com/vovoid/vsxu/blob/master/engine/include/vsx_fifo.h
vsx_fifo<my_struct, 512> my_fifo;
Auteur:
my_struct my_struct_inst;
... fill it out ...
while (!my_fifo.produce(my_struct_inst)) {}
Récepteur:
my_struct my_struct_recv;
while(my_fifo.consume(my_struct_recv))
{
...do stuff...
}
Comme je le vois, il est thread safe mais pas réentrant. – peterh
qui est la théorie, ce qui est demandé i'am la mise en œuvre. Y a-t-il des codes sources ou une bibliothèque qui implémentent ces algorithmes? – uray
@uray: Oui. Dans l'article. – greyfade
où? Je ne vois aucun fichier de code source là. – uray