Je suis un cours d'architecture système et j'ai du mal à comprendre comment fonctionne un cache mappé direct.
J'ai regardé à plusieurs endroits et ils l'expliquent d'une manière différente, ce qui me rend encore plus confus.
Ce que je ne comprends pas, c'est ce qu'est le tag et l'index, et comment sont-ils sélectionnés?
L'explication de ma conférence est: "L'adresse divisée est en un index en deux parties (par exemple 15 bits) utilisé pour adresser directement (32k) les RAMs. Reste de l'adresse, la balise est stockée et comparée avec la balise entrante."
D'où vient cette balise? Il ne peut pas s'agir de l'adresse complète de l'emplacement de la mémoire dans RAM car elle rend le cache mappé direct inutile (par rapport au cache entièrement associatif).
Merci beaucoup.
D'accord. Commençons donc par comprendre comment le processeur interagit avec le cache.
Il existe trois couches de mémoire (au sens large) - cache
(généralement constituées de puces SRAM
), main memory
(Généralement composées de puces DRAM
) et storage
(généralement magnétique, comme les disques durs). Chaque fois que le processeur a besoin de données d'un emplacement particulier, il recherche d'abord dans le cache pour voir s'il s'y trouve. La mémoire cache est la plus proche du CPU en termes de hiérarchie de la mémoire, d'où son temps d'accès est le moins élevé (et le coût est le plus élevé), donc si les données que le CPU recherche peuvent y être trouvées, elles constituent un `` hit '' et est obtenu à partir de là pour être utilisé par le CPU. Si ce n'est pas le cas, les données doivent être déplacées de la mémoire principale vers le cache avant d'être accessibles par le CPU (le CPU n'interagit généralement qu'avec le cache), ce qui entraîne une pénalité de temps.
Ainsi, pour savoir si les données sont présentes ou non dans le cache, différents algorithmes sont appliqués. La première est cette méthode de cache mappé directement. Pour simplifier, supposons un système de mémoire où 10 emplacements de mémoire cache sont disponibles (numérotés de 0 à 9) et 40 emplacements de mémoire principaux disponibles (numérotés de 0 à 39). Cette image résume:
Il y a 40 emplacements de mémoire principaux disponibles, mais seulement jusqu'à 10 peuvent être hébergés dans le cache. Alors maintenant, par certains moyens, la demande entrante du CPU doit être redirigée vers un emplacement de cache. Cela pose deux problèmes:
Comment rediriger? Concrètement, comment le faire de manière prévisible qui ne changera pas avec le temps?
Si l'emplacement du cache est déjà rempli de certaines données, la demande entrante du CPU doit identifier si l'adresse à partir de laquelle il requiert les données est la même que l'adresse dont les données sont stockées dans cet emplacement.
Dans notre exemple simple, nous pouvons rediriger par une logique simple. Étant donné que nous devons mapper 40 emplacements de mémoire principaux numérotés en série de 0 à 39 à 10 emplacements de cache numérotés de 0 à 9, l'emplacement de cache pour un emplacement de mémoire n
peut être n%10
. Donc 21 correspond à 1, 37 correspond à 7, etc. Cela devient l'indice .
Mais 37, 17, 7 correspondent tous à 7. Donc, pour les différencier, vient la balise . Donc, tout comme l'index est n%10
, La balise est int(n/10)
. Donc maintenant 37, 17, 7 auront le même index 7, mais des balises différentes comme 3, 1, 0, etc. C'est-à-dire que le mappage peut être complètement spécifié par les deux données - balise et index.
Alors maintenant, si une demande vient pour l'emplacement d'adresse 29, cela se traduira par une balise de 2 et un index de 9. L'index correspond au numéro d'emplacement du cache, donc l'emplacement du cache no. 9 sera interrogé pour voir s'il contient des données, et si oui, si la balise associée est 2. Si oui, c'est un hit CPU et les données seront récupérées à partir de cet emplacement immédiatement. S'il est vide ou que la balise n'est pas 2, cela signifie qu'il contient les données correspondant à une autre adresse mémoire et non 29 (bien qu'il ait le même index, ce qui signifie qu'il contient des données provenant d'une adresse comme 9, 19, 39, etc.). C'est donc un manque de CPU, et les données de l'emplacement no. 29 dans la mémoire principale devra être chargé dans le cache à l'emplacement 29 (et la balise changée en 2, et supprimant toutes les données qui s'y trouvaient auparavant), après quoi elle sera récupérée par le CPU.
Utilisons un exemple. Un cache de 64 kilo-octets, avec des lignes de cache de 16 octets, a 4096 lignes de cache différentes.
Vous devez décomposer l'adresse en trois parties différentes.
Le nombre de bits que vous utilisez pour l'index est log_base_2 (number_of_cache_lines) [c'est vraiment le nombre d'ensembles, mais dans un cache mappé direct, il y a le même nombre de lignes et d'ensembles]
Un cache mappé direct est comme une table qui a également des lignes appelées ligne de cache et au moins 2 colonnes une pour les données et l'autre pour les balises.
Voici comment cela fonctionne: Un accès en lecture au cache prend la partie centrale de l'adresse appelée index et l'utilise comme numéro de ligne. Les données et la balise sont recherchées en même temps. Ensuite, la balise doit être comparée à la partie supérieure de l'adresse pour décider si la ligne provient de la même plage d'adresses en mémoire et est valide. Dans le même temps, la partie inférieure de l'adresse peut être utilisée pour sélectionner les données demandées dans la ligne de cache (je suppose qu'une ligne de cache peut contenir des données pour plusieurs mots).
J'ai insisté un peu sur l'accès aux données et l'accès aux balises + la comparaison se produit en même temps, car c'est la clé pour réduire la latence (objectif d'un cache). L'accès RAM au chemin de données n'a pas besoin de deux étapes.
L'avantage est qu'une lecture est fondamentalement une simple recherche de table et une comparaison.
Mais c'est un mappage direct qui signifie que pour chaque adresse de lecture, il y a exactement un endroit dans le cache où ces données pourraient être mises en cache. L'inconvénient est donc que beaucoup d'autres adresses seraient mappées au même endroit et pourraient rivaliser pour cette ligne de cache.
J'ai trouvé un bon livre à la bibliothèque qui m'a offert l'explication claire dont j'avais besoin et je vais maintenant le partager ici au cas où un autre étudiant tomberait sur ce fil tout en cherchant des caches.
Le livre est "Computer Architecture - A Quantitative Approach" 3e édition par Hennesy et Patterson, page 390.
Tout d'abord, gardez à l'esprit que la mémoire principale est divisée en blocs pour le cache. Si nous avons un cache de 64 octets et 1 Go de RAM, le RAM serait divisé en blocs de 128 Ko (1 Go de RAM/64B de cache = 128 Ko Taille de bloc).
Du livre:
Où un bloc peut-il être placé dans un cache?
<RAM Block Address> MOD <Number of Blocks in the Cache>
Supposons donc que nous ayons 32 blocs de RAM et 8 blocs de cache.
Si nous voulons stocker le bloc 12 de RAM dans le cache, RAM le bloc 12 serait stocké dans le bloc de cache 4. Pourquoi? Parce que 12/8 = 1 reste 4. Le reste est le bloc de destination.
Si un bloc peut être placé n'importe où dans le cache, le cache est entièrement associatif .
Si un bloc peut être placé n'importe où dans un ensemble restreint de places dans le cache, le cache est ensemble associatif .
Fondamentalement, un ensemble est un groupe de blocs dans le cache. Un bloc est d'abord mappé sur un ensemble, puis le bloc peut être placé n'importe où à l'intérieur de l'ensemble.
La formule est: <RAM Block Address> MOD <Number of Sets in the Cache>
Supposons donc que nous ayons 32 blocs de RAM et un cache divisé en 4 ensembles (chaque ensemble ayant deux blocs, ce qui signifie 8 blocs au total). De cette façon, l'ensemble 0 aurait les blocs 0 et 1 , l'ensemble 1 aurait les blocs 2 et 3, et ainsi de suite ...
Si nous voulons stocker RAM bloc 12 dans le cache, le bloc RAM serait stocké dans les blocs Cache 0 ou 1. Pourquoi? Parce que 12/4 = 3 reste 0. Par conséquent, l'ensemble 0 est sélectionné et le bloc peut être placé n'importe où à l'intérieur de l'ensemble 0 (c'est-à-dire les blocs 0 et 1).
Maintenant, je reviens à mon problème d'origine avec les adresses.
Comment trouve-t-on un bloc s'il est dans le cache?
Chaque trame de bloc dans le cache a une adresse. Juste pour être clair, un bloc a à la fois une adresse et des données.
L'adresse du bloc est divisée en plusieurs parties: Tag, Index et Offset.
La balise est utilisée pour trouver le bloc à l'intérieur du cache, l'index ne montre que l'ensemble dans lequel le bloc est situé (ce qui le rend assez redondant) et le décalage est utilisé pour sélectionner les données.
Par "sélectionner les données", je veux dire que dans un bloc de cache, il y aura évidemment plus d'un emplacement mémoire, le décalage est utilisé pour sélectionner entre eux.
Donc, si vous voulez imaginer un tableau, ce seraient les colonnes:
TAG | INDEX | OFFSET | DATA 1 | DATA 2 | ... | DATA N
La balise serait utilisée pour trouver le bloc, l'index montrerait dans quel ensemble se trouve le bloc, l'offset sélectionnerait l'un des champs à sa droite.
J'espère que ma compréhension de cela est correcte, si ce n'est pas le cas, faites-le moi savoir.