J'utilise boost compile drapeaux: p> sur ma machine: RHEL 7.1, GCC 4.8.3, Xeon E5- 2690 V3 Je reçois 290-300 nanosecondes. P> UPD: strong> Mécanisme de la file d'attente est requis. Si le premier fil produisait des données toutes les 1000 nanosecondes, mais deux poissons de fil de 10 000 nanosecondes pour traiter un article unique, j'ai besoin de "faire la queue" plusieurs articles pendant une courte période. Mais ma "file d'attente" n'est jamais "trop grande". Le tampon à anneau court à la taille fixe doit suffire. P> upd2 strong> Donc, en bref, la question est - quelle est la file d'attente unique à producteur unique la plus rapide (probablement basée sur une sonnerie de taille fixe )? J'utilise Boost SPSC_Queue et j'atteigne ~ 300 ns latence, pouvez-vous suggérer quelque chose de plus rapidement? P> upd3 strong> dans Java World il y a un perturbateur qui atteint 50 ns latence https://code.google.com/p/disrupturdor/wiki/performanceresults avons-nous quelque chose en C ++ avec la même latence de 50 ns? p> p> SPSC_QUEUE code> pour déplacer mes trucs d'un fil à un autre. C'est l'un des endroits critiques de mon logiciel pour que je tiens donc à le faire dès que possible. J'ai écrit ce programme de test:
3 Réponses :
Tout d'abord, écrire un tel programme de test est totalement inutile. Vous ne travaillez pas avec les données afin que les résultats soient asymétriques. Deuxièmement, votre test utilise USLEEP () entre les pousses - à ce rapport, vous pouvez utiliser n'importe quel type de primitif de synchronisation. Il semble également que votre consommateur () ne quitte jamais ... p>
La façon dont vous implémentez une telle chose est la suivante: p>
Vous avez besoin d'une expérience antérieure à la première étape ou vous pouvez essayer de mettre en œuvre différentes approches et de voir ce qui fonctionne mieux. P>
Comment mesurerez-vous la latence de SPSC_Queue?
@javapowered Dans ce cas, la latence dépend de la manière dont de threads utilisent la file d'attente simultanément. Ce n'est pas quelque chose que vous devriez vous soucier de si votre profileur ne le montre que c'est un problème.
Il est clair que ma question qu'il n'y a que 2 threads - celui qui produisent des données et une qui la consomment. Plus de 2 threads Case est beaucoup plus compliqué
@javapowered Comme je l'ai déjà dit, vous n'obtenez aucun résultat de votre demande de test. Tout ce que vous avez fourni dans la question ne fonctionne clairement pas. En ce qui concerne la latence, cela est compliqué à la mesure (dépend de nombreux facteurs). La façon dont vous le faites est également problématique car il n'ya aucune garantie que les threads exécutés réellement en parallèle (comme dans le code fourni) ou qu'aucun interrupteur de contexte ne se produit.
Si vous pensez que mon application n'est pas correcte, modifiez-le pour le rendre correct :)
Étant donné que vous avez Si (iff) que vous souhaitez minimiser la latence (pour un seul élément), mon devinez em> utiliserait un mécanisme de synchronisation de signalisation, Si (iff), cependant, vous souhaitez optimiser le débit (articles par heure), puis mesurer la latence d'un "réveil" d'un objet (unique) fait encore moins de sens. Dans ce cas, vous voulez faire la meilleure utilisation du parallélisme que vous avez, comme Souvent le moyen le plus rapide de passer des données consiste à utiliser un seul fil pour chaque morceau de données. C'est-à-dire qu'il n'utilise que le parallélisme présent dans les données. P>
blockQuote>
Adresses à votre balle: P>
Quelle est la bonne application de l'application de test: em> Je ne pense pas que cela ait beaucoup de sens. p>
le meilleur temps actuel em>: pas d'indice. Pas sûr que quiconque se soucie de cela. (Peut-être dans des trucs de noyau?) P> li>
choix de SPSC_QUEUE EM>: Je ne pense pas que ce soit un bon choix car il nécessite un sondage. P> Li>
plus vite que SPSC_QUEUE? EM>: voir ci-dessus. Utilisez une notification non interrogatoire. P> li>
Écrivez un code qui fait le même travail de manière significative plus rapide? EM>: Non. ou plutôt, je ne le ferai pas. => p> li>
ul>
Pour quote "Réponse de l'homme : p>
Le problème de votre question est que il n'y a pas de définition de problème fort>. p>
En ce qui concerne Jusqu'à présent, dans le contexte d'un processus d'utilisation de l'utilisateur sur un système d'exploitation régulier, la latence de notification de fil croisée semble totalement non pertinente. Quel est votre cas d'utilisation? strong> p> int code> s, ce que vous devez (idéalement) ci-dessus est la latence globale entre un appel à
push () code> à l'heure
POP () code> retourne
true code>. p>
pop code> a récupéré une valeur. P>
SPSC_QUEUE >
, autant que je puisse dire , ne prévoit pas cela. (Vous auriez besoin d'un conteneur ou d'une solution personnalisée où vous utilisez une sorte de variable de condition / événement, ...) p>
planchedatat code> dans un atomique est requis, car vous l'écrivez d'un fil et lisez-le d'un autre. Sinon, vous avez UB. LI>
struct {int Val; int64_t temps;}; code> dans la file d'attente, évitant ainsi la clôture atomique. Li>
ul> li>
"Sondage activement de la file d'attente" est par conception. J'ai 12 cœurs Machine et je peux passer plusieurs cœurs pour "interrogation opérationnelle" dans "hotspots". J'ai besoin de pouvoir stocker plusieurs articles. Donc, si le premier fil produisait des données toutes les 1000 nanosecondes, mais deux poissons de fil de 10 000 nanosecondes pour traiter un élément unique, j'ai besoin de "faire la queue" plusieurs articles pendant une courte période de temps. C'est pourquoi j'utilise SPSC_Queue. Mais 99,999% pourcentage du temps SPSC_Queue est vide et le consommateur vient de "interrogation activement".
Vous pourriez penser que vous avez des noyaux à dépenser, mais, comme je l'ai dit, ma suspicion est que pas i> Sondage devrait avoir la latence inférieure i>. (Je me trompe peut-être que vous seul pouvez mesurer cela pour votre cas.)
Définition du problème - j'ai besoin d'une file d'attente la plus rapide du consommateur unique à producteur unique
@javapowered - Ce n'est pas une définition de problème. Une définition de problème est la suivante: "Je veux faire x, donc Je pense i> J'ai besoin d'une notification rapide + file d'attente."
Je veux faire une fasse d'attente SPSC rapide donc je pense avoir besoin de file d'attente SPSC rapide
Cela dépend de la sémantique de l'application et du nombre de threads impliqués. Jusqu'à présent, vous regardez la latence crue. Avec plus de threads, la mise à l'échelle peut également commencer à être une métrique intéressante. p>
Pour le boîtier à deux filetés, des mises à jour atomiques à un seul emplacement, de préférence dans une ligne de cache qui n'est pas touchée par aucune autre opération, pourrait être plus rapide si ce que vous faites avec les données récupérées le permet. p>
Souvent, le moyen le plus rapide de passer des données est d'utiliser un seul fil pour chaque morceau de données. C'est-à-dire qu'il n'utilise que le parallélisme présent dans les données.
Dans votre référence, le démarrage du fil de consommation pourrait être inclus dans la latence mesurée. Mieux vaut attendre que le fil a commencé. Aussi une moyenne est sensible aux pointes. Conservez chaque latence mesurée et donnez-les après le test pour vérifier manuellement les modèles.
J'ai mis à jour l'exemple - Ajout de l'USLEEP pour vous assurer que le thread de consommation est prêt. Imprimez toutes les valeurs à la console. Tous mes résultats sont toujours valables et identiques.
Je suppose que vous savez que vous ne déménageez pas réellement (comme dans: Copier des bits) d'un fil à un autre? C'est juste la latence de synchronisation / notification pour le consommateur qui vous intéresse? Votre question de minimiser la latence de notification croisée croisée?
Aussi, de bonnes informations dans les anwers là-bas: Stackoverflow.com/questions/13020695/...
@Martinba
testquoise.push (i) code> copies INT vers SPSC_Queue,
testquoise.pop (i) code> laisse la valeur, il semble qu'il renvoie la référence au stockage interne
@javapowered - nah, bien sûr,
poussez code> et
pop code> copie des bits pour obtenir la valeur dans l'objet de la file d'attente, mais ce que je voulais dire, c'est que tu es ne pas copier de i> n'importe quel thread à i> tout autre fil. Toutes les choses résident simplement dans le magasin libre, accessibles à la fois au fil (en principe) tant que la syncronisation appropriée est utilisée.
@Martinba Donne-moi un exemple où vous "copiez-vous de n'importe quel fil à n'importe quel fil"
@javapowered - Impossible de vous donner un exemple, car il n'y a pas une telle chose i> comme face à un fil à un autre, lorsque vous regardez la mémoire de processus. Par définition (principalement) Les threads partagent le même magasin gratuit et vous n'avez pas besoin de copier quelque chose, il vous suffit de bien obtenir la synchronisation.
@Martinba Je ne suis pas expert matériel, mais différents threads peuvent être exécutés sur différents cœurs. Chaque noyau a son propre cache qui doit être "rafraîchi" parfois, c'est-à-dire copié de la mémoire principale. Quoi qu'il en soit, je ne suis déjà pas sous-estimant le point :)
Je modifierais votre test, au lieu d'avoir un tableau séparé pour les horodatages, appuyez simplement sur l'horodatage dans la file d'attente, puis lorsque vous sautez de l'autre côté, vous connaissez le retard pour cette entrée directement ... Ce sera la quantité minimale de Temps qu'il faut pour le consommateur de ramasser quelque chose que le producteur a produit ...
@Nim d'accord, de bons conseils. J'ai mis à jour le code et ma question. Cependant, je ne nave toujours pas 300 nanosecondes latence