顺序机能优化-局部性道理

更多文章

观点

一个编写优越的计算机递次经常具有优越的局部性,它们倾向于援用邻近于其他近来援用过的数据项的数据项,或许近来援用过的数据项自身,这类倾向性,被称为局部性道理。有优越局部性的递次比局部性差的递次运转得更快。

局部性一般有两种差别的情势:

  • 时候局部性

在一个具有优越时候局部性的递次中,被援用过一次的内存位置很可能在不远的未来被屡次援用。

  • 空间局部性

在一个具有优越空间局部性的递次中,假如一个内存位置被援用了一次,那末递次很可能在不远的未来援用四周的一个内存位置。

时候局部性示例

function sum(arry) {
    let i, sum = 0
    let len = arry.length

    for (i = 0; i < len; i++) {
        sum += arry[i]
    }

    return sum
}

在这个例子中,变量sum在每次轮回迭代中被援用一次,因而,关于sum来讲,具有优越的时候局部性

空间局部性示例

具有优越空间局部性的递次

// 二维数组 
function sum1(arry, rows, cols) {
    let i, j, sum = 0

    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            sum += arry[i][j]
        }
    }
    return sum
}

空间局部性差的递次

// 二维数组 
function sum2(arry, rows, cols) {
    let i, j, sum = 0

    for (j = 0; j < cols; j++) {
        for (i = 0; i < rows; i++) {
            sum += arry[i][j]
        }
    }
    return sum
}

再回头看一下时候局部性的示例,像示例中按递次接见一个数组每一个元素的函数,具有步长为1的援用形式。

假如在数组中,每隔k个元素举行接见,就称为步长为k的援用形式。

一般而言,跟着步长的增添,空间局部性下落。

这两个例子有什么区分?区分在于第一个示例是根据列递次来扫描数组,第二个示例是根据行递次来扫描数组。

数组在内存中是根据行递次来寄存的,效果就是按行递次来扫描数组的示例获得了步长为rows的援用形式;
而关于按列递次来扫描数组的示例来讲,其效果是获得一个很好的步长为1的援用形式,具有优越的空间局部性。

机能测试

运转环境

  • cpu: i5-7400
  • 浏览器: chrome 70.0.3538.110

对一个长度为9000的二维数组(子数组长度也为9000)举行10次空间局部性测试,时候(毫秒)取平均值,效果以下:

所用示例为上述两个空间局部性示例

按列排序按行排序
1242316

从以上测试效果来看,二维数组按列递次接见比按行递次接见快了1个数量级的速率。

总结

  • 反复援用雷同变量的递次具有优越的时候局部性
  • 关于具有步长为k的援用形式的递次,步长越小,在内存中以大步长跳来跳去的递次空间局部性会很差

测试代码

const arry = []
let [num, n, cols, rows] = [9000, 9000, 9000, 9000]
let temp = []

while (num) {
    while (n) {
        temp.push(n)
        n--
    }
    arry.push(temp)
    n = 9000
    temp = []
    num--
}

let last, now, val

last = new Date()
val = sum1(arry, rows, cols)
now = new Date()
console.log(now - last)
console.log(val)

last = new Date()
val = sum2(arry, rows, cols)
now = new Date()
console.log(now - last)
console.log(val)

function sum1(arry, rows, cols) {
    let i, j, sum = 0

    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++) {
            sum += arry[i][j]
        }
    }
    return sum
}

function sum2(arry, rows, cols) {
    let i, j, sum = 0

    for (j = 0; j < cols; j++) {
        for (i = 0; i < rows; i++) {
            sum += arry[i][j]
        }
    }
    return sum
}

参考资料

深切明白计算机体系

    原文作者:woai3c
    原文地址: https://segmentfault.com/a/1190000017925791
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞