我正在观察一些不正确的事情。
我发现我可以使用
写入ARM上的主内存 stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10}
比使用
从主存储器(SDRAM)读取的速度快约6倍 ldmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10}
所以,如果我将血红蛋白替换为stmia并将r0指向分配的记忆,那么如果我计时,那么血症会快6倍。
ARM的stmia指令有什么特别之处可能导致假阳性吗?也许stmia与缓存交互奇怪?
总的来说,我已经看到ARM的写入速度比从主内存中读取的速度快,但从硬件的角度来看,速度提高6倍是没有意义的。
更新: 这种情况发生在大块内存中,可能比L2缓存大。
因此,缓存说明没有充分的意义。即使ARM有一个写回L2缓存需要永远回写,它也不会比我分配的内存区域大。
感谢。
答案 0 :(得分:3)
您没有指定您的平台和环境,但我怀疑您正在看到缓存的影响。执行加载时,首先检查缓存,如果数据不存在(缓存未命中),则CPU必须等到实际从主内存中取出,这比缓存慢很多。另一方面,商店可以将数据转储到缓存中并继续前进,依靠缓存控制器来执行实际的内存写入而无需CPU的参与。
要确定是否属于这种情况,您可以尝试各种测试模式,例如:
等等。要阅读有关ARM处理器中缓存的更多信息,我建议您阅读Cortex-A Series Programmer's Guide。即使您的处理器不是Cortex-A,它也会很有用,因为大多数概念也适用于老一代。
答案 1 :(得分:1)
以下是一些示例代码:
.globl _start
_start:
ldr r11,=0xD6800600
mov r1,#0
str r1,[r11,#0x08] ;@ stop timer
mvn r1,#0
str r1,[r11,#0x00] ;@ timer load register
mov r1,#3
str r1,[r11,#0x08] ;@ start timer, 1 x prescaler
mov r3,#3
mov r4,#4
mov r5,#5
mov r6,#6
mov r7,#7
mov r8,#8
mov r9,#9
mov r10,#10
ldr r0,=0xD6001000
mov r12,#0x400
ldr r13,[r11,#0x04]
write_loop:
stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10}
subs r12,#1
bne write_loop
ldr r1,[r11,#0x04]
ldr r0,=0xD6001000
mov r12,#0x400
ldr r2,[r11,#0x04]
read_loop:
ldmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10}
subs r12,#1
bne read_loop
ldr r14,[r11,#0x04]
mov r0,r13
mov r3,r14
ldr sp,=0xD600E000
bl notmain
hang: b hang
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
外设基数为0xD6800000。使用on-core计时器。这是一个带有64位AXI总线的mpcore r2p0(rev 2.0)。您可能会发现写入比读取慢3倍。打印出时间并减去写入是0x191F5刻度并读取0x81F7。
但我知道原因。这个存储器控制器可以/确实将stm转换成4个双字写周期(你在AXI总线上看到的)。我认为读取是单个8字(4个双字)传输,因此写入的总线开销是4倍。每次写入的开销加一个时钟,每次读取都是开销加8个时钟来突发数据。
我添加了代码以验证缓存是否已关闭。并添加了nops,一次一个nop来调整内存中指令的对齐(仍然可以影响提取和片上内存的实现)。例如,在每个循环之前,在读取计时器之前放置nops。通过操纵内存中循环的位置,读取循环最敏感,我可以将结果改为50%。它不是0x8xxx范围,而是在一个敏感点发送到0xAxxx,在另一个敏感点发送到0x6xxx时钟。我不打算深入研究这个问题,ram本身可能会产生一些影响,以及作为一个ARM11的影响,其中有一些平滑来自获取,以及可能未对齐的读取被平滑为更少的对齐读取等。
我建议你这样做,关闭缓存,关闭mmu,关闭奇偶校验或ecc生成/检查。拧紧循环,循环外部的时间。在测试代码前面一次放置一个nops,一次一个,可能多达8或16或32,如果有变化,模式应该在一些逻辑边界上重复,如4,8或16个字。此外,如果你的计时器给你一个不同的数字(没有重新编译)运行后运行,你有中断或类似的事情会弄乱你的数字。像我想象的那样的处理器核心时钟甚至会改变一个时钟,当然取决于你的内存系统。嗯,因为你正在做8个字的指令,试着把起始地址改为0,4,8和12.还试着打开指令缓存(不需要mmu)。我怀疑你也会看到性能数字跳跃。
还有其他一些ARM我可以试试......不是芯片我有尽可能多的内部知识......
你在跑什么家庭/核心?你可以发布测试代码吗?你的测试循环是否与我上面的相似?
答案 2 :(得分:0)
@dwelch 我认为你对NOP提出了一个有趣的观点,但是已经证明代码在读取时可以非常快地运行---只要它访问缓存而不是主内存。速率约为5000MB / s。而写作速度为6000MB / s。所以NOP并没有真正解释为什么写入主内存比从主内存中读取要快得多。
答案 3 :(得分:0)
您观察到的是ARM写入缓冲区的影响。写缓冲区位于CPU和高速缓存或RAM之间。它旨在防止CPU在执行少量写操作时等待内存。典型的写缓冲区可以处理4个唯一的地址,每个地址有2个字,用于存放您在上面的示例中编写的寄存器。如果您创建一个带有8个寄存器的stmia循环,您将开始看到它可以写入的真实速度。没有合并的地址,所以如果你写4个字节,那也将填充写缓冲区。