J'essaie de profiler et d'optimiser les algorithmes et je voudrais comprendre l'impact spécifique des caches sur différents processeurs. Pour les processeurs Intel x86 récents (par exemple Q9300), il est très difficile de trouver des informations détaillées sur la structure du cache. En particulier, la plupart des sites Web (y compris Intel.com ) qui contiennent des spécifications de post-processeur ne contiennent aucune référence au cache L1. Est-ce parce que le cache L1 n'existe pas ou ces informations sont-elles considérées comme non importantes pour une raison quelconque? Y a-t-il des articles ou des discussions sur l'élimination du cache L1?
[modifier] Après avoir exécuté divers tests et programmes de diagnostic (principalement ceux discutés dans les réponses ci-dessous), j'ai conclu que mon Q9300 semble avoir un cache de données 32K L1. Je n'ai toujours pas trouvé d'explication claire pour expliquer pourquoi ces informations sont si difficiles à trouver. Ma théorie de travail actuelle est que les détails de la mise en cache L1 sont désormais traités comme des secrets commerciaux par Intel.
Il est presque impossible de trouver des spécifications sur les caches Intel. Lorsque j'enseignais un cours sur les caches l'année dernière, j'ai demandé à des amis d'Intel (dans le groupe de compilation) et ils ne pouvaient pas trouver de spécifications.
Mais attendez !!! Jed , bénissez son âme, nous dit que sur les systèmes Linux, vous pouvez extraire beaucoup d'informations du noyau:
grep . /sys/devices/system/cpu/cpu0/cache/index*/*
Cela vous donnera l'associativité, la taille définie et un tas d'autres informations (mais pas la latence). Par exemple, j'ai appris que bien qu'AMD annonce son cache L1 de 128 Ko, ma machine AMD a un cache I et D divisé de 64 Ko chacun.
Deux suggestions désormais obsolètes grâce à Jed:
AMD publie beaucoup plus d'informations sur ses caches, vous pouvez donc au moins obtenir des informations sur un cache moderne. Par exemple, les caches AMD L1 de l'an dernier ont fourni deux mots par cycle (pic).
L'outil open source valgrind
contient toutes sortes de modèles de cache, et il est précieux pour le profilage et la compréhension du comportement du cache. Il est livré avec un outil de visualisation très agréable kcachegrind
qui fait partie du SDK KDE.
Par exemple: au troisième trimestre 2008, AMD K8 / K1 Les processeurs utilisent des lignes de cache de 64 octets, avec 64 Ko chacun de cache partagé L1I/L1D. L1D est associatif à 2 voies et exclusif avec L2, avec une latence de 3 cycles. Le cache L2 est associatif à 16 voies et la latence est d'environ 12 cycles.
CPU de la famille AMD Bulldozer utiliser un L1 divisé avec un L1D associatif à 4 voies de 16 Ko par cluster (2 par cœur).
Les processeurs Intel ont gardé L1 le même pendant longtemps (du Pentium M à Haswell à Skylake, et probablement de nombreuses générations après cela): Split 32kB chacun des caches I et D, L1D étant associatif à 8 voies . Lignes de cache de 64 octets, correspondant à la taille de transfert en rafale de la DRAM DDR. La latence d'utilisation de la charge est d'environ 4 cycles.
Voir également le wiki de la balise x86 pour des liens vers plus de performances et des données microarchitecturales.
Ce manuel Intel: Intel® 64 et IA-32 Architectures Optimization Reference Manual contient une discussion décente sur les considérations de cache.
Page 46, Section 2.2.5.1 ( Manuel de référence de l'optimisation des architectures Intel® 64 et IA-32
Même MicroSlop se rend compte du besoin d'outils supplémentaires pour surveiller l'utilisation et les performances du cache, et possède un exemple GetLogicalProcessorInformation () (... tout en ouvrant de nouvelles pistes pour créer des noms de fonctions ridiculement longs dans le processus ) Je pense que je vais coder.
MISE À JOUR I: Hazwell augmente les performances de chargement du cache 2X, à partir de Inside the Tock; Haswell's Architecture
S'il y avait le moindre doute quant à l'importance de faire le meilleur usage possible du cache, cette présentation par Cliff Click, anciennement d'Azul, devrait dissiper tout doute. Selon ses mots, "la mémoire est le nouveau disque!".
MISE À JOUR II: Les spécifications de performances du cache de SkyLake considérablement améliorées.
J'ai fait un peu plus d'enquête. Il y a un groupe à l'ETH Zurich qui a construit un outil d'évaluation des performances de la mémoire qui pourrait être en mesure d'obtenir des informations sur la taille au moins (et peut-être aussi l'associativité) des caches L1 et L2. Le programme fonctionne en essayant différents modèles de lecture expérimentalement et en mesurant le débit résultant. Une version simplifiée a été utilisée pour le manuel populaire de Bryant et O'Hallaron .
Vous regardez les spécifications du consommateur, pas les spécifications du développeur. Voici la documentation que vous voulez. Les tailles de cache varient selon les sous-modèles de famille de processeurs, donc elles ne figurent généralement pas dans les manuels de développement IA-32, mais vous pouvez facilement les rechercher sur NewEgg et autres.
Edit: Plus spécifiquement: Chapitre 10 du Volume 3A (Guide de programmation des systèmes), Chapitre 7 du Manuel de référence de l'optimisation, et potentiellement quelque chose dans la page TLB- mise en cache manuelle, bien que je suppose que l'on est plus éloigné de la L1 que vous ne vous en souciez.
Des caches L1 existent sur ces plateformes. Cela restera presque certainement vrai jusqu'à ce que la vitesse de la mémoire et du bus frontal dépasse la vitesse du CPU, ce qui est très loin.
Sous Windows, vous pouvez utiliser GetLogicalProcessorInformation pour obtenir un certain niveau d'informations sur le cache (taille, taille de ligne, associativité, etc.) La version Ex sur Win7 fournira encore plus de données, comme les cœurs qui partagent quel cache . CpuZ donne également ces informations.
Localité de référence a un impact majeur sur les performances de certains algorithmes; La taille et la vitesse des caches L1, L2 (et sur les nouveaux CPU L3) jouent évidemment un rôle important à cet égard. La multiplication matricielle est l'un de ces algorithmes.
Intel Manual Vol. 2 spécifie la formule suivante pour calculer la taille du cache:
Cette taille de cache en octets
= (Voies + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1)
= (EBX [31:22] + 1) * (EBX [21:12] + 1) * (EBX [11: 0] + 1) * (ECX + 1)
Où Ways
, Partitions
, Line_Size
et Sets
sont interrogés à l'aide de cpuid
avec eax
défini sur 0x04
.
Fournir la déclaration du fichier d'en-tête
x86_cache_size.h
:
unsigned int get_cache_line_size(unsigned int cache_level);
L'implémentation se présente comme suit:
;1st argument - the cache level
get_cache_line_size:
Push rbx
;set line number argument to be used with CPUID instruction
mov ecx, edi
;set cpuid initial value
mov eax, 0x04
cpuid
;cache line size
mov eax, ebx
and eax, 0x7ff
inc eax
;partitions
shr ebx, 12
mov edx, ebx
and edx, 0x1ff
inc edx
mul edx
;ways of associativity
shr ebx, 10
mov edx, ebx
and edx, 0x1ff
inc edx
mul edx
;number of sets
inc ecx
mul ecx
pop rbx
ret
Ce qui sur ma machine fonctionne comme suit:
#include "x86_cache_size.h"
int main(void){
unsigned int L1_cache_size = get_cache_line_size(1);
unsigned int L2_cache_size = get_cache_line_size(2);
unsigned int L3_cache_size = get_cache_line_size(3);
//L1 size = 32768, L2 size = 262144, L3 size = 8388608
printf("L1 size = %u, L2 size = %u, L3 size = %u\n", L1_cache_size, L2_cache_size, L3_cache_size);
}