GO語言————6.12 通過記憶體快取來提升效能

FLy_鵬程萬里發表於2018-07-01

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
}

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

相關文章