1. 程式人生 > >連載:編寫高效程式碼(11) 儘量減少分支

連載:編寫高效程式碼(11) 儘量減少分支

         我們在介紹處理器時,已經知道了,現在的處理器都是流水線結構,if和switch等語句會帶來跳轉,而跳轉會打亂流水線的正常執行,影響程式的執行效率。

         下面這段程式碼,把奇數賦一個值,把偶數賦一個值,可以用這種方式實現:

for(i=0; i<100; i++)

{

   if(i%2 == 0)

   {

       a[i] = x;

   }

   else

   {

       a[i] = y;

   }

}

如果改成如下這種形式就更好了:

for(i=0; i<100; i+=2)

{

   a[i] = x;

   a[i+1] = y;

}


  將最可能進入的分支放在 if中,而不是else中

         Intel處理器有分支預測單元,第一次進入一個分支時,由於沒有歷史資訊可供參考,是否跳轉取決於Static Predictor(靜態預測器)的預測策略,通常Static Predictor的策略是:向下跳轉預測為不跳轉,向上跳轉預測為跳轉。根據這個特性,我們在寫if else語句時,也要注意。且看下面這段程式碼是否合適?

int a = -5;

int b = 0;

if (a > 0)

{

   b = 1;

}

else

{

   b = 2;

}

我們來看看組合語言:

4:        int a = -5;

00401028   mov         dword ptr [ebp-4],0FFFFFFFBh

5:        int b = 0;

0040102F   mov         dword ptr [ebp-8],0

6:        if (a > 0)

00401036   cmp         dword ptr [ebp-4],0

0040103A   jle         main+35h (00401045)

7:        {

8:            b = 1;

0040103C   mov         dword ptr [ebp-8],1

9:        }

10:       else

00401043   jmp         main+3Ch (0040104c)

11:       {

12:           b = 2;

00401045   mov         dword ptr [ebp-8],2

13:       }
       讀者沒必要管這麼一大串組合語言是什麼意思,只需要知道jle是個條件跳轉指令就可以了,它跳到地址00401045處,是向下跳,根據Static Predictor的策略,它被預測為不跳轉,處理器會從0040103C地址處開始取下一條指令。再看看實際的執行情況,a<0,執行else這個分支,於是處理器發現取錯了地址,又要從頭來過,白白浪費了大量時間。可見,執行概率高的分支,應該放在if分支中。

相關推薦

連載編寫高效程式碼(11) 儘量減少分支

         我們在介紹處理器時,已經知道了,現在的處理器都是流水線結構,if和switch等語句會帶來跳轉,而跳轉會打亂流水線的正常執行,影響程式的執行效率。          下面這段程式碼,把奇數賦一個值,把偶數賦一個值,可以用這種方式實現: for(i=0; i

連載編寫高效程式碼(8) 空間換時間——我們總是在走,卻忘了停留

         時間和空間的關係,是霍金這種智商的人要研究的東西,我們只需要知道,在程式設計時,空間是可以換時間的,時間也是可以換空間的。          李開復在他的自傳《世界因你不同》中描述了他小時候在美國學校裡的一個故事,老師出了道題:“誰知道1/7等於多少?”小

C++編寫高效率程式碼

概述: C++相比其他高階語言效率高的多,也有許多程式使用C++作為核心以提高程式的效能瓶頸,一個太大太慢的程式他們的優點無論有多麼引人注目都不會為人們所接受,儘管有一些程式的確是為了複雜的運算才佔用更多的時間和空間,但是更多的程式只能歸咎於糟糕的設計和馬虎的程式設計。想用C++寫出高效的程式碼之前,必須認

程式設計題編寫一個程式碼,將“i am from shanghai”倒置為“shanghai from am i”

題目要求:編寫一個程式碼,將“i am from shanghai”倒置為“shanghai from am i”,即將句子中單詞的位置調換,                    但不改變單詞內部的順序 #include <stdio.h> #include

編寫程式碼如何減少程式碼的認知負荷

Bug 少,效能好,容易修改。好的程式碼影響深遠,而且它可能是產生 10 倍工作效率的開發者的主要原因。儘管好程式碼十分重要,但開發新手卻不得要領。關於這一主題的技巧多而冗雜,讓新手們如何記得住?“《程式碼大全》)” 是這個主題的經典,但內容多達 960 頁! 我認

C++編寫異常安全程式碼

在C++的使用當中,最令人頭疼的地方莫非是記憶體管理或者異常的使用。 想寫出一個真正異常安全的程式碼是非常難得,需要考慮的因素有非常多。 在現代C++當中也有很多人提倡不使用異常,但是要完全杜絕使用C++異常 也是很難的,除非打算不使用任何一個標準庫,重寫所有需要用的資料結構演算法等等。 在一般情況下

程式碼優化案例 減少重複編寫 通過v-if 一個狀態的判斷完成

在出現大部分內容都相同的情況下 這個時候 就需要檢視是否有優化的可能, 如一下情況: IdentifySuccessful(item){ this.dialogTableVisible = true this.

記錄CCS6將編寫DSP程式碼燒入28335晶片中遇到的一些問題

    1.首先配置好targetConfigs檔案     2.編譯過程中預設選擇release,若想選擇debug,需要在include>common.h 中,取消註釋#define DEBUG_MODE ,如圖:    3.  在編譯之前,要確保預設.

第3章Maven使用入門/3.3 編寫測試程式碼

編寫測試程式碼 在約定src/test/java下新建測試程式碼類 `package com.wys.myapp.helloworld; import org.junit.Test;import static org.junit.Assert.*;

Python 工匠編寫條件分支程式碼的技巧

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~ 本文由鵝廠優文發表於雲+社群專欄 作者:朱雷 | 騰訊IEG高階工程師 『Python 工匠』是什麼? 我一直覺得程式設計某種意義是一門『手藝』,因為優雅而高效的程式碼,就如同完美的手工藝品一樣讓人賞心悅目。 在雕琢程式碼的過程中,有大工程:比如

如何編寫高效的Android程式碼

現代的手持裝置,與其說是電話,更像一臺拿在手中的電腦。但是,即使是“最快”的手持裝置,其效能也趕不上一臺普通的臺式電腦。 這就是為什麼我們在書寫Android應用程式的時候要格外關注效率。這些裝置並沒有那麼快,並且受電池電量的制約。這意味著,裝置沒有更多的能力,我們必須把程式寫的儘量有效。

【解決】自己編寫Wordcount程式碼上傳叢集上執行時報錯Exception in thread "main" java.lang.ClassNotFoundException: WordCount

報錯資訊:ClassNotFoundException: WordCount [[email protected] fs_testdir]# hadoop jar /fs_testdir/my

EmmetHTML/CSS程式碼快速編寫神器

Emmet的前身是大名鼎鼎的Zen coding,如果你從事Web前端開發的話,對該外掛一定不會陌生。它使用仿CSS選擇器的語法來生成程式碼,大大提高了HTML/CSS程式碼編寫的速度,比如下面的演示:    Zen coding下的編碼演示 去年年底,該外掛已經改名為Em

題目編寫程式碼模擬三次密碼輸入的場景

要求:最多能輸入三次密碼,密碼正確,提示“登入成功”,密碼錯誤, 可以重新輸入,最多輸入三次。三次均錯,則提示退出程式。 程式碼: #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include<string.h&

CSI-S2編寫快取記憶體友好的程式碼

       在CSI-VII一篇中,我們瞭解了儲存器系統的層次結構,並知道了層次結構自上而下使用了快取(cashing)技術,因此我們著重介紹了儲存系統中快取記憶體的工作原理。本篇內容,我們通過分析幾個程式碼例項來分析快取記憶體如何影響程式,並提出如何編寫快取記憶體友好程

程式碼規範、減少冗餘、高效利用記憶體

1、程式碼規範      a、命名規範、方法名規範,譬如你想查詢一個人的資訊    接口裡就應該為getPersonDetailById(int id) ,呼叫的人很清楚的明白這個方法的作用以及需要傳遞些什麼引數。在DAO層,就應該為fingPersonDetailById(

如何編寫高效程式碼(2014/6/1)

編寫高效的程式碼有兩個條件:選擇好的演算法和資料結構,編寫編譯器能夠優化以轉換成高效可執行的程式碼。前者是基礎和前提,即使後者做的足夠好,但是選用了錯誤的演算法和資料結構,優化也不起作用,這個一點要搞清楚。本文的內容的側重於後者。1 計算機系統架構L1和L2位於CPU晶片上,

程式碼編寫一個簡單的字元裝置驅動——建立多個同類型裝置

編寫同類型多個裝置字元驅動應注意一下幾個問題: 1、申請裝置號alloc_chrdev_region時須指定次裝置號範圍; 2、動態分配裝置空間時同時分配NUM個裝置的空間; 3、根據次裝置號和統一的主裝置號生成針對單個裝置的devno,然後完成cdev_add註冊; 4、

編寫高效Android程式碼

雖然如此說,但似乎並沒有什麼好的辦法:Android裝置是嵌入式裝置。現代的手持裝置,與其說是電話,更像一臺拿在手中的電腦。但是,即使是“最快”的手持裝置,其效能也趕不上一臺普通的臺式電腦。 這就是為什麼我們在書寫Android應用程式的時候要格外關注效率。這些裝置並沒有那麼快,並且受電池電量的制約。這意味

編寫安全程式碼小心volatile的原子性誤解

這時,exit_flag都需要使用volatile來修飾。不然對於執行緒1的程式碼,如果編譯器發現線上程1的程式碼中沒有任何地方修改exit_flag,有可能會將exit_flag放入暫存器快取。這樣,在每次的條件檢查的時候,都是從暫存器中讀取,而非exit_flag對應的記憶體。這樣將導致每次讀取的值都為0