學習筆記(1):編譯的基本概念
什么是編譯
對于語言,有高級語言,低級語言和機器語言的方式來表示,因為機器是只能做數字計算的,能夠讓機器去運算的只有機器語言,從高級語言轉為機器語言的過程就叫做編譯,由編譯器來完成
例如:由 C 轉換為匯編語言需要 匯編器來執行
C 和匯編語言轉換為機器語言都是由編譯器來指向的
編譯器的架構
傳統的編譯器架構
前端:詞法分析,語法分析,語義分析,生成中間代碼
優化器:中間代碼優化
后端:生成機器碼
編譯優化的方法
常量傳播
編譯優化時,能夠將計算出來的變量直接替換為常量
void main()
{
int a=1;
printf("%d",a);
}
優化后
void main()
{
printf("%d",1);
}
公共子表達式消除
如果一個表達式已經計算過,并且表達式中的變量一直沒有變化,那么這個這個表達式就是公共子表達式
void main()
{
int a =1,b=2,x=0;
x=(a+c)*12+(c+a);
}
優化后
void main()
{
int a =1,b=2,x=0;
x=E*12+E;
}
方法內聯
循環優化
循環嵌套外大內小
循環條件使用<要快于<=
for(int i=0;i<50;i++)
把外層可以計算的盡可能放到外層,減少在內層的運算,有判斷條件的語句和與循環不相關的操作語句盡量放在for外面
循環展開
循環交換
https://blog.csdn.net/zhengzhoudaxue2/article/details/6459890
再看這個例子
int main(int argc,char **argv)
{
int i,m,k1,k2,k3,k4,k5,k6,k7,k8;
m=10000000;
for(i=0;i<m;i++){
k1++; k5++;
k2++; k6++;
k3++; k7++;
k4++; k8++;
}
return (0);
}
這個for循環,我們是讓這些數每次循環都加1,這個效率也不是達到了最優,是這樣的,在每次for循環的時候,編譯器會給變量i,變量m每個獨占一個寄存器,因為是循環嘛,編譯器給i和m也是為了效率考慮,不用再向寄存器加載每次循環的判斷變量了,但是,一般基于Intel的處理器都只有8個通用寄存器,這樣,我們就剩下了6個寄存器給for循環里的內容中的變量使用,但是,我們的變量有8個,我們這時會在把其他的變量入棧,這樣,我們的效率變低了,每次出戰或者入棧都會消耗兩個CPU時鐘周期
優化后:
int main(int argc,char **argv)
{
int i,m,k1,k2,k3,k4,k5,k6,k7,k8;
m=10000000;
for(i=0;i<m;i++){
k1++; k5++;
k2++; k6++;
}
for(i=0;i<m;i++){
k3++; k7++;
k4++; k8++;
}
return (0)
}
LLVM
llvm項目是模塊化、可重用的編譯器以及工具鏈技術的集合
LLVM架構
- 不同的前端后端使用統一的中間代碼LLVM Intermediate Representation(LLVM IR)
- 如果需要支持一種新的編程語言,那么只需要實現一個新的前端
- 如果需要支持一種新的硬件設備,那么只需要實現一個新的后端
- 優化階段是一個通用的階段,它針對的是統一的LLVM IR,不論是支持新的編程語言還是支持新的硬件設備,都不需要對優化階段做修改
- 相比之下,GCC的前端和后端沒分得太開,前端后端耦合在了一起。所以GCC為了支持一門新的語言,或者為了支持一個新的目標平臺,就 變得特別困難
- LLVM現在被作為實現各種靜態和運行時編譯語言的通用基礎結構(GCC家族、Java、.NET、Python、Ruby、Scheme、Haskell、D等)
Clang
Clang是LLVM的一個子項目,基于LLVM架構的C/C++/Objective-C編譯器的前端
Clang對比GCC的優點
- 編譯速度快:在某些平臺上,Clang的編譯速度顯著的快過GCC(Debug模式下編譯OC速度比GGC快3倍)
- 占用內存小:Clang生成的AST所占用的內存是GCC的五分之一左右
- 模塊化設計:Clang采用基于庫的模塊化設計,易于 IDE 集成及其他用途的重用
- 診斷信息可讀性強:在編譯過程中,Clang 創建并保留了大量詳細的元數據 (metadata),有利于調試和錯誤報告
- 設計清晰簡單,容易理解,易于擴展增強
LLVM整體架構,前端用的是clang,廣義的LLVM是指整個LLVM架構,一般狹義的LLVM指的是LLVM后端(包含代碼優化和目標代碼生成)。
源代碼(c/c++)經過clang–> 中間代碼(經過一系列的優化,優化用的是Pass) --> 機器碼
參考
深入淺出讓你理解什么是LLVM
https://www.jianshu.com/p/1367dad95445
編譯器常用優化方法
https://www.jianshu.com/p/0caa9cfd995a
你的for循環真的高效嗎
https://blog.csdn.net/zhengzhoudaxue2/article/details/6453366
智能推薦
線程的基本概念-馬士兵線程學習筆記
理解線程 其實搞清楚線程和進程的關系就很好理解線程了。比如說你開一個微信,那微信就是一個進程, 但是微信里你同時和不同的人聊天,那不同的窗口就是一個個線程。線程實際就是可執行程序的最小單元, 是一個進程的不同執行路徑。 線程的兩種創建方式 線程的創建有很多種寫法,但是歸根結底就只有兩種,一種是實現runnable接口,一種是繼承Thread類 熟悉調用線程的幾個函數 sleep() 調用Threa...
機器學習(1)——基本概念
轉載自: http://blog.csdn.net/daigualu 一、名詞解釋 數據集(data set) 記錄的集合,假如我們用3個特征,分別為色澤,根蒂,響聲來描述西瓜的特點,并且拿到了基于這3個特征的10萬條記錄,其中一條記錄的取值為: 色澤=光亮,根蒂=堅硬,響聲=清亮 如果記錄到.csv文件中,這個文件的結構可以記為: fruit[100000][3...
javaScript學習筆記——基本概念
1.javaScript的定義 ①是一種專門為網頁交互而設計的腳本語言 ② 組成: 2.<script>元素 3.區分大小寫 ECMAScript中的一切(變量、函數名,操作符)都區分大小寫; 4.標識符 ①第一個字符必須是字母、下劃線、$,其他字符可以是字母、下劃線、$或數字; ②ECMAScript標識符一般使用駝峰大小寫格式,即第一個字母小寫,剩下的每...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...