Skip to content

为什么该数组写入 1 比写入 0 要慢?

复制本地路径 | 在线编辑

感谢作者:https://www.bilibili.com/video/BV1gu41117bW

非常好的视频,对于这个问题,建议从 55:00 开始看。

如下图所示,为什么这个数组中,写入 1 比写入 0 要慢?

问题说明

回答

知道这个问题,需要先了解 Cache 和 Memory 是 64B 为单位的,建议需要先看这个问题

如果 Cache 向 Memory 中写入数据,必须是 64B 为寻址。所以像上面的代码中给某个地址写入 4B 数据(int)时,他需要把这个地址计算对齐后的地址,读取 64B 数据到 Cache,把其中对应的 4B 数据替换掉,择机写回去(也就是说不是立即写回,假如下一次又要修改这个 64B 部分或整体数据,Cache 有缓存,可以一口气更新进去)

假设对于 64n B 的数据而言,如果每次写入 1,那么对于每隔 4 次,写入某个 4B 数据时 Cache 都必须从 Memory 读取 n 次(关键),向 Memory 写回也是 n 次。

但是对于写入 0 而言,它被编译器自动优化了 memset,而 memset 的内部则是用了叫做 stream 的指令。这个 stream 指令的作用:

  • 正常操作:Cache 向 Memory 写入某个 4B 数据时,Cache 如果没有缓存,需要按照上面所说需要先从 Memory 读取整个 64B 数据
  • stream 指令:Cache 不会立即从 Memory 读取 64B 数据,会等一段时间。这段时间内发现 Cache 又要向这个地址内其他偏移写入数据,最后能正好拼出 64B 数据,那么此时不需要从 Memory 读取 64B,而是直接把这个拼好的、新的 64B 写入 Memory

由于我们上面代码是 for 循环写入 4B 数据,所以使用 stream 指令显然就每隔 4 次就能拼出要更新的 64B 数据了,所以写入 0 没有 Cache 从 Memory 读取 64B 数据的操作,只有从 Memory 写入 n 次的操作。

所以上面的代码整体上写入 1 比写入 0 大概慢 2 倍。

Comments