2017-08-29 2 views
-1

J'utilise le multi-threading C++ sur x64. Je voudrais mieux comprendre le bus de données. Je veux comprendre ce qui se passerait si j'essayais de définir une variable à partir de 2 threads sans aucun garde (pas de mutex, de CV, de sémaphore, et pas d'atomique). Qu'est-ce qui dépend du bus de données. Par exemple, si je variable:Définir une variable à partir de plusieurs threads sans protection en fonction du bus de données

int32_t i; 

si je mets variable dans différents fils: fil 1:

i =0x11223344; 

fil 2:

i =0x44332211; 

Comme je sais pour les données x64 le bus est 64 bits. Donc la variable i peut être réglée en 1 instruction. Je sais que cela dépend du compilateur. Je sais que le cache a aussi une influence. Je voudrais savoir seulement l'interaction avec le bus de données (sans cache). Ma question est ce que serait le comportement en fonction de la largeur du bus de données (8, 16, 32 bits). Quelle serait la valeur de i?

+2

Il n'y a rien à comprendre. Dans les 1400+ pages qui composent le standard C++ actuel, il n'y a aucune mention de ce qui est décrit comme un "bus de données". –

+0

C++ dit simplement que c'est un comportement indéfini, ce qui n'aide pas à répondre à la question.Vous devrez compiler le programme en assembleur, puis rechercher ce que font ces instructions d'assemblage pour savoir ce que le code fait (ce qui change évidemment en fonction des indicateurs du compilateur et d'autres choses). Vous devez publier le code d'assemblage afin qu'une réponse soit au moins possible. – nwp

+0

ma question est si l'ensemble est dans une instruction sont les deux seront atomiques. –

Répondre

1

La réponse est regrettable qu'il n'y a pas de réponse claire à votre question.

LET pas de loin de C++ pour un moment ici: Qu'est-ce que vous voulez faire est effectuer une écriture simultanée désynchronisé. Les garanties que vous pouvez donner en ce qui concerne le résultat d'une telle opération varient considérablement, en fonction d'un certain nombre de facteurs. Bien sûr, l'architecture cible joue un rôle majeur. Une machine avec un modèle de mémoire forte comme x86 pourrait être plus tolérant ici que, disons une machine PowerPC ou ARM. Mais cela ne s'arrête pas là. L'alignement pourrait jouer un rôle crucial, de même que la configuration de la mémoire spécifique sur la machine sur laquelle vous travaillez (pensez aux architectures NUMA). Il n'y a donc pas de solution universelle. Tout dépend très délicatement des circonstances, et même si les circonstances sont connues exactement, la réponse qui vous est souvent laissée est: Nous ne pouvons tout simplement pas dire, cela pourrait être quelque chose à la fin (y compris un nombre qui apparaît hors de -thin-air, c'est-à-dire, une valeur qui n'a été écrite par aucune des opérations d'écriture simultanées), car c'est simplement ainsi que le matériel a été construit.

À cause de cela, il ne suffit pas de sens de discuter de cette question sur un tel haut niveau. En ce qui concerne x86, il y a quelques garanties données par l'architecture du jeu d'instructions. N'hésitez pas à parcourir les sections pertinentes de the manual vous-même. Mais vous n'avez aucun moyen d'accéder à ces garanties à partir d'un langage de niveau supérieur si vous utilisez des accès mémoire non reconnus par le thread. Parce que le comportement n'est pas défini, le compilateur est autorisé à effectuer un nombre illimité d'optimisations qui peuvent gâcher le code généré de manière arbitraire, mais sont toujours compatibles avec ce que vous avez exprimé dans le code. Parce que votre code n'est pas conscient de la concurrence (par définition, comme vous utilisez un accès non synchronisé), le compilateur a le droit de le faire.

Ainsi, la seule solution est d'utiliser la synchronisation appropriée, par exemple des serrures ou Atomics. Ils donnent certaines garanties à la fois au niveau du langage (interdisant certaines optimisations du compilateur) et veillent à ce que ces garanties soient appliquées jusqu'au matériel (en insérant les instructions de synchronisation nécessaires dans le code machine généré). Ce n'est que si vous avez cette chaîne complète de garanties du langage de haut niveau jusqu'au silicium même qui compose le matériel que vous pouvez faire une programmation multi-thread appropriée. Enlevez n'importe quel lien de la chaîne et tout s'effondre.

+0

Oui, vous avez raison pour le haut niveau. Je pensais que, à la et devrait la valeur devrait être l'une des deux valeurs ou mélange d'octets comme (0x11222211). Une telle question sera peut-être mieux d'être demandé au niveau de l'assemblage ou peut-être juste au niveau du matériel. Ma question était pour la simple curiosité. Merci pour les détails. Je vais lire des choses de rosée du manuel. –

+0

@Vladimir - Sur un x64, une valeur entière correctement alignée est toujours écrite en une fois, de sorte qu'elle ne sera pas "mélangée". Cependant, à moins qu'il s'agisse d'un 'atomic ', il n'y a aucune garantie réelle qu'il soit écrit en mémoire. En outre, le compilateur peut tirer parti des fonctionnalités matérielles et utiliser les mêmes instructions pour lire des valeurs atomiques d'écriture que pour les valeurs "normales". Il suffit de s'assurer que c'est fait au bon moment. –