以编程方式获取caching行大小?

所有平台欢迎,请指定您的答案的平台。

一个类似的问题: 如何以编程方式获取C ++中的CPUcaching页面大小?

在Linux上(有一个相当新的内核),你可以从/ sys获得这些信息:

/sys/devices/system/cpu/cpu0/cache/ 

这个目录有一个caching的每个级别的子目录。 每个目录都包含以下文件:

 coherency_line_size level number_of_sets physical_line_partition shared_cpu_list shared_cpu_map size type ways_of_associativity 

这给你更多关于caching的信息,然后你将会知道,包括caching行的大小以及什么样的CPU共享这个caching。 如果您正在使用共享数据进行multithreading编程(如果共享数据的线程也共享caching,则会获得更好的结果),这非常有用。

在Linux上查看sysconf(3)。

 sysconf (_SC_LEVEL1_DCACHE_LINESIZE) 

你也可以使用getconf从命令行获得它:

 $ getconf LEVEL1_DCACHE_LINESIZE 64 

我一直在做一些caching行的东西,需要编写一个跨平台的function。 我承诺它在https://github.com/NickStrupat/CacheLineSize github回购,或者你可以使用下面的来源。 随意做任何你想要的。

 #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 

在x86上,可以使用带有函数2的CPUID指令来确定caching和TLB的各种属性。 parsing函数2的输出有些复杂,所以我将参考英特尔处理器标识和CPUID指令 (PDF)的第3.1.3节。

要从C / C ++代码获取这些数据,您需要使用内联汇编,编译器内在函数或调用外部汇编函数来执行CPUID指令。

在Windows平台上:

来自http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx

GetLogicalProcessorInformation函数将为您提供系统使用的逻辑处理器的特性。 您可以遍历函数返回的SYSTEM_LOGICAL_PROCESSOR_INFORMATION,查找RelationCachetypes的条目。 每个这样的条目都包含一个ProcessorMask,它告诉你哪个处理器适用于这个条目,而在CACHE_DESCRIPTOR中,它告诉你正在描述什么types的caching,以及这个caching的caching行有多大。

如果您使用SDL2,则可以使用此function:

 int SDL_GetCPUCacheLineSize(void); 

它以字节为单位返回L1caching行大小的大小。

在我的x86_64机器上,运行以下代码片段:

 printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize()); 

产生CacheLineSize = 64

我知道我有点晚了,但只是为未来的访问者添加信息。 目前的SDL文档说返回的数字是KB,但实际上是以字节为单位。

ARMv6及以上具有C0或高速cachingtypes寄存器。 但是,它只能在特权模式下使用。

例如,从Cortex™-A8技术参考手册 :

cachingtypes寄存器的目的是确定指令和数据caching的最小行长(以字节为单位),以使一系列地址无效。

cachingtypes寄存器是:

  • 一个只读寄存器
  • 只能在特权模式下访问。

cachingtypes寄存器的内容取决于具体的实现。 图3-2显示了cachingtypes寄存器的位排列


不要以为ARM处理器有一个caching(显然,有些可以configuration没有一个)。 确定它的标准方法是通过C0 。 从ARM ARM页面B6-6:

从ARMv6开始,系统控制协处理器高速cachingtypes寄存器是定义L1高速caching的强制方法,请参阅第B-14页的高速cachingtypes寄存器。 对于早期版本的体系结构,这也是推荐的方法。 此外,第B-12页的其他级别caching的注意事项描述了二级caching支持的体系结构指导原则。

你也可以尝试通过测量一些时间来编程。 显然,它不会总是像cpuid和类似的精确,但它更便携。 ATLAS在它的configuration阶段做它,你可能想看看它:

http://math-atlas.sourceforge.net/