缓存友好的方式添加到int数组

时间:2018-07-20 06:14:09

标签: swift caching optimization

我已经更加注意为缓存优化代码。我很好奇以下哪一项是添加两个数组的更便于缓存的方法。代码很快。

struct A {
    var x, y, z: [Int]
}
func add1(a: inout [A]) {
    for i in 0 ..< a.count {
        a[i].z = a[i].x + a[i].y
    }
}
func add2(x: [Int], y:[Int], z: inout [Int]) {
    for i in 0 ..< x.count {
        z[i] = x[i] + y[i]
    }
}

我担心的是,在add2中,由于xyz在内存中不必彼此靠近,因此本地性的好处可能会减少。例如,假设将x[0]加载到缓存中,然后将y[0]加载到缓存中。 y[0]附近的数据是否可以在缓存中覆盖x[0]附近的数据,以便需要从ram进行新的读取来加载x[1]?如果可以,add1是否可以解决此问题?

1 个答案:

答案 0 :(得分:0)

在具有直接映射的缓存的处理器上,像add2这样的访问模式可能是一个问题,并且仅在阵列的地址完全错误的情况下仍然如此。使用典型的4或8路集关联缓存,即使使用最大不吉利的数组地址,这里也没有问题:如果包含x[0]y[0]z[0]的块全部映射到同一集合,它们仍然适合并且不会互相弹出。直接映射的缓存确实遭受了您担心的冲突遗漏,这是为什么它们现在很少见的一部分,但是还有更多的原因。

实际上,像add2这样的访问模式非常好,因为根据所执行的操作,它也可以自动向量化。这不是通过溢出检查的加法来完成的(检查的加法很难矢量化),而是通过包装的加法&+compiler can use movdqu来在同一位置加载和存储两个Int时间,然后paddq同时添加两个Int。