我以前做过一个更简单的版本。我没有使用过缓存关联或计数,但我查询过缓存大小和缓存行大小。我怀疑可以通过在我所做的事情中交换一些论点来获得信息。
这是我为获得常见 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
}