Lorsque le CPU avec un cache L1 fait une écriture, ce qui se passe normalement est que (en supposant que la ligne de cache sur laquelle il écrit est déjà dans le cache L1) le cache (en plus de mettre à jour les données) marque cette ligne de cache comme sale , et écrira la ligne avec les données mises à jour ultérieurement.
Une optimisation possible serait que le cache compare le contenu de l'écriture et le contenu précédent du cache, et s'ils sont identiques, ne marquez pas la ligne comme sale. Parce que cela pourrait permettre au cache d'éviter les réécritures à l'occasion, je peux voir comment le fabricant de CPU pourrait voir cela comme valant les portes nécessaires pour faire cette logique.
Ma question: y a-t-il des CPU qui effectuent cette optimisation?
Contexte de la raison pour laquelle je demande: j'écris du code qui doit avoir un accès constant à la mémoire; c'est-à-dire que quelqu'un qui est capable d'écouter le comportement du cache ne devrait pas pouvoir déduire ce que je fais. Certains de mes accès sont des écritures, et de manière évidente pour implémenter ce code, beaucoup d'écritures consisteront à écrire les mêmes données qui sont déjà là. J'ai besoin de faire les écritures car, selon les données, les données que j'écris peuvent être identiques ou non, et il est important d'effectuer la même action malgré tout. Si le processeur optimise en n'écrivant pas réellement une `` écriture sans changement '', cela signifierait que le comportement du cache varierait en fonction de ce que je fais, ce qui renverserait mon objectif.
Alors, y a-t-il un processeur qui essaie d'optimiser les écritures de cette façon?
Réponses:
Après des heures de recherche, je n'ai pas pu trouver un processeur qui utilise cette optimisation spécifique. La plupart des optimisations mentionnées sont généralement liées au hit / miss avec les opérations de lecture / écriture et l'accès aux données:
(pages 7 et) https://cseweb.ucsd.edu/classes/fa14/cse240A-a/pdf/08/CSE240A-MBT-L15-Cache.ppt.pdf
Cependant, cela ne signifie pas que cette optimisation ne peut pas être effectuée. En général, il est possible d'accéder par programme à la taille d'une ligne de cache CPU. Il est également possible d'accéder aux valeurs actuelles dans les registres de cache - mais c'est quelque peu dangereux de le faire. Si vous accédez aux mauvais registres à un mauvais moment, vous pourriez altérer ceux liés à un programme en cours d'exécution. Vous pouvez également modifier par inadvertance le contenu des lignes que vous essayez de lire.
Obtention de la valeur actuelle dans le cache du registre
De plus, toutes les solutions théoriques nécessitent une forme d'implémentation logicielle (assembleur). Le plus proche que j'ai trouvé concerne l'architecture ARM, qui semble permettre la manipulation du cache. En plus de cela, vous devez également connaître la taille d'une ligne de cache pour le processeur souhaité. Vous pouvez lire attentivement le contenu du cache vers un emplacement secondaire en mémoire, par incréments de taille de ligne, et le comparer aux données qui sont sur le point d'être écrites dans les registres (ou les lignes de cache L1, dans ce cas).
Lire le contenu du cache du processeur
À partir de là, vous pourriez concevoir un système logiciel qui empêche les réécritures identiques. Bien que cela soit un peu simplifié, c'est parce que la solution doit être applicable à tout processeur existant.
Une autre possibilité que j'ai trouvée liée à la cohérence du cache:
Passage pertinent d'un article de Wikipédia sur la cohérence d'accès
Le principal point qui a retenu mon attention, par rapport à ce problème, était la description de Snarfing:
En d'autres termes, il existe peut-être des mécanismes déjà en place. C'est juste qu'ils pourraient ne pas être utilisés pour l'optimisation que vous avez suggérée. Vous devez implémenter un logiciel qui effectue la comparaison lecture / écriture.
la source
if (mem != x) { mem = x; }
place demem = x;
. Il s'agit seulement parfois d'une optimisation pour les lignes de cache partagées dans un programme multithread, car l'écriture interfère avec la lecture d'autres threads.L'écriture dans le cache L1 est une opération très, très critique en temps.
Réécrire exactement les mêmes données semble être plutôt rare. Une optimisation qui accélère les choses dans ce cas particulier n'obtiendra pas beaucoup d'accélération au total.
D'un autre côté, cette optimisation nécessite une comparaison des anciennes données et des nouvelles données à chaque écriture dans la mémoire cache. Ce qui aggrave cette situation, c'est qu'elle exige que les données à écrire soient réellement disponibles au moment de l'écriture!
Ce n'est généralement pas le cas sur un processeur moderne. Les données à écrire peuvent encore être calculées par exemple. Le cache peut toujours aller de l'avant, charger la ligne de cache si nécessaire, marquer la ligne de cache comme modifiée et ainsi de suite, avant même que le calcul ne soit terminé. Toute la comptabilité peut déjà être effectuée, à l'exception de la modification réelle de la ligne de cache. Si vous souhaitez comparer le résultat nouvellement écrit et les anciennes données de ligne de cache, cela n'est pas possible.
Par exemple, si vous avez un code C a [i] = x / y; la division x / y prend un temps extraordinairement long pour fonctionner sur la plupart des CPU. Cependant, la plupart du travail nécessaire pour gérer le stockage du résultat sur un [i] a eu lieu bien avant la fin de la division; la seule chose qui manque est le déplacement de huit octets de résultat vers la ligne de cache. Une opération de vidage de la ligne de cache attendra automatiquement la fin de la division. Une opération lisant un [i] sera probablement redirigée pour obtenir le résultat directement du diviseur.
la source
Une telle optimisation ne doublera-t-elle pas le temps nécessaire au processeur pour écrire quelque chose dans le cache? Parce que chaque écriture de ligne de cache sera désormais accompagnée d'une opération de comparaison, qui n'est pas gratuite.
Donc, en fait, l'optimisation dépendra maintenant du facteur très vague: combien de fois un logiciel moyen réécrit sa mémoire cache avec les mêmes données.
la source