【python学习笔记】29:模拟OPT和LRU算法

LRU之前做过,OPT 最佳淘汰算法是一种理想状态的算法,是去寻找后面没有使用,或者最晚使用的那个cache中的页面淘汰掉。

急着回去睡觉,不废话了。

代码实现

#-*-coding:utf-8-*-
from numpy import *

#一行四个输出
def MyPrint(lst,strlst):
    i=0
    for j in range(len(lst)):
        print strlst,'[',j,']=',lst[j],
        i+=1
        if i%4==0:
            print

#生成并输出地址表
def VtrAds():
    a=[-1 for i in range(256)] #存虚拟地址的数组
    #放入顺序增长的地址,每次4个
    index=0
    for i in range(32):
        index+=random.randint(0,4) #随机地加一点
        RandAds=random.randint(12767,22767) #随机生成一个起始地址
        #写入连续地址
        a[index]=RandAds
        a[index+1]=RandAds+1
        a[index+2]=RandAds+2
        a[index+3]=RandAds+3
        index+=4 #跳跃到下一个位置
    #放入较小的地址
    index=0
    skip=False #决定要不要跳过(交叉放入)
    lftCount=0
    while(True):
        #如果放入的数目足够了就结束循环
        if lftCount>=64:
            break
        #如果能放并且不用跳过
        if a[index]<0 and skip==False:
            a[index]=random.randint(0,12766) #放入一个小地址
            lftCount+=1 #记录成功放入了一次
            skip=True #下次就需要跳过了
        #如果能放入但需要跳过
        elif a[index]<0 and skip==True:
            skip=False #下次就不用跳过了
        index+=1 #指向下一个需要选择的地址
    #放入较大的地址
    for index in range(256):
        #只要是空的
        if a[index]<0:
            a[index]=random.randint(22768,32767) #就直接放入
    a=array(a) #转换为numpy数组
    #a=reshape(a,(-1,4)) #每行4个
    #按行输出
    print 'THE VIRTUAL ADDRESS STREAM AS FOLLOWS:'
    MyPrint(a,'a')
    print '='*30
    return a

#OPT算法
def MyOpt(i,a):
    print '-'*30
    print 'PAGE NUMBER WITH SIZE %dk FOR EACH ADDRESS IS:'%i
    yita=i*1024 #表示页面大小
    pageno=[num/yita+1 for num in a]
    '''
    pageno=a/yita
    #变成int
    for j in range(len(pageno)):
        pageno[j]=int(pageno[j])
    '''
    MyPrint(pageno,'pageno')
    print 'page assigned',' '*20,'page_in/total reference'
    for lnth in range(4,34,2):
        ok=getInOpt(lnth,pageno)
        print lnth,' '*40,ok

'''
#判断元素是否在列表里
def isIn(a,lst):
    for b in lst:
        if a==b:
            return True
    return False
'''

#获取OPT命中率
def getInOpt(lnth,pageno):
    cache=[]
    innum=0
    #对于需要的每个页面
    for i in range(len(pageno)):
        '''
        if len(cache)==0: #小心越界,单独判断
            cache.append(pageno[i]) #把页面加入进来
            continue
        '''
        #如果已经在cache里面
        if pageno[i] in cache:
            innum+=1
            continue #直接使用就行了,进入下一次
        #如果不在,但cache未满
        elif len(cache)#把页面加入进来
        else: #OPT的核心(如果cache满时缺页)
            cache=lossOpt(cache,pageno,i) #更新cache
    return float(innum)/len(pageno)

#用于在Opt算法下更新cache
def lossOpt(cache,pageno,i):
    #bye数组记录哪个页不要了
    bye=[False for j in range(len(cache))]
    num=0 #记录已经有几个要留下
    #循环去看后面的每个页pageno[j]
    for j in range(i+1,len(pageno)):
        if num==len(cache)-1: #如果已经找到这么多
            break
        #如果有新的缺页项
        if (pageno[j] in cache)\
                and (bye[cache.index(pageno[j])]==False):
                    num+=1 #新的缺页项
                    bye[cache.index(pageno[j])]=True
    #拿掉那个还是False的
    #即使后面的元素不够多,在循环体外拿掉也是正确的
    for k in range(len(bye)):
        if bye[k]==False:
            del cache[k]
            break #拿掉一个就退出!
    return cache #返回新的cache

#获取LRU命中率
def getInLru(lnth,pageno):
    cache=[]
    innum=0 #命中次数
    for i in range(len(pageno)): #每个页面号i 
            if pageno[i] not in cache: #如果不在cache中,即缺页 
                if len(cache)#如果cache未满
                #就在其尾部添加这一页(新加的在后面)
                        cache.append(pageno[i])  
                else: #如果cache满了
                #拿掉最不常用的(在最前)
                #即把后面的前移
                        cache[0:lnth-1:]=cache[1:lnth:]
                        cache[lnth-1::]=[pageno[i]] #将这页放在最后 
            else: #如果在cache中,即命中,注意这时不能用lnth了
            innum+=1 #记录
            #这时候要把那个页放到最后面,不改变其它的相对顺序
            #将它之后的页都复制到从它向后的位置
            #并在最后留一个空位保证不改变cache长度
            #所以保守地显示指明len(cache)-1
            cache[cache.index(pageno[i]):len(cache)-1:]=\
                    cache[cache.index(pageno[i])+1::]
            #把这一页放在最后(最新)
            cache[len(cache)-1::]=[pageno[i]]
    return float(innum)/len(pageno)

#LRU算法
def MyLru(i,a):
    print '-'*30
    print 'PAGE NUMBER WITH SIZE %dk FOR EACH ADDRESS IS:'%i
    yita=i*1024 #表示页面大小
    pageno=[num/yita+1 for num in a]
    MyPrint(pageno,'pageno')
    print 'page assigned',' '*20,'page_in/total reference'
    for lnth in range(4,34,2):
        ok=getInLru(lnth,pageno)
        print lnth,' '*40,ok


#便利函数作入口
def Go():
    a=VtrAds() #生成地址表a
    print '输入OPT/LRU选择算法:'
    name=raw_input() #输入算法名称
    if name!='OPT' and name!='LRU':
        print '错误的输入,再见!'
        return
    print 'The algorithm is:',name
    #执行算法
    if name=='OPT':
        for i in (1,2,4,8):
            MyOpt(i,a)
    elif name=='LRU':
        for i in (1,2,4,8):
            MyLru(i,a)

测试

随机地址表,按照要求一半是顺序执行,一半均匀散布在低地址,一半均匀散步在高地址。
【python学习笔记】29:模拟OPT和LRU算法_第1张图片

【python学习笔记】29:模拟OPT和LRU算法_第2张图片

页面大小取1k,2k,4k,8k,然后对每个页面大小,取cache能存的页数从4~32(步长2),测试一下快表命中率
【python学习笔记】29:模拟OPT和LRU算法_第3张图片

cache能存的页面数一样时,页面越大,命中率越大,因为一个页面能包容的地址更多了。

页面大小一样时,cache能存的页面数越多,命中率越大,因为cache里存的页面多了,自然更容易命中了。

你可能感兴趣的:(Python)