LLVM小結


LLVM小結

 

如果說gcc是FSF的傳奇,llvm就是Chris Lattner的小清新。當然啦,想具體看看這位四處游山玩水還GPA 4.0的大神和他的LLVM編譯鏈還有他與蘋果之間的故事的讀者可以移步http://news.cnblogs.com/n/127343/。另外,據悉,FreeBSD自10.0開始將會完全采用llvm編譯鏈編譯,而之前的版本,與Linux一樣,都是采用的gcc編譯的。

以上,就算是“拉大旗扯虎皮”,既是給llvm做個簡介,也是讓大家知道本篇博文還是說的是比較“有用的東西,而不是什么虛無飄渺的東西。

llvm在編譯鏈中的環節其實是屬於后端,前端可以采用gcc或者clang(從某些編譯課程來看,用yacc和bison寫的前端也行)。gcc想必大家都很熟悉,我也就不再贅述。clang則是專門為llvm定制的前端,據說當初開發它的一個很重要的因素就是gcc和IDE配合得不太好,而且gcc模塊之間寫得比較混雜,難以修改。作為前端,雖然我沒有使用過配合clang的IDE(Apple developer能使用到的XCode算一個,不過我還沒真正用過),但確實,在終端下調試的時候clang給出的輸出比gcc的要好理解得多。不過clang是名副其實的CLang,只支持C/Obj-C/C++這三種語言;而gcc當然是無所不包無所不能的了。這里我上個C程序的例子吧(如果覺得不過癮,你可以自行嘗試C++,據說C++的類模板最能體現這兩者的區別,也可以直接去http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.html):

復制代碼
1 #include <stdio.h>
2 
3 int main(){
4     return 1? 2 3
5 }
復制代碼

我們來看看clang和gcc給出的出錯信息分別是什么(為了證實確實是這段程序,我先cat了它):

首先,其實gcc沒有給全出錯信息,如果你只照gcc的輸出在第4行14列添加了冒號,那么你再次編譯的時候它還會告訴你這一行的末尾缺分號;而clang不僅給全了錯誤而且每個錯誤都是出錯信息一行,源代碼一行,建議一行(note也是這樣的),並且輸出有色彩分別。筆者的gcc版本是4.7.3,clang版本是3.2-1,都是Ubuntu 13.04下最新的(順帶插一句:不知道為什么llvm 3.3已經發布很久了,Ubuntu還沒有正式采用)。我覺得前端有一個很重要的功能就是報錯,clang做得很好,至少這點比gcc做得好。蘋果的產品在“看得見”的地方一向都做得很好,clang也是這樣的。

編譯器的前端,不僅要能生成AST,而且如果源代碼有語法錯誤或者警告(雖然程序猿貌似都忽略警告,但實際上有的時候警告還是很有用的)要應當能給我們很好的指出,畢竟我們是人不是機器,要人性化一點;另外,后端又要能夠在前端分析出的AST為程序做出極致的優化,當然,我不是說程序優化就靠編譯器了,程序猿本身就應當編寫出好的代碼,但是編譯器確實應當負責優化程序。llvm和gcc到底誰優化得更好,大家說法不一,給出的數據差距也很大,但是呢,不過呢,“LLVM has been awarded the 2012 ACM Software System Award!”,估計肯定是不會差的了。除了各種天花亂墜的數據外(如果非要看的話,我還是給個早年的數據吧:http://llvm.org/pubs/2007-07-25-LLVM-2.0-and-Beyond.pdf),畢竟程序最終是要給用戶用的,畢竟用戶體驗才是最重要的,所以我們直接比較產品。舉個栗子:LLVMpipe,這是一個類似於即時編譯或者說在線編譯的東西,它將OpenGL的代碼(本來是拋給GPU的)編譯為CPU可執行的代碼並交由CPU執行。這個東西被很多支持老舊電腦的Linux發行版所采用,所以想來效率也不會太差。當然,效率高不高和運行快不快其實並不等價,因為運行快不快和具體的硬件環境還是有很大關系的。

說到編譯優化,llvm似乎還有一個奇怪的優化方法:llvm(low level virtual machine)本身就是一種抽象的、虛擬的計算機架構,其特性介於RISC和CISC之間,llvm會先將代碼編譯為llvm架構的字節碼(這里還是說說數據吧,從其官方數據來看,生成的字節碼略多於x86的目標代碼而少於SPARC的目標代碼),然后可以對字節碼進行JIT優化然后再翻譯為目標架構的二進制代碼。另外,llvm實際上采用的是一種全生命周期(lifelong)的優化策略(雖然還是很偏重靜態優化),最直接的體現就是比起gcc能做到的 -O3,llvm可以做到 -O4,而且 -O4采用的是LLVMgold.so所提供的運行時庫。llvm本身的設計思想就是希望做到編譯時、鏈接時、運行時、空閑時的全方位優化。關於這些優化,在llvm官網可以找到,請移步http://llvm.org/pubs/2004-01-30-CGO-LLVM.html

最后來說一下llvm和gcc的兼容性,我前面只是說了llvm的后端兼容gcc的前端生成的AST,其實llvm對gcc的兼容性是很高的,我現在系統的環境變量CC設置的就是clang,我編譯了很多工程都不用改Makefile就可以成功編譯,不過很多工程里只是采用的 -O2,讓我略不爽,所以我就手動將之改為 -O4,當然也就需要修改一下CFLAGS和LDFLAGS,為之加上llvm-config的輸出。llvm本身在腳本上就設計為和gcc的兼容,所以改換編譯鏈十分容易。

 

開源庫CImg 數據格式存儲之二(RGB 順序)

 

在上一篇博客中已經初步說明了GDI和CImg數據的存儲格式感謝博友 Imageshop 評論說明

CImg的說明文檔中已有詳細說明(詳見上篇博客說明)

CImg的數據格式確實是RRRGGGBBB順序存儲的已經毫無疑問,但是其參考手冊中對其他GDI

的數據格式說明是略有瑕疵,參考手冊說其他GDI的數據格式是RGBRGBRGB,其實則不是經過驗證

bmp類型的數據格式應該是BGRBGRBGR 下面用code驗證

說明:使用MFC 同時用CImage和CImg加載同一幅圖片

復制代碼
void ImageIO::loadImage(const BiCImg & image, T*& pImagePlane,int& width,int& height,int& nchannels)
{
    // get the image information
    
    width=image.width();
    height=image.height();
    nchannels=3;
    int rgb_leng=width*height;
    pImagePlane=new T[width*height*nchannels];

    // check whether the type is float point
    bool IsFloat=false;
    if(typeid(T)==typeid(double) || typeid(T)==typeid(float) || typeid(T)==typeid(long double))
        IsFloat=true;
    
    const unsigned char* plinebuffer;
    plinebuffer=image.data(0,0);
    for(int i=0;i<height;i++)
    {        
        //plinebuffer=image.scanLine(i);
        for(int j=0;j<width;j++)
        {
                        
pImagePlane[(i*width+j)*3]=plinebuffer[i*width+j+2*rgb_leng];//RGB b
                pImagePlane[(i*width+j)*3+1]=plinebuffer[i*width+j+rgb_leng];//RGB g
                pImagePlane[(i*width+j)*3+2]=plinebuffer[i*width+j];//RGB r
            
        }
    }
}
復制代碼

上述為正確的順序,若改為如下代碼

                pImagePlane[(i*width+j)*3]=plinebuffer[i*width+j];//RGB r 

                pImagePlane[(i*width+j)*3+1]=plinebuffer[i*width+j+rgb_leng];//RGB g

           pImagePlane[(i*width+j)*3+2]=plinebuffer[i*width+j+2*rgb_leng];//RGB b

實驗效果如下圖

 

右圖為原始圖片,明顯左圖的藍色部分取代了原始圖片的紅色應該是BGR缺寫成了RGB 

 

 
 
 
標簽:  RBG 存儲順序
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM