簡體   English   中英

為什么使用指針(優化程度較低)會使程序更快?

[英]Why using pointers (with low optimization) makes the program faster?

我遵循了有關嵌入式C編程的教程,然后意識到使用指針指向變量,然后使用它取消引用可以使程序更快!

我具有匯編的基本知識,但是我沒有弄清楚為什么將變量的地址分配給指針會更快,我們不是在談論按引用,按指針或按值傳遞!

據我所知,

  • 不帶指針的代碼:內存地址已分配給寄存器R0 ,就像帶指針的代碼中發生的情況一樣。
  • p_int成為寄存器R0的別名,這如何有助於使程序更快?

不使用指針的代碼:

int counter = 0;
int main() {
    while (counter < 6) {
        ++(counter);
    }
    return 0;
}

那么組裝就像 在此處輸入圖片說明

相反,這是帶有指針的代碼:

int counter = 0;
int main() {
    int *p;
    p = &counter;
    while (*p < 6) {
        ++(*p);
    }
    return 0;
}

那么組裝就像 在此處輸入圖片說明


更新資料

我與課程創建者聯系,他很樂意為我重播和分解該課程,為了幫助可能遇到相同問題的其他人,我將保留問題和答案

要訪問存儲器中的變量,CPU需要該變量在寄存器之一中的地址。 在代碼優化的最低級別,編譯器在每次訪問變量之前都會從代碼存儲器中加載此地址。 指針加快了速度,因為它是main()函數內部的局部變量,被分配給一個寄存器。 這意味着該地址位於一個寄存器中(在這種情況下為R0),不需要每次都加載並重新加載到寄存器中。 在更高的優化級別上,編譯器生成的代碼更明智,並且沒有指針的代碼與使用指針的代碼一樣快。 -彩信

通常:沒有理由使用指針會使程序運行更快。 與課程創建者在您的報價中所做的一樣,討論未啟用所有優化的程序的性能是沒有意義的。 當然,這不是更改代碼編寫方式的原因。

另一個古老的,經常使用但過時的技巧是編寫諸如遞減計數而不是遞增計數的循環,因為與零的比較通常比與值的比較更快。 但這也不應該影響編寫代碼的方式,因為現代的編譯器可以為您進行優化。

程序員應該做什么,以及編寫課程的人們應該教什么,就是編寫盡可能簡單易懂的代碼。 這意味着您的兩個示例都是不好的,因為它們不必要地晦澀難懂,並帶有“過早優化”的示例。 更好的代碼是:

  int counter;
  ...
  for(counter=0; counter < 6; counter++)
  {}

這與代碼獲得的可讀性差不多,沒有理由相信上面的代碼在任何已知系統上的性能都將比您的示例差。

做這個:

  • 編寫盡可能可讀的代碼。
  • 在發行版中,啟用優化。
  • 如果存在性能問題,請進行基准測試並找到瓶頸。
  • 如果需要,手動優化瓶頸。 可能考慮到特定的系統。

編譯器在優化級別之間變化的任何行為都是特定實現的 因此,盡管已經向您展示了一些可能與直覺相反的演示,但您不應該被教導這是因果關系。

以不同的方式編寫代碼總是可以觸發性能改進或性能下降,並且不同的優化級別有時可能導致更改以錯誤的方式進行。 這是顯而易見的,但是任何將較高的優化級別導致較差的性能(在本示例中不是這種情況)的情況都應視為編譯器的問題。

原始更新提供了一個很好的答案。 此外,在最初,“計數器”是一個全局變量,因此對ARM芯片的每次訪問都需要先將變量加載到寄存器中。 根據變量的位置和優化級別,這至少是一條LDR指令(可能更多),然后更新計數器++要求添加指令和寫回全局變量。

如果將計數器聲明為局部變量,那么實際上使用指針版本將不是最佳選擇。 在這種情況下,大多數編譯器會將計數器分配到寄存器中,然后對其進行訪問將非常快。 如果使用了指針,則將強制將計數器分配給堆棧(因為其地址已分配給“ p”),並且將需要更多指令來進行添加和訪問。

它正好相反(幾乎相同,但還有一條指令:):

https://godbolt.org/z/xDYecQ

在此處輸入圖片說明

暫無
暫無

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

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