欢迎所有平台,请注明您的回答平台。
类似的问题:如何在C++中以编程方式获取CPU缓存页面大小?
在x86上,可以将CPUID指令与函数2一起使用,以确定高速缓存和TLB的各种属性。解析函数2的输出有些复杂,因此请参阅英特尔处理器标识与CPUID指令(PDF)的第3.1.3节。
要从C/C++代码中获取此数据,您需要使用内联汇编、编译器内部函数或调用外部汇编函数来执行CPUID指令。
您还可以尝试通过测量一些时间来以编程方式执行此操作。显然,它不会总是像CPUID等那样精确,但它更便携。Atlas在其配置阶段就做到了这一点,您可能想看看它:
http://math-atlas.sourceforge.net/.
在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共享该缓存。如果您正在使用共享数据进行多线程编程,这将非常有用(如果共享数据的线程也共享缓存,您将获得更好的结果)。
coherency_line_size
在Windows平台上:
从http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx
GetLogicalProcessor信息 功能会给你特点。 正在使用的逻辑处理器的 该系统。你可以走 系统_逻辑_处理器_信息 由查找的函数返回 类型为RelationCache的条目。每一个 此类条目包含处理器掩码 它告诉您哪些处理器 项适用于,而在 缓存_描述符,它告诉你什么 正在描述缓存的类型,并且 该缓存线有多大 缓存.
在Linux上查看sysconf(3)。
sysconf (_SC_LEVEL1_DCACHE_LINESIZE)
您也可以使用getconf从命令行获取它:
$ getconf LEVEL1_DCACHE_LINESIZE 64
我一直在做一些缓存线的东西,需要写一个跨平台的功能。我在https://github.com/NickStrupat/CacheLineSize将其提交给GitHub repo,或者您可以只使用下面的源代码。你想怎么做就怎么做吧。
#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
ARMv6及更高版本具有C0或缓存类型寄存器。但是,它仅在特权模式下可用。
C0
例如,从Cortex™-A8技术参考手册:
高速缓存类型寄存器的目的是确定指令 和数据高速缓存的最小行长度(以字节为单位),以启用 要作废的地址。 缓存类型寄存器为: 只读寄存器 仅在特权模式下可访问。 缓存类型寄存器的内容取决于具体的 实施。图3-2显示了高速缓存的位排列 类型寄存器..
目的是确定指令 和数据高速缓存的最小行长度(以字节为单位),以启用 要作废的地址。
缓存类型寄存器为:
内容取决于具体的 实施。图3-2显示了高速缓存的位排列 类型寄存器..
不要假设ARM处理器有高速缓存(显然,有些可以配置为没有高速缓存)。确定它的标准方法是通过C0。从手臂手臂第B6-6页:
在ARMv6中,系统控制协处理器缓存类型寄存器是 定义一级缓存的授权方法,请参阅上的缓存类型寄存器 第B6-14页。这也是早期变体的推荐方法。 建筑。此外,对其他级别的考虑 第B6-12页上的缓存描述了第2级的体系结构指南 缓存支持.
如果您正在使用SDL2,则可以使用此函数:
int SDL_GetCPUCacheLineSize(void);
其返回L1高速缓存线的大小,以字节为单位。
在我的x86_64机器上,运行以下代码片段:
printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize());
产生CacheLineSize = 64
CacheLineSize = 64
我知道我有点晚了,但只是为未来的访问者添加信息。 SDL文档目前说返回的数字以KB为单位,但实际上是以字节为单位。
,您可以使用硬件_破坏性_干扰_大小。 其定义为:
避免假共享的两个对象之间的最小偏移。保证 至少为ALIGNOF(STD:Max_ALIGN_T)
最小偏移。保证 至少为ALIGNOF(STD:Max_ALIGN_T)