实际测试内存在顺序IO和随机IO时的访问延时差别

《内存随机访问也比顺序慢,带你深刻理解内存IO过程》一文中,咱们理解了内存IO的内部实现过程,知道了内存的随机IO比顺序IO要慢,并对延迟时间进行了大概的估算。那么咱们今天来用代码的方式来实践一下,看看在咱们的项目工程中,内存访问的在不一样的访问场景下延时到底是个什么表现。数组

先测顺序状况

测试原理就是定义一个指定大小的double(8字节)数组,而后以指定的步长去循环。这里面的变量有两个。核心代码以下:缓存

void init_data(double *data, int n){
int i;
for (i = 0; i < n; i++) {
data[i] = i;
}
}

void seque_access(int elems, int stride) {
int i;
double result = 0.0;
volatile double sink;

for (i = 0; i < elems; i += stride) {
result += data[i];
}
sink = result;
}

在这个核心代码的基础上,咱们有两个可调节变量:app

  • 一是数组大小,数组越小,高速缓存命中率越高,平均延时就会越低。dom

  • 二是循环步长,步长越小,顺序性越好,一样也会增长缓存命中率,平均延时也低。咱们在测试的过程当中采起的办法是,固定其中一个变量,而后动态调节另一个变量来查看效果。ide

另外说明一下,这个代码测试中考虑的几个额外的开销的处理状况。
1.加法开销:因为加法指令简单,一个CPU周期就可完成,CPU周期比内存周期要快,因此暂且忽略它。
2.耗时统计:这涉及到高开销的系统调用,本实验经过跑1000次取一次耗时的方式来下降影响。

场景一:固定数组大小2K,调节步长测试

图1 固定数组2k,动态调节步长spa

数组足够小的时候,L1 cache所有都能装的下。内存IO发生较少,大部分都是高效的缓存IO,因此我这里看到的内存延时只有1ns左右,这其实只是虚拟地址转换+L1访问的延时。code

场景二:固定步长为8,数组从32K到64Morm


图2 固定步长,动态调节数组从32K到64Mblog

当数组愈来愈大,Cache装不下,致使穿透高速缓存,到内存实际IO的次数就会变多,平均耗时就增长

场景三:步长为32,数组从32K到64M

图片图3 固定步长为32,动态调节数组从32K到64M

和场景二相比,步长变大之后,局部性变差,穿透的内存IO进一步增长。虽然数据量同样大,可是平均耗时就会继续有所上涨。不过虽然穿透增长,但因为访问地址仍然相对比较连续,因此即便发生内存IO也绝大部分都是行地址不变的顺序IO状况。因此耗时在9ns左右,和以前估算大体相符!

另外注意一个细节,就是随着数组从64M到32M变化的过程当中。耗时有几个明显的降低点,分别是8M,256K和32K。这是由于本机的CPU的L1大小是32K,L2是256K,L3是12M。在数据集32K的时候,L1全能装的下,全部基本都是高速缓存IO。256K的时候、8M的时候,虽然L1命中率降低,可是L二、L3访问速度仍然比真正的内存IO快。可是超过12M之后越多,真正的内存IO就愈来愈多了。

再测随机IO状况

在顺序的实验场景里,数组的下标访问都是比较有规律地递增。在随机IO的测试中,咱们要完全打乱这个规律,提早随机好一个下标数组,实验时不停地访问数组的各个随机位置。

void init_data(double *data, int n){
int i;
for (i = 0; i < n; i++) {
data[i] = i;
}
}

void random_access(int* random_index_arr, int count) {
int i;
double result = 0.0;
volatile double sink;

for (i = 0; i < count; i++) {
result += data[*(random_index_arr+i)];
}
sink = result;
}
这实际比上面的实验多了一次内存IO,但因为对random_index_arr的访问时顺序的,并且该数组也比较小。咱们假设它所有能命中高速缓存,因此暂且忽略它的影响。

随机实验场景:数组从32K到64M

图片图4 随机访问

此次的数组访问就没有步长的概念了,所有打乱,随机访问。当数据集比较小的时候、L一、L二、L3还能抗一抗。但当增长到16M、64M之后,穿透到内存的IO状况会变多,穿透过去之后极大可能行地址也会变。在64M的数据集中,内存的延时居然降低到了38.4ns,和咱们估算的也基本一致。

结论

有了实验数据的佐证,进一步证明了《内存随机访问也比顺序慢,带你深刻理解内存IO过程》的结论。内存存在随机访问比顺序访问慢的多的状况,大概是4:1的关系。因此不要以为内存很快,就用起来太随性了

相关文章
相关标签/搜索