1. 引言
在使用地平线开发板进行模型部署时,大家会遇到两个函数hbSysAllocCachedMem() 和 hbSysAllocMem(),他们都是用来申请内存的,可以发现他们的区别只有一个cache,此时,不知道大家有没有这些疑问:
什么是cache?
为什么要用cache?
怎么用cache?
带着这些疑问,我们来一起学习cache机制。
2. 什么是cache

3. 为什么要用cache
当CPU需要读取一个数据时,首先从缓存cache中查找,找到就立即送给CPU处理。数据已经在缓存中,用一个专业名词代替:缓存命中(cache hit),此时CPU可以直接从缓存中读取数据,从而大大加快访问速度。
如果数据不在缓存中,专业名词称为:缓存未命中(cache miss)。在这种情况下,CPU需要从速率相对较慢的内存中加载数据到缓存中,然后再送给CPU进行处理。这个过程涉及较慢的内存访问,因此会引起一些延迟。
那什么场景下推荐使用带cache的内存呢?
- CPU频繁读取数据的场景。
- 模型连续推理时,多次读写输入/输出数据的场景。
以上场景均可以充分发挥缓存命中的优势,大幅提升性能。此外,对于不确定的场景,也建议使用cache。
此时,大家可能有这样的疑问,既然cache这么好,是不是所有场景都是用cache更优呢?

地平线计算平台中计算器件有CPU、BPU等,它们之间是共享内存的,如上图所示,如果输入数据仅给BPU进行处理,可以不使用cache,减少cache数据刷新的时间开销(1M数据约60us)。
4. 怎么用cache
先来了解一些接口函数。
4.1 hbSysAllocCachedMem()
参数
[in] size 申请内存的大小。
[out] mem 内存指针。
返回值
返回 0 则表示API成功执行,否则执行失败。
4.2 hbSysFlushMem()
对缓存和内存数据进行刷新。
参数
[in] mem 内存指针。
[in] flag 刷新标志符,有1和2两个参数来控制数据刷新方向,详情见hbSysMemFlushFlag的介绍。
返回值
返回 0 则表示API成功执行,否则执行失败。
4.3 hbSysMemFlushFlag
内存与缓存同步参数。
HB_SYS_MEM_CACHE_INVALIDATE 将内存中数据同步到缓存中,CPU读前使用,否则CPU会读取到之前缓存中的旧数据。
HB_SYS_MEM_CACHE_CLEAN 将缓存中数据同步到内存中,CPU写后使用,否则BPU会读取到之前内存中的旧数据。
CPU与内存之间存在cache缓存区,若没有正确刷新数据,可能会导致缓存中的内容与内存中的内容不同步。为了每次都能够拿到最新的数据,我们需要在CPU读前、写后进行数据更新。CPU读前,将内存中数据更新到缓存中。CPU写后,将缓存中数据更新到内存中。
4.4 代码示例
4.5 hbSysAllocMem()
申请内存,此时不需要和cache之间存在数据交互,意味着不需要考虑hbSysAllocMem()与hbSysFlushMem()的联合使用。
参数
[in] size 申请内存的大小。
[out] mem 内存指针。
返回值
返回 0 则表示API成功执行,否则执行失败。

