從零開始山寨Caffe·零:必先利其器


工作環境

巧婦有了米炊

眾所周知,Caffe是在Linux下寫的,所以長久以來,大家都認為跑Caffe,先裝Linux。

niuzhiheng大神發起了caffe-windows項目(解決了一些編譯、API相異問題)

以及willyd大神發起的caffe-windows-dependencies項目(整理了依賴庫,修正了LMDB在NTFS分區的Bug)

我們現在可以很歡樂地在Windows上研究Caffe源碼,以及山寨它了。

編輯器

在Windows下涉及CUDA,Visual Studio必然是首選。如果問原因,這是NVIDIA官方的推薦。

CUDA最初使用的語言,除了二進制機器碼,就是類似CPU匯編的,GPU匯編——PTX代碼。

后來NVIDIA的工程師寫了C接口,編譯器稱為NVCC。

NVCC相當有趣,它在編譯前,需要對CUDA代碼以及傳統C/C++代碼做分離。

這一步給模板(Template)分離式編程帶來比較大的麻煩,C/C++編譯器和NVCC編譯器不共享某些知識,

所以你需要重復某些代碼。(幸好我們有宏)

 

CUDA的地位與DirectX差不多,后者是MS為GPU封裝的C++接口。

CUDA、OpenCL、DirectX旗下的Direct Compute並稱為GPGPU通用計算的三個小王子。

當然,CUDA屬於那種為了奪嫡開掛的小人,目前你看到的CUDA框架,只限於NVIDIA GPU,

因為它在設計的時候,沒有從通用GPU出發,直接在自家的硬件物理架構上設計,所以優勢很大。

 

再說Windows,玩過游戲的人都知道,NVIDIA和MS是多年友商了。

玩游戲有句信條:千萬不要用Linux。這句話可以從兩方面解釋:

(I) NVIDIA為Windows全心全意做驅動程序,證據是Linux裝顯卡驅動曾經

是一個老大難問題,無數人抱怨,“NVIDIA就是MS的奸細”。

(II) 很少有開發者用Linux API寫游戲(PC端)

這個現象最近有所改觀,基礎驅動和CUDA也為部分Linux提供了支持(Ubuntu)。

就連CES2016上,老黃演示無人駕駛系統Drive PX 2 Demo居然也是跑在Linux(Ubuntu)上。

似乎還被人看出來跑的是Caffe(疑似),但不論則么說,NVIDIA現在是對Linux有所關注了。

 

為了體現與MS的友誼,CUDA幾乎是與Visual Studio捆綁的,前提你得先裝VS。

CUDA會把插件和配置直接自動寫到VS里去。

配置NVCC和以及傳統C/C++編譯器相當繁瑣,如果你是民間大神,可以嘗試Vim或Sublime。

但是,最好不要這么作死,VS其實也不是很難用。

OS及VS

我個人在Windows10 Threshold 1下工作。

VS使用是Metro先鋒VS2013,相當老掉牙的版本。(VS 2012及以下的UI相當丑,因為同年8月才出了Windows8)。

VS的默認工作模式是X64 Release。

依賴環境庫

你的VS工作環境,決定了你的依賴庫是如何使用的。

依賴庫有“大三元”的說法:

如圖,就是這三個目錄,分別存着:動態庫、引用頭文件,靜態庫。

(I)先說說靜態庫,VS的靜態庫是lib文件,GCC的靜態庫是a文件。

靜態庫只能在編譯階段的鏈接器中使用,這與C/C++的分離式編程有關。

眾所周知,C/C++倡導聲明定義分離,這大大加快了整體編譯速度,以及方便外部調用。

於是編譯階段分為兩部門:先進行聲明的分析,然后再把定義填充進去。

聲明的全部內容通常是提供給外部的,是由零碎的頭文件組成,你想用就#include就好了。

定義的內容,會被鏈接器灌裝起來。根據灌裝模式的不同,就出現了靜態編譯和動態編譯兩類。

根據生成內容的不同,又可以分為可執行文件生成和庫生成兩類。

利用笛卡爾積,我們大概得到四種模式:

★庫生成,靜態編譯( h文件+lib文件(VC) 或者h文件+a文件(GCC) )

★庫生成,動態編譯  (不存在)

★可執行文件生成,靜態編譯 (exe文件)

★可執行文件生成,動態編譯 ( exe文件+dll or bin文件+so文件(Linux) )

其中第二種方式是不存在的。所以針對庫生成而言,我們只需要h+lib/a文件即可。

它們應當分別放到include和lib文件夾中。

 

在VS中配置頭文件/靜態庫很簡單,分為兩步:

★在工程屬性-VC++目錄中指定"包含目錄"以及”庫目錄“,分別為h目錄以及lib目錄

★在工程屬性-鏈接器-輸入中,手動添加需要的lib文件

第二步相當重要,如果不做,那么編譯是不會錯的,但是在鏈接定義的時候,會找不到lib中的定義:

error LNK2001: 無法解析的外部符號

如果你的lib目錄沒錯,那么試着找一找,是不是沒有手動添加lib文件(VS不會自動掃描目錄文件並且添加)

 

(II)再說說動態庫,這個方式只有在選擇了Release模式編譯之后,才會使用。

先說說Debug和Release的區別。

Debug版本一般不用來發布,不僅是因為里面包含了Debug代碼,而且沒有做編譯優化,性能有折扣。

但是有一點好處,就是可以斷點、調試,但這非常麻煩。

由於外部依賴庫的灌裝,你要Debug你的程序,需要提供pdb符號文件,這意味着你得自己把所有依賴庫

自己編譯一遍,得到pdb文件,否則無法Debug,也就無法斷點調試。

因為無法斷點,所以Debug只能靠人工推理出斷點(推測可能位置,加cout/printf語句測試)

還有一點,就是Debug版本在調試模式中的執行只需要lib文件,如圖:

但是,一旦你把Debug版本的exe文件拿到別處,就需要dll文件了,這時候需要動態庫。

Release版本則是強制使用動態庫,就算是調試模式也無效。

 

在VS中配置動態庫很簡單,只要一步

★在工程屬性-調試中,指定"環境"的值為:PATH=%PATH%;C:\xxx\bin

確保bin里存在需要的dll文件,否則OS會一致提示你缺少dll文件。

 

另外,Debug和Release版本需要的lib文件和dll文件均是不同的,不能混用。

一般文件名后補一個"d",表示這是Debug版本的dll/lib。

教學用·快速依賴環境包

這個包僅教學使用,閹割龐大的Boost,直接無視了OpenCV(這東西其實沒多大用)。

對於山寨Caffe,足夠了。僅僅30MB,適合傻瓜。

強調,請用於: X64 Release

度娘:http://pan.baidu.com/s/1NeDrS

有問題郵箱@我:neopenx@mail.hfut.edu.cn

 

2016.2.18 更新lmdb.lib

-修正Win32平台下,set end of file error!的輸出信息問題

解決方案是在lmdb源碼的mdb.c里把這句printf注釋掉。

這是一句毫無意義的輸出信息,僅僅在Windows平台下被編譯出來,強迫症患者可以選擇嘗試。

度娘:http://pan.baidu.com/s/1sk29YlJ

 


免責聲明!

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



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