欢迎所有平台,但请在回答中指定所使用的平台。
在Linux上(使用相对较新的内核),您可以从/sys目录中获取此信息:
/sys/devices/system/cpu/cpu0/cache/
这个目录有每个缓存级别的子目录。这些目录中包含以下文件:
coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity
这提供了比你所期望知道的缓存更多的信息,包括缓存行大小(coherency_line_size
)以及共享此缓存的CPU。如果您正在使用共享数据的多线程编程(如果共享数据的线程还共享缓存,则会获得更好的结果),那么这非常有用。
cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
返回 64
。对于索引1、2、3文件夹也是如此。 - Abid Rahman Ksysconf(_SC_LEVEL1_DCACHE_LINESIZE)
在WSL上可以使用。 - Myria在Linux上查看sysconf(3)。
sysconf (_SC_LEVEL1_DCACHE_LINESIZE)
您也可以使用getconf命令从命令行获取它:
$ getconf LEVEL1_DCACHE_LINESIZE
64
我一直在研究缓存行相关的内容,需要编写一个跨平台函数。我已经提交了代码到 GitHub 仓库:https://github.com/NickStrupat/CacheLineSize,或者你也可以使用下面提供的源码。欢迎自由使用。
#ifndef GET_CACHE_LINE_SIZE_H_INCLUDED
#define GET_CACHE_LINE_SIZE_H_INCLUDED
// Author: Nick Strupat
// Date: October 29, 2010
// Returns the cache line size (in bytes) of the processor, or 0 on failure
#include <stddef.h>
size_t cache_line_size();
#if defined(__APPLE__)
#include <sys/sysctl.h>
size_t cache_line_size() {
size_t line_size = 0;
size_t sizeof_line_size = sizeof(line_size);
sysctlbyname("hw.cachelinesize", &line_size, &sizeof_line_size, 0, 0);
return line_size;
}
#elif defined(_WIN32)
#include <stdlib.h>
#include <windows.h>
size_t cache_line_size() {
size_t line_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) {
line_size = buffer[i].Cache.LineSize;
break;
}
}
free(buffer);
return line_size;
}
#elif defined(linux)
#include <stdio.h>
size_t cache_line_size() {
FILE * p = 0;
p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
unsigned int i = 0;
if (p) {
fscanf(p, "%d", &i);
fclose(p);
}
return i;
}
#else
#error Unrecognized platform
#endif
#endif
如果您正在使用SDL2,您可以使用这个函数:
int SDL_GetCPUCacheLineSize(void);
返回 L1 缓存行大小(以字节为单位)。
在我的 x86_64 计算机上,运行此代码片段:
printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize());
生成 CacheLineSize = 64
我知道我有点晚了,但是为了以后的访问者增加信息。 SDL文档目前说返回的数字是以KB为单位的,但实际上是以字节为单位的。
两个对象之间的最小偏移量,以避免虚共享。保证至少等于alignof(std::max_align_t)
GetLogicalProcessorInformation函数将提供系统中正在使用的逻辑处理器的特性。您可以遍历函数返回的SYSTEM_LOGICAL_PROCESSOR_INFORMATION,寻找类型为RelationCache的条目。每个这样的条目都包含一个ProcessorMask,告诉您该条目适用于哪个处理器(或多个处理器),以及在CACHE_DESCRIPTOR中,它告诉您正在描述什么类型的缓存以及该缓存的缓存行大小。
C0
或缓存类型寄存器。但是,它仅在特权模式下可用。缓存类型寄存器的目的是确定指令和数据缓存的最小行长度(以字节为单位),以使一系列地址无效。
缓存类型寄存器是:
- 只读寄存器
- 仅在特权模式下可访问。
缓存类型寄存器的内容取决于具体实现。图3-2显示了缓存类型寄存器的位排列...
C0
。来自ARM ARM,B6-6页:
从ARMv6开始,系统控制协处理器缓存类型寄存器是定义L1缓存的强制方法,请参见B6-14页上的Cache Type寄存器。这也是早期架构的推荐方法。此外,考虑到B6-12页上的附加缓存级别,描述了第2级缓存支持的架构指南。
你也可以尝试通过测量一些时间来以编程方式完成。显然,它不总是像cpuid等那样精确,但更具可移植性。ATLAS在其配置阶段执行此操作,您可能需要查看它:
SDL_GetCPUCacheLineSize
函数(扩展自negamartin的答案),然后查看cpuid宏
,该宏具有每个处理器型号的汇编源代码。 您可以查看https://imgur.com/a/KP57m6s或直接查看源代码。 - haxpor