76 votes

Tampon circulaire sans verrouillage

Je suis en train de concevoir un système qui se connecte à un ou plusieurs flux de données, effectue une analyse des données et déclenche des événements en fonction du résultat. Dans une configuration typique de producteur/consommateur multithread, j'aurai plusieurs threads de producteur mettant des données dans une file d'attente, et plusieurs threads de consommateur lisant les données, et les consommateurs sont seulement intéressés par le dernier point de données plus un nombre n de points. Les threads du producteur devront se bloquer si le consommateur lent ne peut pas suivre, et bien sûr les threads du consommateur se bloqueront lorsqu'il n'y aura pas de mises à jour non traitées. L'utilisation d'une file d'attente concurrente typique avec un verrou de lecteur/écrivain fonctionnera bien mais le taux de données entrant pourrait être énorme, donc je voulais réduire mes frais de verrouillage, en particulier les verrous d'écriture pour les producteurs. Je pense qu'un tampon circulaire sans verrou est ce dont j'avais besoin.

Maintenant, deux questions :

  1. Le tampon circulaire sans verrou est-il la solution ?

  2. Si c'est le cas, avant que je ne crée mon propre système, connaissez-vous une implémentation publique qui répondrait à mes besoins ?

Toute indication sur l'implémentation d'un tampon circulaire sans verrou est la bienvenue.

BTW, je fais ça en C++ sur Linux.

Quelques informations supplémentaires :

Le temps de réponse est critique pour mon système. Idéalement, les fils consommateurs voudront voir les mises à jour arriver le plus rapidement possible, car un retard supplémentaire d'une milliseconde pourrait rendre le système sans valeur, ou avec une valeur bien moindre.

L'idée de conception vers laquelle je penche est un tampon circulaire semi-libre où le thread producteur met les données dans le tampon aussi vite qu'il le peut, appelons-le la tête du tampon A, sans blocage jusqu'à ce que le tampon soit plein, lorsque A rencontre la fin du tampon Z. Les threads consommateurs détiendront chacun deux pointeurs vers le tampon circulaire, P et P n où P est la tête de mémoire tampon locale du thread et P n est le nième élément après P. Chaque thread de consommateur fera avancer ses P et P n une fois qu'il a fini de traiter le P actuel et que le pointeur de fin de tampon Z est avancé avec le P le plus lent n . Lorsque P rattrape A, ce qui signifie qu'il n'y a plus de nouvelle mise à jour à traiter, le consommateur tourne et attend que A avance à nouveau. Si le thread du consommateur tourne trop longtemps, il peut être mis en veille et attendre une variable de condition, mais je suis d'accord avec le fait que le consommateur prenne un cycle CPU en attendant la mise à jour car cela n'augmente pas ma latence (j'aurai plus de cœurs CPU que de threads). Imaginez que vous ayez une piste circulaire, et que le producteur soit devant un groupe de consommateurs, la clé est de régler le système de sorte que le producteur soit généralement juste un peu en avance sur les consommateurs, et la plupart de ces opérations peuvent être effectuées en utilisant des techniques sans verrou. Je comprends qu'il n'est pas facile d'obtenir les détails de l'implémentation correcte... ok, très difficile, c'est pourquoi je veux apprendre des erreurs des autres avant de faire les miennes.

0 votes

Je pense qu'il serait utile d'esquisser l'API que vous voulez que cette structure de données implémente.

1 votes

Une chose que j'ai apprise, c'est de prendre de gros morceaux de travail. Je ne connais pas la taille de vos éléments de travail, mais vous pouvez gagner en efficacité si vous pouvez produire de plus gros morceaux et consommer de plus gros morceaux. Vous pouvez également l'augmenter en consommant des morceaux de taille variable afin que les consommateurs ne terminent pas tous en même temps et ne se disputent pas la file d'attente des données.

0 votes

Il faut également se demander si vous avez besoin d'un seul tampon ou d'une série de tampons. Vous pourriez avoir des paires producteur/consommateur partageant un tampon, et lorsqu'un tampon est plein, le producteur ou le consommateur passe temporairement à un autre tampon ouvert. C'est une forme de vol de travail.

3voto

Nikolay Tsenkov Points 376

Il s'agit d'un vieux sujet, mais puisqu'il n'a pas encore été mentionné, il existe une FIFO circulaire, sans verrou, 1 producteur -> 1 consommateur, disponible dans le framework JUCE C++.

https://www.juce.com/doc/classAbstractFifo#details

3voto

Saman Barghi Points 86

Bien que ce soit une vieille question, personne n'a mentionné DPDK Le tampon de l'anneau sans verrouillage. Il s'agit d'un tampon en anneau à haut débit qui prend en charge plusieurs producteurs et plusieurs consommateurs. Il offre également des modes consommateur unique et producteur unique, et le tampon en anneau est sans attente en mode SPSC. Il est écrit en C et supporte plusieurs architectures.

En outre, il prend en charge les modes "Bulk" et "Burst", dans lesquels les éléments peuvent être mis en file d'attente/deux fois en vrac. La conception permet à plusieurs consommateurs ou producteurs d'écrire dans la file d'attente en même temps en réservant simplement l'espace par le déplacement d'un pointeur atomique.

2voto

gabr Points 20458

Juste pour être complet : il existe un tampon circulaire sans verrou bien testé dans le module OtlContainers mais il est écrit en Delphi (TOmniBaseBoundedQueue est un tampon circulaire et TOmniBaseBoundedStack est une pile bornée). Il existe également une file d'attente non bornée dans la même unité (TOmniBaseQueue). La file d'attente non bornée est décrite dans File d'attente dynamique sans verrou - bien faire les choses . La mise en œuvre initiale de la file d'attente bornée (tampon circulaire) a été décrite dans le document Une file d'attente sans verrou, enfin ! mais le code a été mis à jour depuis.

2voto

Rolf Kristensen Points 1326

Vérifiez Disrupteur ( Comment l'utiliser ) qui est un tampon circulaire auquel plusieurs threads peuvent s'abonner :

1voto

switchmode Points 155

http://dream.eng.uci.edu/eecs123/2009sp_3_NBB.pdf

Le diaporama du cours de mon professeur sur les tampons sans verrou et non bloquants.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X