6.12 通過內存緩存來提升性能

當在進行大量的計算時,提升性能最直接有效的一種方式就是避免重複計算。通過在內存中緩存和重複利用相同計算的結果,稱之爲內存緩存。最明顯的例子就是生成斐波那契數列的程序(詳見第 6.6 和 6.11 節):

要計算數列中第 n 個數字,需要先得到之前兩個數的值,但很明顯絕大多數情況下前兩個數的值都是已經計算過的。即每個更後面的數都是基於之前計算結果的重複計算,正如示例 6.11 fibonnaci.go 所展示的那樣。

而我們要做就是將第 n 個數的值存在數組中索引爲 n 的位置(詳見第 7 章),然後在數組中查找是否已經計算過,如果沒有找到,則再進行計算。

程序 Listing 6.17 - fibonacci_memoization.go 就是依照這個原則實現的,下面是計算到第 40 位數字的性能對比:

  • 普通寫法:4.730270 秒
  • 內存緩存:0.001000 秒

內存緩存的優勢顯而易見,而且您還可以將它應用到其它類型的計算中,例如使用 map(詳見第 7 章)而不是數組或切片(Listing 6.21 - fibonacci_memoization.go):

package main

import (
    "fmt"
    "time"
)

const LIM = 41

var fibs [LIM]uint64

func main() {
    var result uint64 = 0
    start := time.Now()
    for i := 0; i < LIM; i++ {
        result = fibonacci(i)
        fmt.Printf("fibonacci(%d) is: %d\n", i, result)
    }
    end := time.Now()
    delta := end.Sub(start)
    fmt.Printf("longCalculation took this amount of time: %s\n", delta)
}
func fibonacci(n int) (res uint64) {
    // memoization: check if fibonacci(n) is already known in array:
    if fibs[n] != 0 {
        res = fibs[n]
        return
    }
    if n <= 1 {
        res = 1
    } else {
        res = fibonacci(n-1) + fibonacci(n-2)
    }
    fibs[n] = res
    return
}

內存緩存的技術在使用計算成本相對昂貴的函數時非常有用(不僅限於例子中的遞歸),譬如大量進行相同參數的運算。這種技術還可以應用於純函數中,即相同輸入必定獲得相同輸出的函數。

鏈接

results matching ""

    No results matching ""