如何获取每种缓存的数量

how to get number of cache of each sort

本文关键字:缓存 何获取 获取      更新时间:2023-10-16

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

一级数据缓存=2 x 64KB。

CPUID会给我每种缓存的大小,但不是它的编号。在MSDN上,我发现GetLogicalProcessorsInformationEx过程可能有助于获得该数字。但我不确定我是否理解正确。我想,CACHE_RELATIONSHIP结构的成员GROUP_AFINITY将与数量有关。有人能给我一些提示吗?或者告诉我其他人能找到这样的信息吗。

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

以下是我在普通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
}