1

我正在编写 cpuid 程序。我需要帮助来获取每种类型的缓存的数量。不是它的大小,而是数量。例如,我需要获取如下信息:

L1 数据缓存 = 2 x 64KB。

CPUID 会给我每种缓存的大小,但不是它的数量。在 MSDN 上,我发现 GetLogicalProcessorsInformationEx proc 可能有助于获得该号码。但我不确定我是否理解正确。我猜,CACHE_RELATIONSHIP 结构的那个成员,GROUP_AFFINITY 将与数量有关。有人可以给我一些提示如何获取该号码或告诉我是否可以找到此类信息。

4

1 回答 1

2

我以前做过一个更简单的版本。我没有使用过缓存关联或计数,但我查询过缓存大小和缓存行大小。我怀疑可以通过在我所做的事情中交换一些论点来获得信息。

这是我为获得常见 PC 平台上最大 CPU 缓存大小所做的工作。我已经在 windows(msvc, mingw)、Linux(gcc, clang) 和 Mac OS X (gcc) 上运行了它,它编译和运行时没有警告,除了来自 msvc 的一些看似虚假的警告。此代码来自https://github.com/BlackToppStudios/DAGFrameScheduler/blob/master/src/systemcalls.cpp,但您可以随意将此功能用于您自己的目的(我是作者/所有者,我可以重新许可它GPL)。

它检查是否存在 L4 缓存,如果存在则返回它。然后它检查是否存在 L3 缓存,如果存在则返回它,然后同样返回 L2 和 L1。

此代码要求 _MEZZ_THREAD_WIN32_ 仅在 Windows 上定义,_MEZZ_THREAD_APPLE_ 仅在 Mac OS X 上定义,否则假定 Linux/BSD。在撰写本文前 6 周,MinGW 有这样做的问题,可能可以使用 msvc/windows sdk 标头和 c 库,但我没有尝试过,它似乎很乱。

#ifdef _MEZZ_THREAD_WIN32_
    #include <windows.h>
#else
    #ifdef _MEZZ_THREAD_APPLE_
        #include <sys/sysctl.h>
    #endif
    #include <sys/time.h>
    #include <unistd.h>
#endif

typedef unsigned int Whole

Whole GetCacheSize()
{
    #ifdef _MEZZ_THREAD_WIN32_
        #ifdef _MSC_VER
            size_t Size = 0;
            DWORD buffer_size = 0;
            DWORD i = 0;
            SYSTEM_LOGICAL_PROCESSOR_INFORMATION * buffer = 0;

            GetLogicalProcessorInformation(0, &buffer_size);
            buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)malloc(buffer_size);
            GetLogicalProcessorInformation(&buffer[0], &buffer_size);

            for (i = 0; i != buffer_size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
                if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) {
                    Size = buffer[i].Cache.Size;
                    break;
                }
            }

            free(buffer);
            return Size;
        #else
            //mingw can't do this, see bug http://sourceforge.net/p/mingw/bugs/1626/
            // assume 32k
            return 32768;
        #endif
    #else
        #ifdef _MEZZ_THREAD_APPLE_
            Whole CacheSize;
            Whole CSSize = sizeof(CacheSize);
            if(0==sysctlbyname("hw.l4icachesize", &CacheSize, &CSSize, NULL, 0))
            {
                return CacheSize;
            }else{
                if(0==sysctlbyname("hw.l3icachesize", &CacheSize, &CSSize, NULL, 0))
                {
                    return CacheSize;
                }else{
                    if(0==sysctlbyname("hw.l2icachesize", &CacheSize, &CSSize, NULL, 0))
                    {
                        return CacheSize;
                    }else{
                        if(0==sysctlbyname("hw.l1icachesize", &CacheSize, &CSSize, NULL, 0))
                        {
                            return CacheSize;
                        }else{
                            return 0;
                        }
                    }
                }
            }
        #else
            Whole CSSize = sysconf(_SC_LEVEL4_CACHE_SIZE);
            if(!CSSize)
            {
                CSSize = sysconf(_SC_LEVEL3_CACHE_SIZE);
                if(!CSSize)
                {
                    CSSize = sysconf(_SC_LEVEL2_CACHE_SIZE);
                    if(!CSSize)
                        { CSSize = sysconf(_SC_LEVEL1_DCACHE_SIZE); }
                }
            }
            return CSSize;
       #endif
    #endif
}
于 2013-08-20T20:14:22.450 回答