我在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个字节的间隔?)
答案 0 :(得分:2)
1)正确。读取el1->next
时,它会读取包含该成员的缓存行,但不会读取它指向的缓存行。 (处理器不知道该字段的值是内存地址,除非它执行取消引用该字段的指令。)
2)高速缓存行是64字节,对齐64字节。如果访问next
并且它位于地址0x600428处,则将要读取的高速缓存行包含字节0x600400-0x60043f。处理器不知道结构的大小,也不知道结构的某些部分正在填充。如果您访问跨越两条缓存行的结构中的一个元素,则处理器不会知道这一点,因此它仅读取访问的缓存行。 (硬件预取器可能会提取下一行,以为可能很快就会需要它,但这与结构的大小无关。)