使用指针访问结构变量时,Cache中会带来什么?

时间:2019-04-23 18:53:20

标签: c linux pointers caching x86

我在C中定义了一个结构,因此它是缓存行的大小(64字节)。

typedef struct _list{
  int value_1;
  int value_2;
  char padding[40];
  struct _list * next;
  struct _list * prev;
} list;

然后,如果我创建这种类型的元素

volatile list * el1 = malloc(sizeof(list));
el1->value_1 = 1;

volatile list * el2 = malloc(sizeof(list));
el2->value_1 = 1;

volatile list * el3 = malloc(sizeof(list));
el3->value_1 = 1;

el1->next = el2;
el2->next = el3;

volatile list * temp = el1;

//flushed above elements from cache.

temp = temp->next;

元素之间的间隔为16个字节。

 el1:  value_1: 0x557816467530, next: 0x557816467560
 el2:  value_1: 0x557816467580, next: 0x5578164675b0,

使用这样的代码,在刷新后,使用禁用的预取器,执行最后一行:

1)在高速缓存中,它将仅携带el1元素并修改temp,因此它将查找el1的下一个查找对象的地址。这段代码不会导致el2元素进入缓存吗?

2)它会从下一个变量引入缓存地址吗?从0x557816467560开始,再加上下一个相邻的64个字节? (如果是,那么在下一个相邻字节中,是否包括16个字节的间隔?)

1 个答案:

答案 0 :(得分:2)

1)正确。读取el1->next时,它会读取包含该成员的缓存行,但不会读取它指向的缓存行。 (处理器不知道该字段的值是内存地址,除非它执行取消引用该字段的指令。)

2)高速缓存行是64字节,对齐64字节。如果访问next并且它位于地址0x600428处,则将要读取的高速缓存行包含字节0x600400-0x60043f。处理器不知道结构的大小,也不知道结构的某些部分正在填充。如果您访问跨越两条缓存行的结构中的一个元素,则处理器不会知道这一点,因此它仅读取访问的缓存行。 (硬件预取器可能会提取下一行,以为可能很快就会需要它,但这与结构的大小无关。)