我最近使用了一個板(LPCXpresso 5411x)做一些計算,我們試圖減少週期,只要我們能夠節省我們的特定需求的運行時間,所以我需要對cortex-m4指令的成本週期進行一些研究。我發現很多奇怪的東西(不能用我在互聯網上找到的東西解釋)用手臂皮質m4週期計數奇怪的東西
我用DWT-> CYCCNT來計算我想測試的函數所消耗的週期數。
int start_cycle, end_cycle;
__asm volatile (
"LDR %[s1], [%[a]], #0\n\t"
:[s1] "=&r"(start_cycle): [a] "r"(&(DWT->CYCCNT)):);
AddrSumTest();
__asm volatile (
"LDR %[s1], [%[a]], #0\n\t"
:[s1] "=&r"(end_cycle): [a] "r"(&(DWT->CYCCNT)):);
printf("inside the func() cycles: %d\n",end_cycle - start_cycle);
這裏是我的功能是如何定義的:
__attribute__((always_inline)) static inline void AddrSumTest(){
uint32_t x, y, i, q;
__asm volatile (
"nop\n\t"
:[x] "=r" (x), [y] "=r" (y), [i] "=r" (i), [q] "=r" (q):);
}
}
- 據Arm Infocenter,指令MOV應該花費一個週期,但我發現,
以下指令需要8個週期(不是3個,因爲需要額外的週期來讀取DWT-> CYCC NT)
"nop\n\t"
"MOV %[x], #2\n\t"
"nop\n\t"
添加另一MOV指令之後,需要10個循環以下循環(爲什麼不9個週期)
"nop\n\t"
"MOV %[x], #2\n\t"
"MOV %[y], #3\n\t"
"nop\n\t"
和組裝編碼後一種情況是
4000578: f853 4b00 ldr.w r4, [r3], #0
400057c: bf00 nop
400057e: f04f 0502 mov.w r5, #2
4000582: f04f 0603 mov.w r6, #3
4000586: bf00 nop
4000588: f853 1b00 ldr.w r1, [r3], #0
400058c: 4805 ldr r0, [pc, #20] ;(40005a4<test_AddrSum+0x30>)
400058e: 1b09 subs r1, r1, r4
4000590: f000 f80e bl 40005b0 <__printf_veneer>
這兩個ldrs正在從DWT-> CYCCNT讀取,另外,爲什麼這會花費10個週期,我估計是2(來自ldr)+ 4 = 6
順便說一句,板沒有任何緩存,並且我將代碼存儲在sramx中,並且堆棧在sram2中。
我錯過了什麼,它有什麼辦法可以弄清楚每個週期如何消耗?此外,我也對cortex-m4的數據依賴性感到困惑。
如果沒有任何緩存,您可能不得不爲循環獲取指令提取額外的費用。另請注意,您計算的週期時間只包含讀取DWT-> CYCCNT的兩條LDR指令之一,而不是兩條指令。推測它們在執行兩條指令時(例如在開始時)在相同的相對點處讀取循環計數。要包含這兩者,循環次數必須在第一個LDR指令開始時和第二個LDR指令結束時。 –
我同意你的意見,但你的意思是每個指令fetche的週期額外成本 –
每個指令獲取,但我不知道如何Cortex-M4指令提取。例如,它可能會在每個提取中獲取32位字,因此並非每條指令都會支付它。 –