Y a-t-il des CPU qui effectuent cette optimisation possible d'écriture du cache L1?

9

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?

poncho
la source
11
On dit qu'il y a deux problèmes vraiment difficiles en informatique: l'invalidation du cache, le bien nommer les choses et les erreurs ponctuelles. Ceci est un exemple de la raison pour laquelle le premier d'entre eux est délicat.
Mason Wheeler
@poncho vous dites que "quelqu'un qui est capable d'écouter le comportement du cache ne devrait pas pouvoir déduire ce que je fais." Maintenant, si certains processeurs ont implémenté cette fonctionnalité de "réécriture intelligente" qui n'invalide pas le cache à moins que les données ne soient vraiment mises à jour, alors en s'éloignant d'un niveau plus loin du processeur dans la hiérarchie de la mémoire, on serait en mesure d'observer le trafic / le timing différences entre les écritures réelles et les écritures factices. Est-ce cela qui vous préoccupe?
TheCodeArtist
@poncho Votre vraie question semble également concerner l'implémentation d'un meilleur mode privilégié / sécurisé qui ne divulgue pas les informations d'utilisation. Vous devriez peut-être demander cela? ...
TheCodeArtist
1
@TheCodeArtist: eh bien, il y a eu des attaques cryptographiques de canaux secondaires publiées où une routine de cryptage pourrait être attaquée par un autre programme fonctionnant sur un noyau différent du même CPU, en ayant le programme d'attaque surveiller le cache partagé. Je crois qu'un tel programme pourrait potentiellement détecter si les lignes de cache L1 ont été vidées, et pourrait donc déduire des informations sur le programme qui m'intéresse, si le CPU fait l'optimisation en cours de discussion. Je ne parle pas d'un «mode sécurisé», car je ne suppose pas la possibilité de modifier le CPU ou le système d'exploitation.
poncho
4
Même si c'est vrai aujourd'hui, ce n'est pas garanti pour demain.
pjc50

Réponses:

4

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:

Il s'agit d'un mécanisme dans lequel un contrôleur de cache surveille à la fois l'adresse et les données pour tenter de mettre à jour sa propre copie d'un emplacement de mémoire lorsqu'un second maître modifie un emplacement dans la mémoire principale. Lorsqu'une opération d'écriture est observée vers un emplacement dont une antémémoire a une copie, le contrôleur d'antémémoire met à jour sa propre copie de l'emplacement de mémoire snarfed avec les nouvelles données.

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.

Communauté
la source
Il est également possible d'accéder aux valeurs actuelles dans les registres de cache - mais c'est quelque peu dangereux de le faire. Huh, cela n'a aucun sens. Vous voulez dire les registres CPU? Le code asm généré par le compilateur ou écrit à la main utilise des registres pour contenir les valeurs sur lesquelles il fonctionne ...
Peter Cordes
Si vous essayez d'implémenter cela dans un logiciel, il vous suffirait que le compilateur génère du code qui le fait à la if (mem != x) { mem = x; }place de mem = 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.
Peter Cordes
1
"snarfing" n'a rien à voir avec cela. C'est juste un espionnage passif. Les caches CPU utilisent MESI pour avoir des caches d'écriture cohérente.
Peter Cordes,
@PeterCordes Si vous trouvez ma réponse désagréable, je m'en excuse. Cependant, il semble que vous ayez plus de connaissances que moi sur la question. Alors, pourquoi ne pas répondre vous-même à la question? Ma réponse était évidemment inadéquate par rapport à vos normes ...
Je l'ai fait, sur un quasi-double de cette question sur SO .
Peter Cordes
3

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.

gnasher729
la source
Un cache utilisant MESI pour la cohérence pourrait toujours faire le RFO, mais si les données se comparaient de la même manière une fois qu'elles étaient prêtes, laissez la ligne en état exclusif au lieu de modifiée. La vraie raison pour laquelle cela n'est pas fait dans le matériel est que cela coûte des lectures de cache supplémentaires lorsque les données sont validées dans le cache, et nécessiterait une sorte de cycles atomiques de lecture / comparaison / écriture (avec réglage facultatif du bit sale) qui le fait aspirer pendant un mise en œuvre en pipeline.
Peter Cordes
1

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

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.

Vladislav Rastrusny
la source
Cette comparaison serait implémentée dans la logique CPU. Cela ne nécessiterait pas une opération CPU supplémentaire, mais la durée du signal pourrait augmenter, ce qui pourrait être un problème ou non.
ziggystar
@ziggystar Eh bien, je ne suis pas un maître du matériel, mais je me suis habitué à l'idée que tout a un coût. Il en va de même pour comparer l'opération avec la ligne de cache. Ça pourrait être rapide. Mais cela coûte toujours. Et je pense que les développeurs ont décidé de ne pas le payer. Peut-être même après avoir réfléchi et mesuré.
Vladislav Rastrusny
1
Mais vous parlez de temps, où le coût pourrait n'être qu'une augmentation du nombre de portes.
ziggystar
1
@ziggystar: Ce n'est pas seulement plus de portes. Lorsque des données sont envoyées au cache, normalement le processus d'envoi des données peut marquer la ligne de cache comme modifiée. Avec cette "optimisation", les anciennes données et les nouvelles données doivent toutes les deux passer par ces portes, ce qui entraînera un certain retard, et alors seulement le cache pourra être invalidé. Vous devez regrouper tout cela en un seul cycle de processeur, sinon l'écriture sur une ligne de cache prend soudainement deux cycles. Et maintenant, pour compliquer les choses, réfléchissez à ce qui se passe lorsque j'écris huit mots consécutifs sur une ligne de cache.
gnasher729
1
Et chacune de ces écritures retarde la décision de modifier la ligne de cache. Ainsi, lorsque la deuxième écriture se produit, la ligne de cache ne sait pas si elle est modifiée ou pas (encore). Cela va être amusant.
gnasher729