ARM ARM实际上并没有以正确的方式给出这条指令的正确用法,但我发现它在其他地方被用来知道它接受一个地址作为在哪里读取下一个值的提示。
我的问题是,给定一个256字节的ldm/stm指令的紧密复制循环,比如r4-r11 x 8,在复制之前,在每个指令对之间预取每个高速缓存线是更好,还是根本不这样做,因为所讨论的memcpy不是同时读取和写入相同的内存区域。我非常确定我的缓存线大小是64字节,但它可能是32字节-在这里编写最终代码之前等待确认。
发布于 2011-06-21 00:52:40
来自Cortex-A Series Programmer's Guide的第17.4章(注意:ARM11的一些细节可能有所不同):
memcpy()的最佳性能是使用整个缓存线的
,然后用整个缓存线的STM写入这些值。存储的对齐比负载的对齐更重要。在可能的情况下应使用PLD指令。在加载/存储单元中有四个PLD槽。PLD指令优先于自动预取器,并且在整数流水线性能方面没有成本。用于最佳memcpy()的PLD指令的确切时序在不同系统之间可能略有不同,但是PLD到当前复制行之前三个高速缓存线的地址是一个有用的起点。
发布于 2011-06-21 21:35:00
在Linux内核arch/arm/lib/copy_page.S中可以找到使用高速缓存行大小的LDM/STM块和/或PLD的合理通用复制循环的示例。这实现了Igor上面提到的关于预加载的使用,并说明了阻塞。
请注意,在ARMv7 (缓存行大小通常为64字节)上,不可能将整个缓存行作为单个操作进行LDM (只有14个regs可以使用,因为不能使用SP/PC )。因此,您可能需要使用两对/四对LDM/STM。
发布于 2013-07-06 06:10:33
要真正获得尽可能“快”的ARM asm代码,您需要在系统上测试不同的方法。就ldm/stm循环而言,这个循环似乎最适合我:
// Use non-conflicting register r12 to avoid waiting for r6 in pld
pld [r6, #0]
add r12, r6, #32
1:
ldm r6!, {r0, r1, r2, r3, r4, r5, r8, r9}
pld [r12, #32]
stm r10!, {r0, r1, r2, r3, r4, r5, r8, r9}
subs r11, r11, #16
ldm r6!, {r0, r1, r2, r3, r4, r5, r8, r9}
pld [r12, #64]
stm r10!, {r0, r1, r2, r3, r4, r5, r8, r9}
add r12, r6, #32
bne 1b上面的代码块假设您已经设置了r6、r10、r11,并且此循环按字而不是字节的r11术语进行倒计时。我已经在Cortex-A9 (iPad2)上测试过了,它似乎在那个处理器上有相当好的结果。但要小心,因为在Cortex-A8 (iPhone4)上,霓虹灯循环似乎比ldm/stm更快,至少对于较大的副本是这样。
https://stackoverflow.com/questions/6414555
复制相似问题