4 Réponses :
Oui, vous avez raison - la différence entre les modèles de mémoire faibles et solides est une différence dans les optimisations disponibles (ordre des lectures / écriture et des clôtures associées). P>
Vous pouvez spécifier un modèle de mémoire en commençant par un modèle cohérent séquentiellement (le modèle le plus restrictif ou le plus fort), puis spécifiez comment les lectures et les écrires à partir d'un seul thread peuvent être introduits, supprimés ou déplacés par rapport aux autres. p>
Dans ce modèle (cohérent séquentiellement), la mémoire est indépendante de l'un des processeurs (threads) qui l'utilisent. La mémoire est connectée à chacun des threads par un contrôleur qui alimente les demandes de lecture et d'écriture de chaque thread. Le lit lit et écrit à partir d'une mémoire de fil à un seul thread dans
exactement forte> la commande spécifiée par le thread, mais elles pourraient être entrelacées avec des lectures et écrites d'autres threads de manière non spécifiée p> blockQuote> Comprendre l'impact des techniques à faible serrure dans des applications multithreaded p>
Cependant, il n'y a pas de liaison exacte entre des modèles de mémoire forts et faibles, à moins que vous ne considériez que les autres. Certains d'entre eux sont tout simplement plus forts / plus faibles et donc plus ouverts aux optimisations par réorganisation que d'autres. Par exemple, le modèle de mémoire in .NET 2.0 pour X86 permet de mieux les optimisations de la véronée 1.1 pour pouvoir être considérées comme un modèle plus faible. P>
Les deux termes ne sont pas clairement définis et ce n'est pas une chose noire / blanche. P>
Les modèles de mémoire peuvent être extrêmement faibles, extrêmement forts ou partout entre. p>
Il fait essentiellement référence aux garanties offertes sur les accès à la mémoire simultanée. P>
naïvement, vous vous attendriez à une écriture faite sur un fil, à être immédiatement visible à tous les autres threads. Et vous vous attendriez à ce que des événements apparaissent dans le même ordre sur tous les threads. P>
Mais dans un modèle de mémoire plus faible, aucun de ceux qui ne peuvent tenir. p>
La cohérence séquentielle est le terme pour un modèle de mémoire qui garantit que des événements sont vus dans le même ordre sur les threads tous les em>. Donc un modèle de mémoire qui garantit une consistance séquentielle est assez forte. P>
Une garantie plus faible est la cohérence causale: la garantie que les événements sont observés après les événements qu'ils dépendent. P>
En d'autres termes, si vous écrivez d'abord une valeur Il y a de nombreux autres niveaux de "consistance", certains plus forts, autres plus faibles et offrant toutes sortes de garanties subtiles sur ce que vous pouvez compter sur. P>
Fondamentalement, un modèle de mémoire plus fort va offrir davantage de garanties sur l'ordre dans lequel les événements sont observés et garantissent normalement le comportement plus proche de ce que vous attendiez intuitivement. P>
Mais un modèle plus faible permet une optimisation plus de place d'optimisation, et surtout, il échoue mieux avec plus de noyaux (car une synchronisation moins nécessaire) p>
La consistance séquentielle est essentiellement exempte d'un processeur monocolore, est faisable sur un quad-noyau, mais serait prohibitif sur un système de 32 cœurs ou un système avec 4 processeurs physiques. Ou un système de mémoire partagée entre plusieurs machines physiques. p>
Les noyaux que vous avez, et plus ils sont à part, plus ils sont plus difficiles à garantir qu'ils observent tous des événements dans le même ordre. Donc, des compromis sont fabriqués et vous vous contentez d'un modèle de mémoire plus faible qui gagne des garanties de lâche. P> x code> à une adresse
a code>, puis écrivez une deuxième valeur
y code> adresse, alors aucun thread ne sera jamais em> lire la valeur
y code> après la lecture de la valeur
x code>. Étant donné que les deux écrit sont à la même adresse, il violerait la cohérence causale si toutes les fils n'ont pas observé le même ordre.
Mais cela ne dit rien de ce qui devrait arriver à les événements em> non liés. Le résultat de l'écriture d'une troisième valeur à une adresse de mémoire différente pourrait être observé à l'absolument tout temps em> par d'autres threads (des threads différents peuvent observer des événements dans un ordre différent, contrairement à une consistance séquentielle) p>
"Un modèle de mémoire qui garantit une consistance séquentielle est assez forte". N'est-ce pas la définition de forte?
@Jonharrop: Cela dépend de qui vous demandez. Je ne suis pas au courant d'une seule définition canonique du terme. Mais oui, je serais enclin à être d'accord, dans la pratique, lorsque nous parlons de modèles de mémoire forts, nous signifions généralement une consistance séquentielle
En termes de concurrence, un modèle de mémoire spécifie les contraintes sur les accès des données et les conditions dans lesquelles des données écrites par un thread / noyau / processeur devient visible à une autre. P>
Les termes D'autre part, un modèle faible place très peu de contraintes sur le matériel, mais place la responsabilité de veiller à la visibilité entre les mains du programmeur. P>
Le modèle de mémoire le plus puissant est consistance séquentielle forte>: toutes les opérations à toutes les données de tous les processeurs forment une seule commande totale convenue par tous les processeurs, ce qui correspond à l'ordre des opérations sur chaque processeur individuellement. Ceci est essentiellement un entrelacement des opérations de chaque processeur. P>
Le modèle de mémoire le plus faible n'imposera aucune restriction sur l'ordre que les processeurs se voient écrit. Différents processeurs du même système peuvent voir écrit dans différentes commandes et que certains processeurs peuvent utiliser des données "stables" à partir de leur propre cache pendant une longue période après une écriture sur la même adresse de mémoire par un autre processeur. Parfois, les lignes de cache entières sont traitées comme une unité unique, une variable d'écriture sur une ligne de cache provoquera des écrires à partir d'autres processeurs à d'autres variables sur cette ligne de cache qui ne sont pas encore visibles au premier processeur à jeter efficacement, car Les valeurs obsolètes sont écrites sur le dessus lorsqu'elle écrit éventuellement la ligne de cache à la mémoire. Dans un tel système, il convient de veiller à ce que les données soient transférées sur d'autres processeurs dans le bon ordre, en utilisant des instructions de synchronisation explicite. p>
Par exemple, le modèle de mémoire Intel X86 est généralement considéré comme une extrémité plus forte, car il existe des règles strictes sur l'ordre dans lequel les écrires deviennent visibles pour les autres processeurs, alors que les processeurs Dec alpha et ARM sont généralement considérés comme ayant une Les modèles de mémoire faibles, comme l'écrit d'un processeur ne sont nécessaires que pour être visibles à d'autres processeurs dans un ordre particulier si vous mettez explicitement des instructions de commande (clôtures de mémoire ou barrières) dans votre code. P>
Certains systèmes ont une mémoire qui n'est accessible que par des processeurs particuliers. Le transfert de données entre ces processeurs nécessite donc des instructions de transfert de données explicites. C'est le cas avec les processeurs de cellules et est souvent le cas avec les GPU aussi. Cela peut être considéré comme une extrême d'un modèle de mémoire faible --- Les données ne sont visibles que par d'autres processeurs si vous invoquez explicitement le transfert de données. P>
Les langages de programmation imposent généralement leurs propres modèles de mémoire sur tout ce qui est fourni par les processeurs sous-jacents. Par exemple, C ++ 0x Spécifie un ensemble complet de contraintes de commande allant de complètement détendues à une consistance séquentielle complète, de sorte que vous pouvez spécifier en code ce dont vous avez besoin. D'autre part, Java dispose d'un ensemble très spécifique de contraintes de commande qui doivent être respectées et ne peuvent pas être variées. Dans les deux cas, le compilateur doit traduire les contraintes souhaitées dans les instructions pertinentes du processeur sous-jacent, qui peut être tout à fait impliquée si vous demandez une consistance séquentielle sur une machine faiblement commandée. P>
Google présente des résultats intéressants (principalement des documents scientifiques) sur des modèles de mémoire, mais quelqu'un peut-il expliquer ce qui est un modèle de mémoire faible et quel est un modèle de mémoire solide et leur relation avec la concurrence? P> blockQuote>
Un modèle de mémoire forte est l'un des endroits où, du point de vue des autres cœurs, des lectures et des écrivies semblent se produire comme ils apparaissent dans le programme et, en particulier, dans l'ordre dans lequel ils apparaissent dans le programme. Ceci est connu comme une consistance séquentielle. P>
Un modèle de mémoire faible est celui où les exécutions de mémoire peuvent être modifiées par la CPU, par ex. réorganisé. Toutes les architectures CPU pratiques permettent de réorganiser des instructions. P>
Notez que Herb Sutter utilise un "modèle de mémoire solide" pour signifier un où les intrinsions atomiques ne sont pas réorganisées. Ce n'est pas la définition couramment acceptée. P>