簡體   English   中英

在為ARM7編譯的C代碼中,使用全局變量是增加還是降低性能?

[英]Does using global variables increase or decrease performance, in C code compiled for ARM7?

在為ARM7嵌入式平台編譯時,在C代碼中使用大量全局變量是否會降低或提高性能?

代碼庫由多個C源代碼文件組成,這些文件使用extern關鍵字引用彼此的全局變量。 來自不同源代碼文件的不同函數指的是不同的全局變量。 一些變量是數組。

我正在使用的編譯器是IAR的EW ARM kickstart版本(32kb)。

你可能擔心一些對你來說不是真正問題的事情......

從理論上或挑剔的角度來看,訪問全局變量需要某種重定向(如PIC的GOT),因此訪問速度較慢

當您在本地范圍內訪問變量時,您隱式使用本地引用(如堆棧指針或放置在寄存器中的值),因此訪問它們的速度更快

例如:

extern int x;

int foo(int a, int b, int c, int d, int e) {
  return x + b + e;
}

編譯成

foo(int, int, int, int, int):
    movw    r3, #:lower16:x
    movt    r3, #:upper16:x
    ldr     r3, [r3, #0]
    adds    r0, r1, r3
    ldr     r3, [sp, #0]
    adds    r0, r0, r3
    bx      lr

你可以看到訪問br1 )或eldr r3, [sp, #0] )與訪問xmovw r3, #:lower16:x; movt r3, #:upper16:x; ldr r0, [r3, #0] )。

好吧,使用全局變量不會直接影響CPU性能。 堆棧分配通常分別在函數入口/出口處單個加或減。

但是,堆棧的大小非常有限。 在堆上使用動態分配通常是解決方案。 在嵌入式系統中,這可能是一個問題,因為分配或釋放動態內存可能需要多長時間。

如果分配和釋放堆是系統的問題,全局變量可以緩解分配/自由執行時間的問題。

我不建議將此作為您的第一個解決方案 - 特別是如果此應用程序涉及線程。 可能很難追蹤哪些線程/函數正在修改全局變量,從而導致未來的麻煩。 static變量在技術上與全局變量(“全局和靜態數據”)位於同一位置,因此您可能需要首先考慮此選項。

任何性能優勢或其他方面完全取決於訪問模式和使用,因此無法在不查看代碼的情況下在單個情況下進行說明。 無論使用全局變量,代碼都可能是高效的或低效的。

如果通過使數據成為全局數據,例如,您可以避免對訪問器函數的函數調用,並且此類訪問是頻繁的,那么避免函數調用開銷可能具有可測量的性能優勢。 但僅僅是全局本身並沒有任何優勢 - 它關於訪問方法和生成的指令數量(或等待狀態,如果內存訪問比處理器慢 - 例如片外存儲器 - 但是適用於任何數據,全球或其他)。

以您描述的方式使用全局變量通常表示設計不佳和/或開發人員經驗不足,並且可能存在代碼區域對性能的影響遠大於僅僅是數據訪問的位置。

最終,使用全球數據來獲得一些感知到的性能優勢是錯誤的。 在大多數情況下,性能應該是實現所需的實時期限或數據吞吐量,而不是盡可能快 ; 如果您的處理器最終空閑時間達到90%,那么您所獲得的就是更多時間無所事事。

我懷疑你的代碼庫更多地使用了糟糕的設計或工藝,而不是任何故意的性能問題。 具有顯式內聯或編譯器優化的訪問函數的封裝靜態數據可能具有類似的性能,同時更易於維護且更易於調試 - 這些優勢可能遠遠超過性能問題。 問問自己,是否最好節省一毫秒的CPU時間或一個月的開發時間,或者更糟糕的是產品召回和客戶流失,因為您的產品在現場出現故障。

static變量相比,這將始終降低性能並增加程序大小。 你的問題沒有具體問你要比較什么 我可以看到各種替代品,

  1. 與靜態變量相對應。
  2. 與值一起傳遞的參數。
  3. 與傳遞的數組或結構指針中的值相對應。

ARM博客提供了有關如何將常量加載到arm寄存器的詳細信息。 必須始終執行此步驟以獲取全局變量的地址。 編譯器不會知道事先有多遠。 如果你使用帶有-lto gcc或使用類似整個程序的東西,那么可以執行更好的優化。 基本上,這些將把全局轉變為靜態

這里編譯器可以保存具有全局基地址的寄存器,然后使用偏移量加載不同的變量; 例如ldr rN, [rX, #offset] 也就是說,如果你很幸運。

RISC CPU的設計(如ARM)支持處理所有內存訪問的加載/存儲單元。 通常,加載/存儲指令能夠具有[register + offset]形式。 此外,所有RISC寄存器都是近似對稱的。 這意味着任何寄存器都可用於此偏移訪問。 通常,如果將struct或數組指針作為參數傳遞,那么它就變成了同樣的東西。 即, ldr rN, [rX, #offset]

現在,參數的優點是最終,您的例程可以通過傳遞不同的指針來支持多個數組結構 此外,它還為您提供了將通用數據組合在一起的優勢,從而提供了緩存優勢。

我認為全局變量對ARM是有害的。 你應該只使用全局指針 ,你的代碼需要一個單例 或者你有某種同步記憶。 即,全局變量應僅用於全局功能而不用於數據。

通過堆棧傳遞所有值顯然是無效的,並且錯過了內存引用或指針的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM