0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于LRU(Least Recently Used)的逻辑实现

Spinal FPGA 来源:Spinal FPGA 2024-11-12 11:47 次阅读

凑巧看到一个有关LRU(Least Recently Used)的逻辑实现,其采用矩阵方式进行实现,看起来颇有意思,但文章中只写方法不说原理,遂来研究下。

LRU

LRU(Least Recently Used)算法是一种常用的缓存淘汰策略,其核心思想是:如果一个数据在最近一段时间内没有被访问到,那么在未来它被访问的可能性也很小。因此,当缓存满了的时候,最久未使用的数据会被淘汰。

LRU在Cache替换策略里还是有较大的用途的。对于一个N路组相连,当对应的entry满了之后,当有新的访问请求到来后需从N个entry中挑选出一个替换entry。通过LRU可以挑选出最久没有被使用的元素。

LRU矩阵实现原理

对于一个具有N个Entry空间,LRU实现可以采用矩阵方式实现。这里以四个Entry空间为例:

c58b690e-9056-11ef-a511-92fbcf53809c.jpg

对于矩阵中的元素Value[i,j](第i行第j个元素),定义如下:

1: 为1时表示元素i在j访问之后被访问过。

0:为0时表示元素i在j被访问之后没有被访问过。

搞清楚了这两个元素定义,那么我们自然可以定义规则。当entry i被访问时,执行如下操作:

将第i行所有元素全部设置为1.

将第i列所有元素全部设置为0.

这里有一个点就是Value[i,i]将会被设置为0,也没有毛病,毕竟元素i在元素i被访问之后没有被访问过也是对的。

那么基于此,很明显一定存在某一行存在所有元素全为0的情况,从而也表示了其是Least Recently Used。

下图给出了基于矩阵的LRU检测过程:

c5af0d32-9056-11ef-a511-92fbcf53809c.jpg

Demo

基于上面的原理,下面的代码基于SpinalHDL写了一个简单的Demo,包含仿真代码:

packageLRU

importspinal.core._
importspinal.lib._

caseclass LRUUpdateRequest(entryNum: Int)extends Bundle {
val lru_state = Bits(entryNum * entryNum bits) //LRU State entryNum row,entryNum col
val lru_update_entry = UInt(log2Up(entryNum) bits)
}

caseclass LruControl(entryNum: Int)extends Component {
val io = newBundle {
val lru_state = in Bits(entryNum * entryNum bits)//LRU状态
val lru_entry = out UInt(log2Up(entryNum)bits) //最近最少被使用

val lru_update_req = in(LRUUpdateRequest(entryNum))
val lru_update_result = out(Bits(entryNum * entryNum bits))
}
noIoPrefix()
/** *****************************************************************************************
* 计算最近最少被使用者
* 寻找矩阵中为0的行,只需找到一个即可,找最低位
* 实现机制:每一行做按位或,随后取反,转换为寻找最低位为1的位置
* ***************************************************************************************** */
val lru_row_state = io.lru_state.subdivideIn(entryNum bits).map(~_.orR).asBits()
val lru_row_state_oh = OHMasking.first(lru_row_state) //先转换成独热码
io.lru_entry := OHToUInt(lru_row_state_oh) //再转换成二进制
/** *****************************************************************************************
* lru更新
* 更新规则,当更新entry i时,矩阵中第i行全部填1,矩阵中第i列全部填0
* ***************************************************************************************** */
val lru_update_entry_oh = UIntToOh(io.lru_update_req.lru_update_entry) //转换成独热码
for{
rowIndex <- 0 until entryNum;
    colIndex <- 0 until entryNum
  } {
    io.lru_update_result(rowIndex * entryNum + colIndex) := Mux(
      sel = lru_update_entry_oh(colIndex),
      whenTrue = False,
      whenFalse = Mux(
        sel = lru_update_entry_oh(rowIndex),
        whenTrue = True,
        whenFalse = io.lru_update_req.lru_state(rowIndex * entryNum + colIndex))
    )
  }
}

import spinal.core.sim._
import spinal.lib.tools.BigIntToListBoolean

object LruControlApp extends App {
  SimConfig.withFstWave.compile(LruControl(4)).doSim(dut => {
var lruState = BigInt(0)

def showLruState()= {
val lru_state_boolean = BigIntToListBoolean(lruState, 16bits)
for(rowIndex <- 0 until 4) {
        println(s"${lru_state_boolean.slice(rowIndex * 4, rowIndex * 4 + 4).map(_.toInt)}")
      }
    }

    def updateRequest(entry: Int) = {
      println(s"Update Entry:${entry}")
      dut.io.lru_update_req.lru_update_entry #= entry
      dut.io.lru_update_req.lru_state #= lruState
      sleep(1)
      lruState = dut.io.lru_update_result.toBigInt
      //show 矩阵
      showLruState()

      dut.io.lru_state #= lruState
      sleep(1)
      val lruEntry = dut.io.lru_entry.toInt
      println(s"The Lru Entry is $lruEntry")
      sleep(1)
    }

    showLruState()
    dut.io.lru_state #= lruState
    sleep(1)
    val lruEntry = dut.io.lru_entry.toInt
    println(s"The Lru Entry is $lruEntry")
    sleep(1)
    for (entry <- Array(0, 1, 2, 3, 2, 3, 0, 1, 2, 0, 3)) {
      updateRequest(entry)
    }
  })
}

对于LRU矩阵实现,由于矩阵的存在导致其所需要的资源会随着entry的增加而膨胀。实现一个四路组相连则需要16bit的空间用于存储矩阵信息,8路就需要64bit信息了。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 仿真
    +关注

    关注

    50

    文章

    4029

    浏览量

    133350
  • 逻辑
    +关注

    关注

    2

    文章

    832

    浏览量

    29428
  • 矩阵
    +关注

    关注

    0

    文章

    420

    浏览量

    34482

原文标题:一文看懂LRU(Least Recently Used)实现

文章出处:【微信号:Spinal FPGA,微信公众号:Spinal FPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    LRU缓存模块最佳实践

    LRULeast Recently Used)是一种缓存替换算法,它的核心思想是当缓存满时,替换最近最少使用的数据。在实际应用中,LRU
    的头像 发表于 09-30 16:47 847次阅读

    Redis的LRU实现和应用

    在编程中,计数器是一种基本但强大的工具,用于跟踪和管理数据和资源。本文将深入探讨不同类型的计数器的应用,从Redis的LRU(最近最少使用)缓存淘汰算法的实现,到如何在内存受限的环境中有效地使用计数器,再到普通计数器的巧妙应用。
    的头像 发表于 12-15 09:24 561次阅读

    【原创】Android开发—Lru核心数据结构实现突破缓存框架

    【原创】Android开发—Lru核心数据结构实现突破缓存框架回复即可获取下载链接[hide=d15]链接:http://pan.baidu.com/s/1c2BfjsW 密码:bta5 更多学习资料加Q:1352716312,学习交流群:150923287[/hide]
    发表于 06-21 16:58

    关于汽车网络管理逻辑环的实现问题

    最近想做汽车网络管理,但是资料比较少,想采用底层和模型结合的方法来实现,看论文说要建立一个关于节点的逻辑环,用来观察节点之间的通信情况。不知道这个逻辑环具体要怎么
    发表于 04-27 15:18

    用作AND/OR逻辑的数字是什么意思

    喜我正在使用spartan6-150和ISE13.3。在地图报告文件(.mrp)中,有一个关于“切片寄存器数量”部分中“用作AND / OR逻辑的数字”的项目。我想知道寄存器如何用
    发表于 10-23 10:14

    如何在LUT和逻辑元件之间以及逻辑元件和逻辑单元之间进行交换

    嗨,我目前正在对设计进行初步分析。我正在研究关于实现不同功能所需资源的不同FPGA。我找不到一种方法来将设计使用的LUT数量相关联,并将其转换为virtex和spartan范围的逻辑单元格。如果可能
    发表于 01-08 10:18

    架构设计应用级缓存回收策略

    下。FIFO(First In First Out):先进先出算法,即先放入缓存的先被移除。LRULeast Recently Used):最近最少算法,使用时间距离现在最久的那个被
    发表于 01-14 17:08

    基于修正LRU的压缩Cache替换策略

    以优化压缩cache的替换策略为目标,提出一种优化的基于修正LRU的压缩cache替换策略MLRU-C。MLRU-C策略能利用压缩cache中额外的tag资源,形成影子tag机制来探测并修正LRU替换策略的错误
    发表于 04-15 09:51 36次下载

    CMOS级逻辑电路实现综述

    由前面的基础可知,CMOS只能实现基本逻辑的非,比如或逻辑,与逻辑,如果不加反相器,CMOS只能实现或非,与非
    的头像 发表于 09-07 14:43 5700次阅读
    CMOS级<b class='flag-5'>逻辑</b>电路<b class='flag-5'>实现</b>综述

    谷歌在内存方面依赖于per memcg lru lock

    能力。 作为世间最流行的操作系统Linux, 内核使用LRU, Last Recent Used 链表来管理全部用户使用的内存,用一组链表串联起一个个的内存页,并且使用lru lock来保护链表的完整性。 所有应用程序常用操作都
    的头像 发表于 01-15 14:00 1878次阅读
    谷歌在内存方面依赖于per memcg <b class='flag-5'>lru</b> lock

    在InnoDB如何选择从LRU_list

    如果写入redo 速度不变, 那么生成page 速度不变, 如果刷脏能力极其快, 那么理论上LRU_scan_depth 的深度设置成用户每秒最大的page IO 生成能力即可, 那么系统最好的状态
    的头像 发表于 05-29 10:59 509次阅读
    在InnoDB如何选择从<b class='flag-5'>LRU</b>_list

    设计并实现一个满足LRU约束的数据结构

    LRUCache(int capacity)` 以 **「正整数」** 作为容量 `capacity` 初始化 `LRU` 缓存
    的头像 发表于 06-07 17:05 950次阅读
    设计并<b class='flag-5'>实现</b>一个满足<b class='flag-5'>LRU</b>约束的数据结构

    在组相联cache中,用于替换cache line的算法有哪些?

    LRU(Least Recently Used)算法:该算法会跟踪每个cache line的age(年龄)情况,并在需要时替换掉近期最少使用的cache line。
    的头像 发表于 10-08 11:10 834次阅读

    redis的淘汰策略

    的写入。 Redis的淘汰策略主要有以下几种: LRULeast Recently Used,最近最少使用): 这是Redis默认的淘汰策略。当内存空间不足时,Redis会选择最近最
    的头像 发表于 12-04 16:23 516次阅读

    redis的lru原理

    Redis是一种基于内存的键值数据库,它使用了LRULeast Recently Used)算法来进行缓存的数据淘汰。LRU算法的核心思想
    的头像 发表于 12-05 09:56 593次阅读