Différence de performance entre la mémoire partagée IPC et la mémoire des threads
J'entends souvent que l'accès à un segment de mémoire partagée entre les processus n'a pas de perte de performance par rapport à l'accès à la mémoire de processus entre les threads. En d'autres termes, une application multi-thread ne sera pas plus rapide qu'un ensemble de processus à l'aide de la mémoire partagée (à l'exclusion de verrouillage ou d'autres problèmes de synchronisation).
Mais j'ai des doutes:
1) shmat() cartes le processus local de la mémoire virtuelle sur le segment partagé. Cette traduction doit être effectuée pour chaque adresse d'une mémoire partagée et peut représenter un coût important. Dans une application multi-thread il n'existe pas de traduction supplémentaires requis: toutes les VM adresses sont convertis en adresses physiques, comme dans un processus régulier qui n'a pas accès à la mémoire partagée.
2) Le segment de mémoire partagée doit être maintenue en quelque sorte par le noyau. Par exemple, lorsque tous les processus attachés à la shm sont prises vers le bas, la shm segment est encore et peut être à terme, d'accéder à nouveau par de nouveaux processus. Il pourrait y avoir des frais généraux liés à noyau opérations sur la shm segment.
Est un multi-processus de la mémoire partagée du système aussi rapide qu'une application multi-thread?
source d'informationauteur Robert Kubrick
Vous devez vous connecter pour publier un commentaire.
Il n'y a pas de frais généraux par rapport à la régulière accès à la mémoire à part le coût initial de configurer les pages partagées - remplissage de la page table dans le processus qui appelle
shmat()
- dans la plupart des saveurs de Linux que de 1 page (4 ou 8 octets) par 4 ko de mémoire partagée.C'est (à tous les éléments pertinents de comparaison), au même prix, si les pages sont allouées partagée ou au sein du même processus.
Qu'elles soient partagées ou non, chaque page de mémoire a un "struct page" qui y est attaché, avec quelques données à propos de la page. L'un des éléments est un compteur de référence. Lorsqu'une page est consacrée à un processus [si c'est par "shmat", ou quelque autre mécanisme], le nombre de références est incrémenté. Lorsqu'il est libéré par certains moyens, la référence compteur est décrémenté. Si le nombre est décrémenté à zéro, la page est réellement libérés sinon "rien ne se passe".
La surcharge est essentiellement à zéro, par rapport à toute autre mémoire allouée. Le même mécanisme est utilisé pour d'autres fins pour les pages de toute façon - dire par exemple vous avez une page qui est également utilisé par le noyau et votre processus meurt, le noyau a besoin de savoir, de ne pas libérer cette page jusqu'à ce qu'il a été publié par le noyau de l'utilisateur-processus.
La même chose arrive quand une "fourchette" est créé. Lorsqu'un processus est fourchue, la totalité de la page table des processus parent est essentiellement copié dans le processus de l'enfant, et toutes les pages mises en lecture seule. Chaque fois qu'une écriture qui se passe, un problème est pris en compte par le noyau, ce qui conduit à cette page copié - il y a donc désormais deux copies de cette page, et le processus de faire de l'écriture peut modifier la page, sans affecter les autres processus. Une fois que l'enfant (ou le parent) processus meurt, bien sûr, toutes les pages sont encore détenus par les DEUX processus [tels que le code de l'espace, qui n'est jamais écrit, et probablement un tas de données commune qui n'a jamais touché, etc] ne peuvent évidemment pas être libéré jusqu'à ce que les DEUX processus sont "morts". Encore une fois, la référence compté les pages de venir dans utile ici, car on n'a de compte à rebours de la ref-comte sur chaque page, et lorsque la ref-count est égal à zéro, lorsque tous les processus à l'aide de cette page est libéré, la page est en fait retourné comme une "page utile".
Exactement la même chose arrive avec les bibliothèques partagées. Si un processus utilise une librairie partagée, il sera libérée lorsque le processus se termine. Mais si deux, trois ou 100 les processus utilisent la même librairie partagée, le code sera évidemment rester dans la mémoire jusqu'à ce que la page n'est plus nécessaire.
Donc, en gros, toutes les pages de l'ensemble du noyau sont déjà référence compté. Il y a très peu de frais généraux.
De la configuration de la mémoire partagée nécessite un travail supplémentaire par le noyau, de sorte que l'attachement/détachement d'une région de mémoire partagée à partir de votre processus peut être plus lente qu'une simple allocation de mémoire (ou peut être pas... je n'ai jamais comparé). Mais, une fois qu'il est attaché à votre processus de mémoire virtuelle carte de mémoire partagée est pas différent de toute autre mémoire pour les accès, sauf dans le cas où vous avez plusieurs processeurs de la lutte pour le même cache-ligne de la taille des morceaux. Donc, en général, de la mémoire partagée doit être aussi rapide que n'importe quel autre souvenir pour la plupart des accès, mais, selon ce que vous mettez là, et combien de threads/processus d'accès, vous pouvez obtenir un certain ralentissement pour certains modèles d'utilisation.
Côté les coûts pour la fixation (
shmat
) et le détachement (shmdt
) de la mémoire partagée, l'accès devrait être aussi rapide. En d'autres termes, il doit être rapide comme le matériel prend en charge. Il devrait y avoir pas de frais généraux sous la forme d'une couche supplémentaire pour chaque accès.De synchronisation doit être aussi rapide, aussi. Par exemple, sous Linux, un futex peut être utilisé à la fois les processus et les threads. Variable atomique devrait aussi bien fonctionner.
Tant que l'attachement/détachement des coûts ne dominent pas, il devrait y avoir aucun inconvénient pour l'utilisation de processus. Les Threads sont plus simples, cependant, et si vos processus sont essentiellement des courts-lifed, l'attachement/détachement de surcharge peut être un problème. Mais comme les coûts pour créer le processus sera élevé, de toute façon, cela ne devrait pas être un scénario probable si vous êtes préoccupé par la performance.
Enfin, cette discussion pourrait être intéressant: Sont shmat et shmdt cher?. (Mise en garde: Il est tout à fait obsolète. Je ne sais pas si la situation a changé depuis.)
Cette question pourrait également être utile: Quelle est la différence entre la mémoire partagée pour les IPCs et les fils de la mémoire partagée?
(La réponse courte: Pas beaucoup.)
Le coût de la mémoire partagée est proportionnelle au nombre de "méta" des modifications: répartition, de libération, de sortie de processus, ...
Le nombre d'accès à la mémoire n'a pas un rôle à jouer. Un accès à une salle de segment est aussi rapide qu'un accès de n'importe où ailleurs.
Le PROCESSEUR effectue la page mappage de table. Physiquement, le CPU ne savent pas que la cartographie est partagé.
Si vous suivez les meilleures pratiques (ce qui est rarement le changement de la cartographie), vous obtenez fondamentalement les mêmes performances qu'avec les processus de mémoire privée.
Si l'on considère ce qui se passe au niveau de la microélectronique lorsque deux threads ou processus accèdent à la même mémoire, il y a d'intéressantes conséquences.
Le point d'intérêt est de savoir comment l'architecture du PROCESSEUR permet à plusieurs cœurs (donc, les threads et les processus) pour accéder à la même mémoire. Cela se fait par le biais de la L1 caches, puis la L2, L3 et enfin de la mémoire DRAM. Il y a énormément de coordination a aller sur entre les contrôleurs de tous.
Pour une machine avec 2 Processeurs ou plus, que la coordination se déroule sur un bus série. Si l'on compare les bus de la circulation qui a lieu quand deux cœurs sont accédant à la même mémoire, et lorsque les données sont copié à un autre morceau de la mémoire, c'est environ la même quantité de trafic.
Donc selon où dans une machine, les deux fils sont en cours d'exécution, il peut y avoir peu de vitesse peine de copier les données de vs faire partager.
La copie peut être 1) un memcpy, 2) un tuyau d'écriture, 3) un interne de transfert DMA (puces Intel pouvez le faire ces jours-ci).
Interne DMA est intéressante car elle ne nécessite aucun temps CPU (un naïf memcpy est juste une boucle, prend effectivement du temps). Donc, si l'on peut copier des données, au lieu de partager des données, et cela, avec un intérieur DMA, vous pouvez être rapide, comme si vous étiez le partage de données.
La pénalité est de plus de RAM, mais le retour sur investissement est que des choses comme Acteur modèle de programmation sont en jeu. C'est une façon pour enlever toute la complexité de la sécurisation de la mémoire partagée avec les sémaphores à partir de votre programme.