2016-02-14 1 views
0

J'ai écrit le programme suivant en utilisant à la fois gcc __get_cpuid et inline assembly pour obtenir les informations de cache de mon ordinateur portable, mais ne parviennent pas à les identifier sur la table (Encodage de cache et descripteurs TLB) J'ai trouvé en ligne.Obtenir des informations de cache en utilisant C/C++ avec inline assembly/intrinsics dans osx

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <string.h> 
#include <time.h> 
#include <stdint.h> 
#include <math.h> 
#include <cpuid.h> 

static inline void cpuid(uint32_t *eax, uint32_t *ebx, 
         uint32_t *ecx, uint32_t *edx); 

int main() { 
    uint32_t a, b, c, d; 
    uint32_t eax, ebx, ecx, edx; 
    eax = 2; /* processor info and feature bits */ 
    uint32_t command = 2; 
    cpuid(&eax, &ebx, &ecx, &edx); 
    __get_cpuid(command, &a, &b, &c, &d); 

    printf("eax: %08x\n", eax); 
    printf("ebx: %08x\n", ebx); 
    printf("ecx: %08x\n", ecx); 
    printf("edx: %08x\n", edx); 

    printf("a: %08x\n", a); 
    printf("b: %08x\n", b); 
    printf("c: %08x\n", c); 
    printf("d: %08x\n", d); 
} 

static inline void cpuid(uint32_t *eax, uint32_t *ebx, 
         uint32_t *ecx, uint32_t *edx) 
{ 
     /* ecx is often an input as well as an output. */ 
     asm ("cpuid" 
      : "=a" (*eax), 
       "=b" (*ebx), 
       "=c" (*ecx), 
       "=d" (*edx) 
      : "0" (*eax)); 
} 

ma sortie:

eax: 76036301 
ebx: 00f0b5ff 
ecx: 00000000 
edx: 00c10000 
a: 76036301 
b: 00f0b5ff 
c: 00000000 
d: 00c10000 

J'ai trouvé ce tableau de here enter image description here

J'utilise sysctl hw.cachesize et trouve que

L1 cache: 32KB 
L2 cache: 256KB 
L3 cache: 6MB 

Mon environnement:

system: os x 10.10.1 
compiler: clang-602.0.53 
CPU: I7-4850 HQ 2.3HZ 

Qu'est-ce qui ne va pas avec mon programme? Mon programme devrait fonctionner puisque les deux méthodes donnent le même résultat ... Je suis confus à ce sujet. Je vous remercie!

EDIT: J'essaie ce que Mats' a suggéré et obtenir ce qui suit comme ma sortie:

gcc intrinsic 
a: 76036301 
b: 00f0b5ff 
c: 00000000 
d: 00c10000 
eax: 2 
eax: 76036301 
ebx: 00f0b5ff 
ecx: 00000000 
edx: 00c10000 
eax: 4, ecx: 0 
eax: 1c004121 
ebx: 01c0003f 
ecx: 0000003f 
edx: 00000000 
eax: 4, ecx: 1 
eax: 1c004122 
ebx: 01c0003f 
ecx: 0000003f 
edx: 00000000 
eax: 4, ecx: 2 
eax: 1c004143 
ebx: 01c0003f 
ecx: 000001ff 
edx: 00000000 
eax: 4, ecx: 3 
eax: 1c03c163 
ebx: 02c0003f 
ecx: 00001fff 
edx: 00000006 
eax: 4, ecx: 4 
eax: 1c03c183 
ebx: 03c0f03f 
ecx: 00001fff 
edx: 00000004 
eax: 4, ecx: 5 
eax: 00000000 
ebx: 00000000 
ecx: 00000000 
edx: 00000000 

Je regarde la table à here
cpuid_cache_descriptor_t statique intel_cpuid_leaf2_descriptor_table [] = {

// ------------------------------------------------------- 
// value type level  ways size entries 
// ------------------------------------------------------- 
    { 0x00, _NULL_, NA,  NA, NA, NA }, 
    { 0x01, TLB, INST,  4, SMALL, 32 }, 
    { 0x02, TLB, INST,  FULLY, LARGE, 2 }, 
    { 0x03, TLB, DATA,  4, SMALL, 64 }, 
    { 0x04, TLB, DATA,  4, LARGE, 8 }, 
    { 0x05, TLB, DATA1,  4, LARGE, 32 }, 
    { 0x06, CACHE, L1_INST, 4, 8*K, 32 }, 
    { 0x08, CACHE, L1_INST, 4, 16*K, 32 }, 
    { 0x09, CACHE, L1_INST, 4, 32*K, 64 }, 
    { 0x0A, CACHE, L1_DATA, 2, 8*K, 32 }, 
    { 0x0B, TLB, INST,  4, LARGE, 4 }, 
    { 0x0C, CACHE, L1_DATA, 4, 16*K, 32 }, 
    { 0x0D, CACHE, L1_DATA, 4, 16*K, 64 }, 
    { 0x0E, CACHE, L1_DATA, 6, 24*K, 64 }, 
    { 0x21, CACHE, L2,  8, 256*K, 64 }, 
    { 0x22, CACHE, L3_2LINESECTOR, 4, 512*K, 64 }, 
    { 0x23, CACHE, L3_2LINESECTOR, 8, 1*M, 64 }, 
    { 0x25, CACHE, L3_2LINESECTOR, 8, 2*M, 64 }, 
    { 0x29, CACHE, L3_2LINESECTOR, 8, 4*M, 64 }, 
    { 0x2C, CACHE, L1_DATA, 8, 32*K, 64 }, 
    { 0x30, CACHE, L1_INST, 8, 32*K, 64 }, 
    { 0x40, CACHE, L2,  NA, 0, NA }, 
    { 0x41, CACHE, L2,  4, 128*K, 32 }, 
    { 0x42, CACHE, L2,  4, 256*K, 32 }, 
    { 0x43, CACHE, L2,  4, 512*K, 32 }, 
    { 0x44, CACHE, L2,  4, 1*M, 32 }, 
    { 0x45, CACHE, L2,  4, 2*M, 32 }, 
    { 0x46, CACHE, L3,  4, 4*M, 64 }, 
    { 0x47, CACHE, L3,  8, 8*M, 64 }, 
    { 0x48, CACHE, L2,  12,  3*M, 64 }, 
    { 0x49, CACHE, L2,  16, 4*M, 64 }, 
    { 0x4A, CACHE, L3,  12,  6*M, 64 }, 
    { 0x4B, CACHE, L3,  16, 8*M, 64 }, 
    { 0x4C, CACHE, L3,  12,  12*M, 64 }, 
    { 0x4D, CACHE, L3,  16, 16*M, 64 }, 
    { 0x4E, CACHE, L2,  24, 6*M, 64 }, 
    { 0x4F, TLB, INST,  NA, SMALL, 32 }, 
    { 0x50, TLB, INST,  NA, BOTH, 64 }, 
    { 0x51, TLB, INST,  NA, BOTH, 128 }, 
    { 0x52, TLB, INST,  NA, BOTH, 256 }, 
    { 0x55, TLB, INST,  FULLY, BOTH, 7 }, 
    { 0x56, TLB, DATA0,  4, LARGE, 16 }, 
    { 0x57, TLB, DATA0,  4, SMALL, 16 }, 
    { 0x59, TLB, DATA0,  FULLY, SMALL, 16 }, 
    { 0x5A, TLB, DATA0,  4, LARGE, 32 }, 
    { 0x5B, TLB, DATA,  NA, BOTH, 64 }, 
    { 0x5C, TLB, DATA,  NA, BOTH, 128 }, 
    { 0x5D, TLB, DATA,  NA, BOTH, 256 }, 
    { 0x60, CACHE, L1,  16*K, 8, 64 }, 
    { 0x61, CACHE, L1,  4, 8*K, 64 }, 
    { 0x62, CACHE, L1,  4, 16*K, 64 }, 
    { 0x63, CACHE, L1,  4, 32*K, 64 }, 
    { 0x70, CACHE, TRACE,  8, 12*K, NA }, 
    { 0x71, CACHE, TRACE,  8, 16*K, NA }, 
    { 0x72, CACHE, TRACE,  8, 32*K, NA }, 
    { 0x78, CACHE, L2,  4, 1*M, 64 }, 
    { 0x79, CACHE, L2_2LINESECTOR, 8, 128*K, 64 }, 
    { 0x7A, CACHE, L2_2LINESECTOR, 8, 256*K, 64 }, 
    { 0x7B, CACHE, L2_2LINESECTOR, 8, 512*K, 64 }, 
    { 0x7C, CACHE, L2_2LINESECTOR, 8, 1*M, 64 }, 
    { 0x7D, CACHE, L2,  8, 2*M, 64 }, 
    { 0x7F, CACHE, L2,  2, 512*K, 64 }, 
    { 0x80, CACHE, L2,  8, 512*K, 64 }, 
    { 0x82, CACHE, L2,  8, 256*K, 32 }, 
    { 0x83, CACHE, L2,  8, 512*K, 32 }, 
    { 0x84, CACHE, L2,  8, 1*M, 32 }, 
    { 0x85, CACHE, L2,  8, 2*M, 32 }, 
    { 0x86, CACHE, L2,  4, 512*K, 64 }, 
    { 0x87, CACHE, L2,  8, 1*M, 64 }, 
    { 0xB0, TLB, INST,  4, SMALL, 128 }, 
    { 0xB1, TLB, INST,  4, LARGE, 8 }, 
    { 0xB2, TLB, INST,  4, SMALL, 64 }, 
    { 0xB3, TLB, DATA,  4, SMALL, 128 }, 
    { 0xB4, TLB, DATA1,  4, SMALL, 256 }, 
    { 0xBA, TLB, DATA1,  4, BOTH, 64 }, 
    { 0xCA, STLB, DATA1,  4, BOTH, 512 }, 
    { 0xD0, CACHE, L3,  4, 512*K, 64 }, 
    { 0xD1, CACHE, L3,  4, 1*M, 64 }, 
    { 0xD2, CACHE, L3,  4, 2*M, 64 }, 
    { 0xD3, CACHE, L3,  4, 4*M, 64 }, 
    { 0xD4, CACHE, L3,  4, 8*M, 64 }, 
    { 0xD6, CACHE, L3,  8, 1*M, 64 }, 
    { 0xD7, CACHE, L3,  8, 2*M, 64 }, 
    { 0xD8, CACHE, L3,  8, 4*M, 64 }, 
    { 0xD9, CACHE, L3,  8, 8*M, 64 }, 
    { 0xDA, CACHE, L3,  8, 12*M, 64 }, 
    { 0xDC, CACHE, L3,  12,  1536*K, 64 }, 
    { 0xDD, CACHE, L3,  12,  3*M, 64 }, 
    { 0xDE, CACHE, L3,  12,  6*M, 64 }, 
    { 0xDF, CACHE, L3,  12, 12*M, 64 }, 
    { 0xE0, CACHE, L3,  12, 18*M, 64 }, 
    { 0xE2, CACHE, L3,  16, 2*M, 64 }, 
    { 0xE3, CACHE, L3,  16, 4*M, 64 }, 
    { 0xE4, CACHE, L3,  16, 8*M, 64 }, 
    { 0xE5, CACHE, L3,  16, 16*M, 64 }, 
    { 0xE6, CACHE, L3,  16, 24*M, 64 }, 
    { 0xF0, PREFETCH, NA,  NA, 64, NA }, 
    { 0xF1, PREFETCH, NA,  NA, 128, NA } 
}; 

Le problème en ce moment est que je ne peux toujours pas obtenir la taille correcte de mon cache L3 (quand ecx = 1, j'obtiens 22 soit 512K, mais la valeur correcte est 6MB). En outre, il semble y avoir quelques conflits en termes de taille de mon cache L2 (43 (quand ecx = 2) et 21 (quand ecx = 0))

Répondre

1

Donc, vos données semblent être raisonnablement correctes, juste que vous utilisez une ancienne référence. Malheureusement, le site Web d'Intel est soit cassé actuellement ou il n'aime pas Firefox et/ou Linux.

76 moyens oligo-cache avec 64K ops.

03 signifie DATA TLB à 4 voies avec 64 entrées. 63 est 32 Ko cache L1 - la source here montre cette valeur, qui ne figure pas dans vos documents.

01 signifie TLB d'instruction à 4 voies avec 32 entrées.

00f0b5ff donne

00 "rien"

prefetch f0, 64 entrées.

0b TLB 4 voies pour les grandes pages, 4 entrées.

b5 n'est pas documenté même sur ce lien. [Pour les petites données TLB]

Pour obtenir les tailles de cache L2 et L3, vous devez utiliser CPUID avec EAX = 4 et définir ECX sur 0, 1, 2, ... pour chaque niveau de cache.Le code lié le montre, et les docs d'Intel ont des détails sur les bits qui veulent dire quoi.

+0

Merci! Mais pourquoi ne puis-je pas obtenir des informations sur le cache L2 et le cache L3 dans mon programme? En outre, y a-t-il des moyens (plutôt que de trouver directement ces informations en utilisant le terminal) pour obtenir l'information d'eux en utilisant un programme similaire à mon actuel? – PLNewbie

+0

@PLNewbie Voir éditer. –

+0

Merci! Cependant, j'ai encore quelques problèmes à trouver leurs valeurs après avoir réglé eax = 4 et réglé ecx = 0,1,2,3,4,5 dans chaque cas. S'il vous plaît voir mon edit. – PLNewbie

1

Intel's Instruction Set Reference a toutes les informations nécessaires dont vous avez besoin (à la page 263), et est réellement à jour contrairement à toutes les autres sources que j'ai trouvées. Le meilleur moyen d'obtenir les informations de cache est probablement mentionné dans cette référence.

Lorsque eax = 4 et ECX est le niveau de cache,

Ways = EBX[31:22] 

Partitions = EBX[21:12] 

LineSize = EBX[11:0] 

Sets = ECX 

Total Size = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) 

Alors, quand CUPID est appelée avec EAX = 4 et ECX = 3, vous pouvez obtenir votre taille du cache L3 en faisant le calcul ci-dessus. En utilisant les données affichées de l'OP:

ebx: 02c0003f 
ecx: 00001fff 

Ways = 63 
Partitions = 0 
LineSize = 11 
Sets = 8191 

cache L3 total size = 6291456

Ce qui est ce qui était attendu.

+0

Merci! Une façon étrange d'obtenir la taille du cache ... 'Ce cache en octets = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) = (EBX [31:22] + 1) * (EBX [21:12] + 1) * (EBX [11: 0] + 1) * (ECX + 1) ' – PLNewbie