【餵到嘴邊了的模塊】不服?跑個分看看!——Coremark篇

嵌入式小美老師 發佈 2024-03-01T04:38:00.328897+00:00

Coremark包含了一系列算法:列表操作、常用的矩陣運算、狀態機以及CRC——這樣做的目的據說是為了克服Dhrystone過於依賴libc庫的缺點。

【說在前面的話】


在計算機領域,很多無意義的論戰都會在「不服跑個分看看」的叫囂中進入下一個階段:從原本Battle的議題轉移為對跑分軟體(Benchmark)嚴謹性和合法性的爭論上——隨著某些跑分軟體陳芝麻爛穀子的黑料重見天日,群里論戰的熱情達到了最高潮……

這類盛況在PC和手機領域頗為常見。那麼有的小夥伴會問了,在枯燥的MCU生態里,有沒這樣一個往群里大叫一聲「不服?跑個分看看」,然後搬個小板凳躲在角落裡吃瓜的機會呢?

哎!還真有。這就是大名鼎鼎的Coremark。根據EEMBC的說法:

CoreMark is a simple, yet sophisticated benchmark that is designed specifically to test the functionality of a processor core. Running coremark produces a single-number score allowing users to make quick comparisons between processors.

https://www.eembc.org/coremark/

簡單來說,Coremark是一個專門測量嵌入式MCU(或者CPU)性能的跑分軟體,用來替代已經過時且充滿爭議的Dhrystone跑分。Coremark包含了一系列算法:列表操作(查找和排序)、常用的矩陣運算、狀態機以及CRC——這樣做的目的據說是為了克服Dhrystone過於依賴libc庫的缺點。官方甚至專門在網頁上開闢了一個段落,細數Coremark相對Dhrysone做了哪些改進,感興趣的小夥伴可以點擊去看一看:

https://www.eembc.org/coremark/

這裡記住結論就行:Dhrystone低級、過時、踩一腳;Coremark高級拉一把!

嵌入式物聯網需要學的東西真的非常多,千萬不要學錯了路線和內容,導致工資要不上去!

無償分享大家一個資料包,差不多150多G。裡面學習內容、面經、項目都比較新也比較全!某魚上買估計至少要好幾十。

點擊這裡找小助理0元領取:加微信領取資料

【部署CoreMark從未這麼簡單】


雖然Coremark的原始碼在Github上可以直接下載,但拿回家後還需要針對你的目標處理器進行一番移植。總的來說,移植需要解決兩類問題:

    • 提供對printf的重映射支持
    • 提供一個足夠精準的時間測量手段

哎,巧了不是。如果你使用的是Cortex-M處理器,並且習慣了在MDK環境下耕耘,只要藉助 perf_counter 的幫助,在RTE里簡單的勾選幾下就可以迅速的在任意Cortex-M處理器中部署 Coremark。

首先,關於MDK下實現通用的printf功能,請參考文章《【震驚!】MDK下99%用戶都不知道的萬能printf方法》,這裡就不再贅述。

從 v2.0.0開始 perf_counter 內置了 Coremark,並針對Cortex-M處理器完成了幾乎所有的移植工作,這意味著你只需要在RTE中勾選對應的模塊,即可完成對Coremark的部署(如下圖所示):

如果你已經通過往期文章《【餵到嘴邊了的模塊】超級嵌入式系統「性能/時間」工具箱》熟悉過perf_counter的使用,那麼接下來只要在超級循環里加入如下的代碼就大功告成了:

#include "perf_counter.h"


int main(void)
{
    
    printf("Coremark 1.0\r\n");
    
    coremark_main();
    
    while(1) {


    }
    
}

對應的運行效果如下(這裡以Cortex-M55 r0p0為例,r0p1跑分會更高一些):

可以看到,這裡的跑分結果是 4.367429

如果你之前從未用過 perf_counter,則推薦通過文章《【餵到嘴邊了的模塊】超級嵌入式系統「性能/時間」工具箱》來了解詳細的部署和使用方式。這裡就不再贅述。

值得特別強調的是,perf_counter 已經加入 KEIL的官方索引列表,因此小夥伴可以直接從 Pack Installer 中找並安裝它的最新版本:

如果你的網絡不太好,無法通過Pack Installer直接安裝,也可以在關注公眾號【裸機思維】後向後台發送關鍵字 perf_counter 來獲取網盤連結


【常見問題】


Coremark雖然簡單直接,但在使用上仍然存在一些注意事項:

  • Coremark跑分的制約因素

一般來說,Coremark的結果肯定會受到以下幾個因素的影響:

1. 優化等級

不要奢望 -O0 能跑出多高的結果。但如果你的項目從來都只用 -O0 那麼跑Coremark時也一定要用 -O0 ——因為這反應了你使用時候的真實狀況。

很多晶片公司和Arm一樣都會用最好的編譯器在最高的速度優化下跑Coremark,這意味著,我們通常可以在 Arm Compiler 6下使用 -Omax跑出當前硬體平台的最佳結果。

很多小夥伴可能不知道如何在 MDK 環境下使用 -Omax,因為Optimisation 下拉列表中根本沒有 -Omax-Omax 是一個比 -Ofast要更上一個台階的優化等級(用過都說好),可以說是MDK的一個隱藏技巧:

  • 請在 Msc Controls 中直接添加 -Omax,同時
  • 勾選 Link-Time-Optmisation

需要強調的是,一旦在 Misc Controls 文本框中添加了 -Omax,無論你在 Optimization 下拉列表中選擇了哪個優化等級,都會被 -Omax 覆蓋掉。為了避免誤導後來人,推薦在這種情況下在該列表中選擇<default>


2. 程序存儲器的速度以及RAM的訪問速度

其實用腳指頭想也知道:Coremark的跑分會受到存儲器訪問速度的影響。很多大公司會將程序保存在 0 wait state 的 RAM中來跑 Coremark,以求獲得最佳的結果。

我猜很多小夥伴看到這裡可能就炸了:我們平時都是在Flash里跑代碼,你拿RAM跑出來的數據糊弄我?這不是欺負老實人麼?

實際並非如此,原因如下:

1)對很多大公司來說,他要給客戶提供理想狀況下所能達到的最高評分,方便用戶選型的時候了解晶片的能力上限(如果上限都達不到就別勉強了)

2)很多晶片會專門提供用於運行代碼的 PRAMSRAM或者 TCM(Tightly Couple Memory),因此,只要合理安排程序的存儲器布局,在核心應用和算法上,的確可以跑出官方給出的最大性能

從另外一個角度來說,以Cortex-M處理器為例,通過Coremark,對比Arm提供的最高跑分,我們可以很容易的評估當前晶片的 Flash速度是否拖累了處理器——從跑分的差異上判斷拖累的程度。比如,很多時候,使用片內Flash跑 CoremarkXIPQSPI)連接的片外FlashCoremark 可以看出巨大的跑分差異,給了我們一個定量判斷性能損失的參考手段——注意,只是參考,不是絕對的。

此外,RAM的速度也會對Coremark產生很大的影響,簡單來說,0 wait stateRAM1~2wait stateRAM以及 SDRAMCoremark的結果是截然不同的——這同樣給了我們一個直觀感受不同RAM性能差異的參考手段。

3. 是否存在cache

有沒有Cache,有多大的cache,以及cache覆蓋ROM還是RAMCoremark結果的影響是巨大的。比如,哪怕你用 XIP 來跑 Coremark(或者用SDRAM來存儲數據),只要你Cache到位,其跑分幾乎和理想狀況相差無幾。

以上內容用腳趾都能想出來。接下來給大家說一個由cache引起的反直覺的現象:

前面我們說過,如果你想跑出最佳的跑分,就應該使用編譯器的最高性能優化,對Cortex-MArm Compiler 6來說就是 -Omax + Link Time Optimisation

有些晶片雖然為Flash提供了一個專門的Cache,但由於其尺寸有限(通常是為了降低功耗或者晶片面積),會出現 -Omax + Link Time Optimisation優化下跑分反而不如 -Oz 或者 -Os 的情況。

首先這不是編譯器的BUG,也不是你忘記給電腦開光導致來了髒東西。原因其實很簡單:很多編譯器在面向性能優化的時候會進行瘋狂的循環展開,這會導致原本小巧的循環體突然體積暴漲——如果循環展開後的體積超過了cache所能容忍的程度,就會在這個關鍵的循環中頻繁出現 cache miss——相當於處理器是直接從Flash上讀取代碼。相反,在 -Oz-Os 通常不會進行此類循環展開,因此在執行循環熱點時,0 wait statecache發揮了高速緩存應有的作用,與直接在Flash上讀取代碼相比,極大的提高了程序的運行速度。

這裡的關鍵其實是 cache 的大小以及循環展開後的體積。一般來說,大家常用的一線廠商晶片其 Flash Cache尺寸還是很得體的,一般不會出現上述情況,可以放心食用。

  • Coremark必須跑夠10秒以上

這是Coremark為了跑出有效跑分而在算法中做出的硬性規定,如果你的晶片頻率過高,則很可能會出現類似如下的提示:

ERROR! Must execute for at least 10 secs for a valid result.

觀察 Total time (secs)可以知道Coremark實際運行了多少秒。

要解決這一問題也很簡單:直接在工程中定義宏 ITERATIONS,並給出一個較大的值即可,比如3000:

重新編譯,調試:

  • Coremark的結果處理

細心的小夥伴可能會發現一個現象,在很多新聞報導中,某些晶片廠商會聲稱自己的晶片Coremark跑分高達幾千分,為什麼我們這裡所展示的Coremark跑分只有個位數呢?

其實二者都沒錯,幾千分的那個結果是將晶片的頻率考慮在內,而這裡個位數的跑分是以1MHz作為參考——也就是所謂的 「每兆赫茲 Coremark」——顯然,將結果換算成 1MHz 為單位的結果更為直觀,也方便大家將不同頻率的晶片拿到一起作比較,因此 perf_counter 在移植 Coremark 時也選擇以 每MHz Coremark作為結果輸出的標準格式。

【說在後面的話】



Battle千萬條,拉踩第一條;跑分不規範,親人兩行淚。

感謝大家對 perf_counter 的支持。如果你喜歡我的作品,不妨獻上您寶貴的一個 Star:

https://github.com/GorgonMeducer/perf_counter




轉載自:裸機思維

文章來源於【餵到嘴邊了的模塊】不服?跑個分看看!——Coremark篇

原文連結:https://mp.weixin.qq.com/s/DM-U2YFpg_Aid1x7TqIAvw

關鍵字: