幾種快取記憶體演算法
阿新 • • 發佈:2018-12-30
快取是在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;
}
}