1. 程式人生 > >幾種快取記憶體演算法

幾種快取記憶體演算法

快取是在CPU和記憶體之間的一塊存取速度極快的儲存單元,CPU在處理資料時,如果在暫存器中找不到目標資料,則優先從快取中尋找。而快取的容量遠遠小於記憶體的容量,當快取已滿而又要繼續往其中新增新的資料的時候,如何替換快取中已有的資料就是快取記憶體演算法要解決的問題。假設CPU要使用的頁面依次為{1,2,4,1,5,7,4},而快取的最大容量為3,以下分別以此為例介紹往快取的中新增資料的兩種演算法

(a) LRU演算法(Least Recently Used,最久未使用演算法)。將最久未使用的頁面捨棄,給新資料騰空間。步驟如下:

1) 將頁面1調入快取:1

2) 將頁面2調入快取: 2,1

3)將頁面4調入快取: 4,2,1

4)將頁面1調入快取: 1,4,2

5)將頁面5調入快取: 5,1,4;快取已滿,將最久未使用的頁面2捨棄,給新頁面5騰空間

6)將頁面7調入快取: 7,5,1;將最久未使用的頁面4捨棄

7)將頁面4調入快取: 4,7,5;將最久未使用的頁面1捨棄

(b)LFU演算法(Least Frequently Used,最不經常使用演算法)。將使用最少的頁面捨棄,給新頁騰空間。需要給要使用的所有頁面分別維護一個變數,用來記錄其被使用的次數。每一次需要置換時,用新頁面替換快取中使用次數最少的頁面。

        現基於這兩種演算法,建立一個函式,用於記錄CPU在使用一組頁面時,從快取中獲取目標頁面失敗的次數,例如,當CPU要使用頁面4時,此時快取中恰好存有頁面4時,則從快取中獲取目標頁面成功,否則認為獲取失敗。函式的輸入為快取的最大容量capasity和要使用的頁面陣列。具體程式碼如下:

package javaTest;

public class CacheAlgorithm {
	public static void main(String[] args){
		int capacity = 4;
		int[] pages = {1,2,3,2,5,2,6,7,4,8,3};
		System.out.println(lru(capacity,pages));
		System.out.println(lfu(capacity,pages));
	}

	public static int lru(int capacity, int[] pages){
		int count = 0;
		int[] cacheUnit = new int[capacity];
		for(int i=0; i<pages.length; i++){
			boolean flag = false;
			for(int j=0; j<capacity; j++){
				if(cacheUnit[j]==pages[i]){
					add(cacheUnit, pages[i], j);
					flag = true;
					break;
				}
			}
			if(!flag){
				count++;
				add(cacheUnit,pages[i],capacity-1);
			}
		}
		return count;
	}

	public static int lfu(int capacity, int[] pages){
		int[] cacheUnit = new int[capacity];
		int count = 0;
		int max = 0;
		for(int i:pages){
			if(i>max){max = i;}
		}
		int[] state = new int[max+1];
		for(int i:pages){
			state[pages[i]]++;
			boolean flag = false;
			for(int j=0; j<capacity; j++){
				if(cacheUnit[j]==i){
					flag = true;
					break;
				}
			}
			if(!flag){
				count++;
				int index = 0;
				for(int j=0; j<capacity; j++){
					if(state[cacheUnit[j]]<state[cacheUnit[index]]){
						index = j;
					}
				}
				cacheUnit[index] = i;
			}
		}
		return count;
	}
	
	public static void add(int[] cacheUnit, int value, int index){
		for(int i=0; i<index; i++){
			cacheUnit[i+1] = cacheUnit[i];
		}
		cacheUnit[0] = value;
	}
}