編譯CUDA動態鏈結庫及使用

2021-06-12 06:17:38 字數 4349 閱讀 3042

除了直接在專案中使用cu或cuh來編寫cuda**之外,還可以將cuda相關操作**放在乙個dll專案中,將專案編譯成動態鏈結庫dll,然後在需要使用的專案中引用這個dll並呼叫其內部函式即可。

現在新建乙個dll專案,專案名稱為test00302,如下圖所示:

現在在專案中新建乙個名為test.cu的檔案,如下圖所示:

然後設定專案的生成自定義方式為,如下圖所示:

然後設定test.cu的屬性中「項型別」為「cuda c/c++」,如下圖所示:

在test.cu中新增如下**:

#include #include #include //cuda執行時庫標頭檔案

using namespace std;

extern "c"

//顯示裝置資訊

void showdeviceprop(void)

else

freelibrary(mycudadll);//動態地解除安裝dll檔案

執行專案test00303,其結果如下圖所示:

專案test00303為普通的控制台應用程式,test00302.dll為編譯的包含cuda函式的動態鏈結庫,通過動態引用,即可在普通的應用程式裡面載入cuda程式。

下面再用呼叫cuda核心函式的進行測試,先在專案test00302中新建乙個名為test2.cu的檔案,在test2.cu中新增gpu中執行的核函式addkernel(),然後新增用於向量相加的函式vectoradd(),在函式vectoradd()中選擇用於執行的gpu裝置、在裝置上分配記憶體、複製主機記憶體資料到裝置記憶體、啟動核函式、呼叫cudadevicesynchronize()監聽核函式執行、複製裝置記憶體資料到主機記憶體、重置cuda裝置、釋放裝置記憶體。test2.cu中的**如下:

#include "cuda_runtime.h"

#include "device_launch_parameters.h"

#include extern "c"

//cuda核函式

__global__ void addkernel(int *c, const int *a, const int *b)

//向量相加

int vectoradd(int c, int a, int b,int size)

// 在gpu中為變數dev_a、dev_b、dev_c分配記憶體空間.

cudastatus = cudamalloc((void**)&dev_c, size * sizeof(int));

if (cudastatus != cudasuccess)

cudastatus = cudamalloc((void**)&dev_a, size * sizeof(int));

if (cudastatus != cudasuccess)

cudastatus = cudamalloc((void**)&dev_b, size * sizeof(int));

if (cudastatus != cudasuccess)

// 從主機記憶體複製資料到gpu記憶體中.

cudastatus = cudamemcpy(dev_a, a, size * sizeof(int), cudamemcpyhosttodevice);

if (cudastatus != cudasuccess)

cudastatus = cudamemcpy(dev_b, b, size * sizeof(int), cudamemcpyhosttodevice);

if (cudastatus != cudasuccess)

// 啟動gpu核心函式

addkernel<<<1, size>>>(dev_c, dev_a, dev_b);

// 採用cudadevicesynchronize等待gpu核心函式執行完成並且返回遇到的任何錯誤資訊

cudastatus = cudadevicesynchronize();

if (cudastatus != cudasuccess)

// 從gpu記憶體中複製資料到主機記憶體中

cudastatus = cudamemcpy(c, dev_c, size * sizeof(int), cudamemcpydevicetohost);

if (cudastatus != cudasuccess)

result=0;

// 重置cuda裝置,在退出之前必須呼叫cudadevicereset

cudastatus = cudadevicereset();

if (cudastatus != cudasuccess)

error:

//釋放裝置中變數所佔記憶體

cudafree(dev_c);

cudafree(dev_a);

cudafree(dev_b);

return result;

}

編譯專案test00302,在生成的動態鏈結庫檔案test00302.dll複製到專案test00303的debug資料夾下,然後修改專案

test00303中的檔案test00303.cpp內容如下:

// test00303.cpp : 定義控制台應用程式的入口點。

#include "stdafx.h"

#include #include #include typedef int(*dllfunc)(void);//宣告需要從dll中呼叫的函式原型的函式指標

typedef int(*dllfunc2)(int *c, int *a, int *b,int size);//宣告需要從dll中呼叫的函式原型的函式指標

int _tmain(int argc, _tchar* argv)

//else

////呼叫dll中的vectoradd函式

dllfunc2 dllfun2=(dllfunc2)getprocaddress(mycudadll,"vectoradd");//獲得函式指標

if (dllfun2)

; int b[arraysize] = ;

int c[arraysize] = ;

int r=dllfun2(c,a,b,arraysize);//執行函式

if(r==0)

+ = \n",

c[0], c[1], c[2], c[3], c[4]);

}else

printf("計算失敗\n");

} else

freelibrary(mycudadll);//動態地解除安裝dll檔案

} else

system("pause");

return 0;

}

由於dll中的函式vectoradd 定義如下:

int vectoradd(int c, int a, int b,int size);

所以在宣告函式的原型指標時也需要定義為:

typedef

int(*dllfunc2)(int *c, int *a, int *b,int size);

或:typedef

int(*dllfunc2)(int c, int a, int b,int size);

執行專案test00303,其結果如下圖所示:

雖然這個例子比較簡單,但是向量相加的計算過程是由gpu完成的。

GCC 編譯使用動態鏈結庫

動態鏈結庫 1.建立動態鏈結庫 複製 如下 include void hello 用命令gcc shared hello.c o libhello.so編譯為動態庫。可以看到,當前目錄下多了乙個檔案libhello.so。2.再編輯乙個測試檔案test.c,內容如下 複製 如下 include in...

GCC 編譯使用動態鏈結庫和靜態鏈結庫

1 庫的分類 根據鏈結時期的不同,庫又有靜態庫和動態庫之分。靜態庫是在鏈結階段被鏈結的 好像是廢話,但事實就是這樣 所以生成的可執行檔案就不受庫的影響了,即使庫被刪除了,程式依然可以成功執行。有別於靜態庫,動態庫的鏈結是在程式執行的時候被鏈結的。所以,即使程式編譯完,庫仍須保留在系統上,以供程式執行...

GCC 編譯使用動態鏈結庫和靜態鏈結庫

1 庫的分類 根據鏈結時期的不同,庫又有靜態庫和動態庫之分。靜態庫是在鏈結階段被鏈結的 好像是廢話,但事實就是這樣 所以生成的可執行檔案就不受庫的影響了,即使庫被刪除了,程式依然可以成功執行。有別於靜態庫,動態庫的鏈結是在程式執行的時候被鏈結的。所以,即使程式編譯完,庫仍須保留在系統上,以供程式執行...