char x[2048] 和缓存行问题

char x[2048] and cache line issue

下面是简单的c源码,其中char x[2048]是一个全局变量,func1thread1调用,func2被[=15调用=]:

char x[2048]={0} , y[16]={0};

void func1(){
    strcpy(x,y);
}

void func2(){
    printf("(%s)\n",x);
} 

int main(int argc, char **argv){
    strncpy(y,argv[1],sizeof(y)-1);
} 

在Intel的cpu中,一个cache line有64字节,所以x应该占32 缓存行,我的问题是:

  1. thread1 调用 func1 时,是否所有 32 个缓存行都可用于该 CPU 缓存直到那时 strcpy? (或)编译器知道只有一个高速缓存行就足以完成这项工作?

  2. thread2 调用 func2 时,是否所有 32 个缓存行都可用于该 CPU 缓存直到那时 printf? (或)编译器可以识别一个缓存行是否足够?

在 x86 和 x64(以及现代 ARM 和其他常见 CPU 上),缓存对用户模式程序是完全透明的。

因此,strcpy 执行第一次读取,CPU 自动拉入一个缓存行,strcpy[=12=] 上退出,完成。与 printf("%s",x).

相同

我建议您阅读维基百科页面:https://en.wikipedia.org/wiki/CPU_cache

一些背景:

  1. 通常情况下,缓存行($L) 对程序是透明的。所以大多数程序员不直接处理缓存行(将其引入,将其踢出)。 CPU 一旦发现 code/data 不在 $L 中,就会停止这种内存访问并按需引入 $L。
  2. 虽然有编码技术可以在代码中将数据引入缓存行(例如通过预取指令),但通常编译器不会足够聪明地为您执行此操作,因为它可能预取得太早(所以到时候$L 已被使用,它已经被踢出),或者为时已晚(CPU 仍然需要暂停内存访问)。

回答你的问题:

  1. 没有。编译器不知道需要引入多少$L(它怎么知道一段数据是否已经在$L 中,所以安全起见,不要自取其辱)。编译器只是发出,例如MOV指令,CPU,在执行这条指令时,发现操作数不在$中,所以会按需带入。由于您的编程只复制到 '\0',所以 $L 引入停止在那里。
  2. 同#1。只有读取的 $L 才会被引入,编译器与此无关。

更多信息:

  1. CPU 预取器可能会带来当前需要的额外 $L。例如,它可能会引入下一个 $L 并希望获得数据局部性。
  2. 一些高级程序使用预取指令来提高程序性能。假设您知道您的代码将在不久的将来访问某个位置,您可以预取它,并且在您需要它时它已经存在,因此不会招致 $L 未命中惩罚。但是很难做到正确(您必须知道代码的内存访问模式并将预取指令插入正确的位置。一些高性能代码设计软件管道来执行此操作,但这又是一个高级主题)。

https://en.wikipedia.org/wiki/Instruction_prefetch