首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用CPUID获取Ryzen CPU中的缓存大小

使用CPUID获取Ryzen CPU中的缓存大小
EN

Stack Overflow用户
提问于 2022-08-19 14:15:14
回答 1查看 135关注 0票数 4

我想使用CPUID指令来获取每个缓存级别(L1、L2、L3)的大小。

我一直在读"AMD64体系结构程序员手册“第3卷:一般用途和系统说明。在第613页中有与L1相关的信息:

在第616页中有与L2和L3相关的信息。

我制作了一个简单的C+assembly程序来打印这些值。

代码语言:javascript
复制
const char* amd_L2_L3_associotivity_str(uint32_t code)
{
    switch(code) {
        case 0: return "Disabled";
        case 1: return "1 way (direct mapped)";
        case 2: return "2 way";
        case 4: return "4 way";
        case 6: return "8 way";
        case 8: return "16 way";
        case 10: return "32 way";
        case 11: return "48 way";
        case 12: return "64 way";
        case 13: return "96 way";
        case 14: return "128 way";
        case 15: return "Fully Associative";
        default: assert(0);
    }
    return 0;
}

void cpuid_caches_amd()
{
    uint32_t eax, ebx, ecx, edx;
    { // L1
        eax = 0x80000005; // the specific code of the cpuid instruction for L1

        __asm__ (
            "cpuid" // cpuid is the name of the instruction that queries the info we want
            : "+a" (eax)
            , "=b" (ebx)
            , "=c" (ecx)
            , "=d" (edx)
        );

        uint32_t
            dataCache_size = ecx & 0xFF,
            dataCache_associativity = (ecx >> 8) & 0xFF,
            dataCache_linesPerTag = (ecx >> 16) & 0xFF,
            dataCache_lineSize = (ecx >> 24) & 0xFF;

        uint32_t
            instrCache_size = edx & 0xFF,
            instrCache_associativity = (edx >> 8) & 0xFF,
            instrCache_linesPerTag = (edx >> 16) & 0xFF,
            instrCache_lineSize = (edx >> 24) & 0xFF;

        printf(
            "L1 Data Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %d\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            "\n"
            "L1 Instruction Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %d\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            ,
            dataCache_size,
            dataCache_associativity,
            dataCache_linesPerTag,
            dataCache_lineSize,
            instrCache_size,
            instrCache_associativity,
            instrCache_linesPerTag,
            instrCache_lineSize
        );
    }

    { // L2, L3
        eax = 0x80000006; // the specific code of the cpuid instruction for L1

        __asm__ (
            "cpuid" // cpuid is the name of the instruction that queries the info we want
            : "+a" (eax)
            , "=b" (ebx)
            , "=c" (ecx)
            , "=d" (edx)
        );

        uint32_t
            L2_size = ecx & 0xFFFF,
            L2_associativity = (ecx >> 16) & 0xF,
            L2_linesPerTag = (ecx >> 20) & 0xF,
            L2_lineSize = (ecx >> 24) & 0xFF;


        uint32_t
            L3_size = edx & 0x3FFF,
            L3_associativity = (edx >> 16) & 0xF,
            L3_linesPerTag = (edx >> 20) & 0xF,
            L3_lineSize = (edx >> 24) & 0xFF;

        printf(
            "L2 Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %s\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            "\n"
            "L3 Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %s\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            ,
            L2_size,
            amd_L2_L3_associotivity_str(L2_associativity),
            L2_linesPerTag,
            L2_lineSize,
            L3_size * 512,
            amd_L2_L3_associotivity_str(L3_associativity),
            L3_linesPerTag,
            L3_lineSize
        );
    }
}

int main()
{
    cpuid_caches_amd();
}

这是我的Ryzen 3700X程序的输出:

代码语言:javascript
复制
L1 Data Cache:
        Size: 64 KB
        Associativity: 1
        Lines per Tag: 8
        Line Size: 32 B

L1 Instruction Cache:
        Size: 64 KB
        Associativity: 1
        Lines per Tag: 8
        Line Size: 32 B
L2 Cache:
        Size: 24896 KB
        Associativity: Disabled
        Lines per Tag: 0
        Line Size: 2 B

L3 Cache:
        Size: 2260992 KB
        Associativity: Disabled
        Lines per Tag: 0
        Line Size: 1 B

根据这一点,我有2GB的L3缓存,这是不可能的。根据官方规范,它应该有L1: 512 4MB,L2: 4MB,L3: 32 4MB。

另一件让我困惑的是,L1DcSize只有8位宽。这只允许表示高达255 to的L1大小,尽管我的L1应该有512 to的L1!

我的密码怎么了?如何获得实际的缓存大小?

编辑:

谢谢大家的回复。正如人们所指出的,我的位移位是颠倒的。仍然存在关于缓存L1的问题。这就是代码现在的样子:

代码语言:javascript
复制
void cpuid_caches_amd()
{
    uint32_t eax, ebx, ecx, edx;
    { // L1
        eax = 0x80000005; // the specific code of the cpuid instruction for L1

        __asm__ (
            "cpuid" // cpuid is the name of the instruction that queries the info we want
            : "+a" (eax)
            , "=b" (ebx)
            , "=c" (ecx)
            , "=d" (edx)
        );

        uint32_t
            dataCache_size = (ecx >> 24) & 0xFF,
            dataCache_associativity = (ecx >> 16) & 0xFF,
            dataCache_linesPerTag = (ecx >> 8) & 0xFF,
            dataCache_lineSize = ecx & 0xFF;

        uint32_t
            instrCache_size = (edx >> 24) & 0xFF,
            instrCache_associativity = (edx >> 16) & 0xFF,
            instrCache_linesPerTag = (edx >> 8) & 0xFF,
            instrCache_lineSize = edx & 0xFF;

        printf(
            "L1 Data Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %d\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            "\n"
            "L1 Instruction Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %d\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            ,
            dataCache_size,
            dataCache_associativity,
            dataCache_linesPerTag,
            dataCache_lineSize,
            instrCache_size,
            instrCache_associativity,
            instrCache_linesPerTag,
            instrCache_lineSize
        );
    }

    { // L2
        eax = 0x80000006; // the specific code of the cpuid instruction for L1

        __asm__ (
            "cpuid" // cpuid is the name of the instruction that queries the info we want
            : "+a" (eax)
            , "=b" (ebx)
            , "=c" (ecx)
            , "=d" (edx)
        );

        uint32_t
            L2_size = (ecx >> 16) & 0xFFFF,
            L2_associativity = (ecx >> 12) & 0xF,
            L2_linesPerTag = (ecx >> 8) & 0xF,
            L2_lineSize = ecx & 0xFF;


        uint32_t
            L3_size = (edx >> 18) & 0x3FFF,
            L3_associativity = (edx >> 12) & 0xF,
            L3_linesPerTag = (edx >> 8) & 0xF,
            L3_lineSize = (edx >> 0) & 0xFF;

        printf(
            "L2 Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %s\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            "\n"
            "L3 Cache:\n"
            "\tSize: %d KB\n"
            "\tAssociativity: %s\n"
            "\tLines per Tag: %d\n"
            "\tLine Size: %d B\n"
            ,
            L2_size,
            amd_L2_L3_associotivity_str(L2_associativity),
            L2_linesPerTag,
            L2_lineSize,
            L3_size * 512,
            amd_L2_L3_associotivity_str(L3_associativity),
            L3_linesPerTag,
            L3_lineSize
        );
    }
}

新的产出:

代码语言:javascript
复制
L1 Data Cache:
        Size: 32 KB
        Associativity: 8
        Lines per Tag: 1
        Line Size: 64 B

L1 Instruction Cache:
        Size: 32 KB
        Associativity: 8
        Lines per Tag: 1
        Line Size: 64 B
L2 Cache:
        Size: 512 KB
        Associativity: 8 way
        Lines per Tag: 1
        Line Size: 64 B

L3 Cache:
        Size: 32768 KB
        Associativity: Value for all fields should be determined from Fn8000_001D
        Lines per Tag: 1
        Line Size: 64 B
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-19 14:52:50

似乎你弄错了结果的位布局。大小结果在上位,但您正在提取下位。其他字段的顺序也类似地相反。

例如,L3Size31:18中,但是您使用没有移位的0x3FFF掩码,它使用13:0

而不是:

代码语言:javascript
复制
L3_size = edx & 0x3FFF,
L3_associativity = (edx >> 16) & 0xF,
L3_linesPerTag = (edx >> 20) & 0xF,
L3_lineSize = (edx >> 24) & 0xFF;

写入:

代码语言:javascript
复制
L3_size = (edx >> 18) & 0x3FFF,
L3_associativity = (edx >> 12) & 0xF,
L3_linesPerTag = (edx >> 8) & 0xF,
L3_lineSize = (edx >> 0) & 0xFF;

对其他寄存器也做同样的事情。字段的最低位数是您必须移动的数量。

至于关于L1大小的第二个问题,规格表有芯片总数。然而,从CPUID的角度来看,重要的是核心的缓存。如果将32 kiB of L1i和32 kiB of L1d乘以处理器中的8核,就会得到预期的512 kiB。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73418161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档