数据缓存和指令缓存是什么意思?

Cel*_*tas 25 assembly arm cpu-architecture cpu-cache

这里:

指令和数据具有不同的访问模式,并访问不同的内存区域.因此,对于指令和数据具有相同的高速缓存可能并不总是有效.

因此,拥有两个缓存是相当普遍的:仅存储指令的指令缓存和仅存储数据的数据缓存.

知道指令和数据之间的区别是直观的,但现在我不确定这种情况下的区别吗?什么构成数据并被放入数据缓存中,什么构成指令并被放入指令缓存?

我知道ARM组装.请问什么需要STR,LDR,LDMF或者STMFD使用数据缓存?但是从技术上来讲STR,LDR,LDMFSTMFD都说明,所以我这就是为什么我很困惑."数据"必须始终存在"指令"吗?是否在该.data部分中考虑了数据?

例如,LDR R1, =myVar那么LDR会进入指令缓存并且myVar的内容会进入数据缓存吗?或者它不是那样的工作?

说明和数据有不同的访问模式有人可以详细说明吗?

我在一篇有用的帖子上发表的评论突显了我难以理解:

"我的想法是,如果一条指令已经从内存中加载,它可能会很快再次使用",但知道下一条指令的唯一方法就是读取它.这意味着内存读取(你不能说它已经在缓存中了,因为新指令是红色的).所以我仍然没有看到这一点?说刚刚发生了LDR指令,所以现在LDR在数据缓存中.可能会发生另一条LDR指令,也许它不会发生,我们无法确定所以我们必须实际读取下一条指令 - 从而破坏了缓存的目的.

old*_*mer 15

可以在块中完成指令提取,假设您大部分时间都要连续运行许多指令.因此,指令提取可以更有效,每个事务可能有少量或更多的开销时钟,然后存储器使数据准备好的延迟,然后是事务大小的总线宽度的时钟.例如,8个字或指令可以说是5 + n + 8个时钟,这比一次一个指令(5 + 1 + 1)*8更有效.

另一方面,数据并不是一个好的假设,数据将在大部分时间顺序读取,因此额外的周期可能会受到伤害,只需要获取所需的数据(直到内存或总线的宽度,因为这是一个免费赠品).

在ARM上我知道L1缓存I和D是分开的,它们是L2组合在一起.L1不在axi/amba总线上,并且可能比L2更有效的访问,并且超出其范围是amba/axi(开销的几个周期加上时间加上每个事务的每个总线宽度的数据一个时钟).

对于标记为可缓存的地址空间(如果mmu处于打开状态)L1,因此L2将获取缓存行而不是数据的单个项目,并且可能超过获取指令的I数据的获取量.

每个ldr和ldm指令都会产生数据周期,如果地址可缓存,则可以进入L2和L1缓存(如果尚未存在).如果在可缓存的地址处将进入L2和L1缓存(如果尚未存在),则指令本身也是如此.(是的,有很多旋钮可以控制什么是可缓存的而不是,不想进入这些细微差别,只是为了讨论而假设所有这些指令提取和数据访问都是可缓存的).

您可能希望保存刚刚在缓存中执行的指令,以防您有循环或再次运行该代码.此外,缓存行中的后续指令将受益于更高效访问所节省的开销.但是如果你只执行一小部分缓存行,那么总体来说这些周期是浪费,如果这种情况发生得太多,那么缓存会使事情变慢.

一旦某些内容在缓存中,则在下次读取(或根据设置编写)时,缓存副本是使用的缓存副本,而不是慢速内存中的副本.最终(取决于设置)如果某个项的缓存副本由于写入(str,stm)而被修改,并且某些新访问需要保存在缓存中,那么旧的访问将被逐出缓慢的内存和写入来自缓存使缓慢的内存发生.你没有指令的这个问题,指令基本上是只读的,所以你不必将它们写回慢速内存,理论上缓存副本和慢速内存副本是相同的.

ldr r1,=myvar
Run Code Online (Sandbox Code Playgroud)

将导致pc相对负载

ldr r1,something
...
something: .word myvar
Run Code Online (Sandbox Code Playgroud)

ldr指令将成为缓存行提取,指令提取(以及更多指令)的一部分.这些将保存在手臂上的L1缓存的一部分和L2的共享部分(如果启用等).当最终执行该指令时,某些内容的地址将经历数据读取,如果在该区域中为该读取启用了缓存,那么它也将进入L2和L1缓存(D部分)(如果尚未存在).如果你循环并立即再次运行该指令,那么理想情况下,指令将在L1缓存中,并且获取它的访问时间非常快,少数时钟总计.数据也将位于L1缓存中,并且还将是少数几个要读取的时钟.

我在上面提到的5 + n + 8,有一些开销时钟(5只是一种可能性,它可以通过设计和并行的其他方式来改变).N取决于较慢的内存速度.对于dram来说,n非常大,所以缓存l2和L1要快得多,这就是为什么缓存完全可以减少每个dram访问的大量时钟周期,有效与否.


War*_*Dew 6

指令高速缓存将包括从存储器中提取的高速缓存行以执行。数据高速缓存将包括从内存中提取的高速缓存行,以作为数据加载到寄存器中。

  • 你能举个例子吗?例如`LDR R1, =myVar` 那么LDR 会进入指令缓存,而myVar 的内容会进入数据缓存吗? (2认同)
  • @Celeritas指令缓存不缓存操作码,而是缓存特定指令。缓存指令在循环(重复执行同一代码)中特别有用,但是即使没有循环,也可以从不同位置调用函数,从而可以重复使用代码。缓存还有助于预取和利用空间局部性。 (2认同)
  • @Celeritas我的意思是,使用Icache而不是总是获取[等待内存] /解码/执行处理器,而是因为代码是最近执行的(循环或循环),所以处理器更经常获取[cache hit] / decode / execute。最近一次函数调用),或者由于缓存中的数据块被“预取”(因为x86实现通常使用64B缓存块)。 (2认同)
  • @Celeritas 我明白你在说什么,尽管我实际上只是说指令是从内存中获取的。也许您的另一个问题的答案是这样的:指令和数据都存储在内存中;在具有独立指令和数据高速缓存的处理器上,指令从内存提取到指令高速缓存,而数据从内存提取到数据高速缓存。 (2认同)

aus*_*len 5

指令高速缓存只是更快地访问指令的另一级内存。它不是CPU发条/内部部件/获取-解码-执行逻辑的一部分——无论你如何命名它。

当一条指令被缓存时,他们的意思是,它非常接近CPU内存级别,因此当CPU需要加载地址X处的指令时,与其他地址Y相比,它的速度非常快。

CPU 内部不缓存指令。

指令和数据有不同的访问模式有人可以详细说明吗?

例如,更新(覆盖)指令是不被允许的,而且这种情况并不常见。因此,如果您为指令设计缓存,则可以针对读取进行优化。而且指令是顺序的,所以如果CPU访问N处的指令,它很可能也会访问N+1处的指令。然而,这两个属性对于数据缓存来说并不那么重要,或者数据缓存必须更加详细。