Linux下c和cuda混合编译,并生成动态链接库.so和使用
Linux下c和cuda混合編譯,并生成動態鏈接庫.so和使用
2016-08-27 14:27 98人閱讀 評論(0) 收藏 舉報 分類: Linux版權聲明:本文為博主原創文章,未經博主允許不得轉載。
目錄(?)[+]
梗概
如果要生成動態鏈接庫,就需要把源碼,無論是.c .cpp .cu還是其他的語言寫的程序,都通過編譯器變成.o文件,之后把相應的.o文件進行鏈接成為.so動態鏈接庫。這樣就可以直接調用其中的函數了。
形成過程: .c .cpp .cu -> .o -> .so
使用 : test.c + .so - > test
./test
但是其中還是有許多的小細節需要注意的。
現在就舉個栗子:
把yolo算法,編譯成動態鏈接庫,其中需要用到opencv、cuda、cudnn。之后講介紹怎么把這些庫一起與源碼進行編譯,生成可以用的.so。
源碼文件分為三類:.c文件 .h頭文件和 .cu的cuda文件
【分析編譯.c文件】
gcc : 編譯器
-fPIC: 使用 -fPIC 選項,會生成 PIC 代碼。告訴編譯器產生與位置無關代碼(Position-Independent Code), .so 要求為 PIC,以達到動態鏈接的目的,否則,無法實現動態鏈接。
`pkg-config –cflags opencv`: 根據pkg-config信息來找到opencv的include,因為源文件中包含使用了一些opencv的函數,所以需要引入include文件。對應的“ 兩個反引號不要少。
-I/usr/local/cuda/include/ : 首先-I表示根據需要在/usr/local/cuda/include/目錄下找到對應的文件。并包含進去一起編譯。
-Wall: 表示把所有警告都展示出來。
-Wfatal-errors: 表示當發生第一個錯誤的時候停止編譯,這樣的好處就是可以找到錯誤的地方,防止許多無用的信息掩蓋了錯誤信息。
-Ofast:編譯所采用的優化手段。
-c: 進行源文件的編譯成.o文件
-o: 輸出到哪里,并且文件名是什么,只有緊跟其后的一項是輸出
-DOPENCV,-DGPU,-DCUDNN:這些選項就是控制代碼中的宏定義,如果帶有這些選項進行編譯,證明宏定義是選定的。即#ifdef OPENCV 是定義了的,否則沒有定義。這也相當與vs中的預處理選項。通過這項可以根據修改Makefile文件來確定某個庫是否使用,在源碼中再通過宏定義來實現,非常方便。
【分析.cu文件編譯】
<code class="hljs lasso has-numbering">nvcc <span class="hljs-subst">--</span>gpu<span class="hljs-attribute">-architecture</span><span class="hljs-subst">=</span>compute_52 <span class="hljs-subst">--</span>gpu<span class="hljs-attribute">-code</span><span class="hljs-subst">=</span>compute_52 <span class="hljs-attribute">-DOPENCV</span> <span class="hljs-string">`pkg-config --cflags opencv2`</span> <span class="hljs-attribute">-DGPU</span> <span class="hljs-attribute">-I</span>/usr/<span class="hljs-built_in">local</span>/cuda/include<span class="hljs-subst">/</span> <span class="hljs-attribute">-DCUDNN</span> <span class="hljs-subst">--</span>compiler<span class="hljs-attribute">-options</span> <span class="hljs-string">"-Wall -Wfatal-errors -Ofast -DOPENCV -DGPU -DCUDNN -fPIC"</span> <span class="hljs-attribute">-c</span> <span class="hljs-built_in">.</span>/src/convolutional_kernels<span class="hljs-built_in">.</span>cu <span class="hljs-attribute">-o</span> obj/convolutional_kernels<span class="hljs-built_in">.</span>o</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>很多與c的編譯差不多。
nvcc : cuda的編譯器
–gpu-architecture=compute_52 –gpu-code=compute_52 : 這個是根據顯卡計算能力來確定的,來表示gpu的架構是說明,我的顯卡是GT960,所以是compute_52
–compiler-options : 在雙引號中填寫一些編譯選項。 尤其是-fPIC選項,因為在外面寫是編譯不通過的,只能在雙引號里面寫。
把所有的.c文件和.cu文件都編譯成.o文件,當然都是-fPIC編譯的,即是位置無關的。
現在就開始通過這些目標文件來進行.so的生成。
-shared : 因為要做成動態鏈接庫,所以需要把該庫做成可以共享的。
*.o : 即剛才生成的所有.o文件,依次添加進去。
但是只把這些.o文件進行鏈接,鏈接到libtest.so文件中,雖然也可以生成.so文件,但是在使用時會出現一些錯誤,如:undefined reference to `cudnnGetConvolutionBackwardDataWorkspaceSize’ 等關于cudnn的錯誤。 所以需要在鏈接的時候把cudnn的相關鏈接也鏈接進去。
-L/usr/local/cuda/lib64 : 確定lib的路徑,-L后面跟的就是lib所在的路徑,如果要引入其中的.so文件,只需要-l開頭即可,后面跟文件名去掉lib的名字即可。
這樣就生成了.so文件。
使用.so文件:
Step 1:
<code class="hljs brainfuck has-numbering"><span class="hljs-comment">gcc</span> <span class="hljs-literal">-</span><span class="hljs-comment">c</span> <span class="hljs-comment">test</span><span class="hljs-string">.</span><span class="hljs-comment">c</span> <span class="hljs-comment">$(pkg</span><span class="hljs-literal">-</span><span class="hljs-comment">config</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">cflags</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">libs</span> <span class="hljs-comment">opencv)</span></code><ul style="" class="pre-numbering"><li>1</li></ul>因為test.c中有opencv的函數,所以編譯的時候需要引入opencv,生成test.o文件
Step 2:
把程序與cuda的庫進行動態鏈接,生成可執行文件test。
總結
以上是生活随笔為你收集整理的Linux下c和cuda混合编译,并生成动态链接库.so和使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle 10.2.0.1 升级 1
- 下一篇: Linux动态链接库的使用