VS2008+QT中使用CUDA的示例


各工具或庫的版本:

IDE:VS2008

QT:4.8.0 (使用MSVC編譯器)

CUDA:3.2

單獨使用CUDA文件在vccc下進行編譯很多書上都講過。這里主要講在QT中如何的使用CUDA,QT在VS2008環境下開發。

下面以寬為1024的舉證乘法為例,再輔以QT GUI說明如何在VS2008的QT工程中使用CUDA,VS2010沒試過,不過應該是差不多的步驟。

1.新建VS2008下QT工程

這個就不多說了,熟悉VS2008下進行QT開發的都知道怎么弄,新建一個Qt GUI程序,基類我選擇的QDialog,如下:

2.設置項目屬性

需要設置的項目屬性包括:更改生成規則(添加對CUDA文件的編譯連接支持)、添加使用CUDA需要用到的鏈接庫(.lib文件)

首先添加生成規則:右鍵工程——>自定義生成規則,添加CUDA Runtime API Build Rule (v3.2),如下圖:

然后添加鏈接庫:項目——>屬性——>鏈接器——>常規,在附加庫目錄中添加ToolKit和SDK目錄里的lib,在輸入的附加庫目錄下添加需要用到的lib文件。這一步和在單獨使用CUDA時的做法是一樣的,詳見http://www.cnblogs.com/Romi/archive/2012/04/20/2459669.html

3.編寫CUDA文件(.cu)

在項目中新建一個.cu的文件,加上如下代碼,完成在GPU設備上進行矩陣乘法:

View Code
 1 //CUDAtest.cu
 2 
 3 #include "cuda_runtime.h"  
 4 
 5 #define TILE_WIDTH 64
 6 
 7 //核函數
 8 __global__ static void MatrixMulKernel(const float* Md,const float* Nd,float* Pd,int Width)
 9 {
10     //計算Pd和Md中元素的行索引
11     int Row = blockIdx.y*TILE_WIDTH+threadIdx.y; //行
12     int Col = blockIdx.x*TILE_WIDTH+threadIdx.x; //列
13 
14     float Pvalue = 0.0;
15     for (int k=0;k<Width;k++)
16     {
17         Pvalue +=Md[Row*Width+k]*Nd[k*Width+Col];
18     }
19     //每個線程負責計算P中的一個元素
20     Pd[Row*Width+Col]=Pvalue;
21 }
22 
23 //矩陣乘法(CUDA中)
24 //在外部調用,使用extern
25 extern "C" void MatrixMultiplication_CUDA(const float* M,const float* N,float* P,int Width)
26 {
27     cudaSetDevice(0);  //設置目標GPU 
28 
29     float *Md,*Nd,*Pd;
30     int size = Width*Width*sizeof(float);//字節長度
31 
32     cudaMalloc((void**)&Md,size);
33     cudaMalloc((void**)&Nd,size);
34     cudaMalloc((void**)&Pd,size);
35 
36     //Copies a matrix from the memory* area pointed to by src to the memory area pointed to by dst
37     cudaMemcpy(Md,M,size,cudaMemcpyHostToDevice);
38     cudaMemcpy(Nd,N,size,cudaMemcpyHostToDevice);
39 
40     //
41     dim3 dimGrid(Width/TILE_WIDTH,Width/TILE_WIDTH); //網格的維度
42     dim3 dimBlock(TILE_WIDTH,TILE_WIDTH); //塊的維度
43     MatrixMulKernel<<<dimGrid,dimBlock>>> (Md,Nd,Pd,Width);
44 
45     cudaMemcpy(P,Pd,size,cudaMemcpyDeviceToHost);
46     //釋放設備上的矩陣
47     cudaFree(Md);
48     cudaFree(Nd);
49     cudaFree(Pd);
50 }

這里使用extern以聲明函數可以在外部被調用。如果是在調用該函數的原文件中使用include “XXX.cu”,我這會出現編譯錯誤,暫沒有解決,所以使用extern

4.在Qt響應源文件中添加CUDA的引用

Qt GUI設計如下圖,點擊“GPU計算”按鈕進行CUDA計算,后面顯示計算的時間:

源文件如下(包含用到的自定義函數和按鈕響應函數):

View Code
 1 //cudainqt.cpp源文件
 2   
 3   #include "cudainqt.h"
 4   #include <QProgressDialog>
 5   #include <time.h>
 6   
 7   //這里不要忘了加引用聲明
 8   extern "C" void MatrixMultiplication_CUDA(const float* M,const float* N,float* P,int Width);
 9   
10   //構造函數...
11   //析構函數...
12   
13   //產生矩陣,矩陣中元素0~1
14   void matgen(float* a,int Width)
15   {
16       int i,j;
17       for (i=0;i<Width;i++)
18       {
19           for (j=0;j<Width;j++)
20           {
21               a[i*Width+j]=(float)rand()/RAND_MAX + (float)rand()/(RAND_MAX*RAND_MAX);
22           }
23       }
24   }
25   
26   //矩陣乘法(CPU驗證)
27   void MatrixMultiplication(const float* M,const float* N,float* P,int Width)
28   {
29       QProgressDialog progress("Progress", "Cancel", 0, 100);
30       int i,j,k;
31       for (i=0;i<Width;i++)
32       {
33           for (j=0;j<Width;j++)
34           {
35               double sum=0;
36               for (k=0;k<Width;k++)
37               {
38                   sum += M[i*Width+k]*N[k*Width+j];
39               }
40               P[i*Width+j]=sum;
41           }
42           if(0==i%5)
43               progress.setValue(100*i/(Width-1));
44       }
45   }
46   
47   void cudaInQt::OnButtonClicked_GPU()
48   { 
49       float *M,*N,*Pg;
50       int Width=1024; //1024×1024矩陣乘法
51       M=(float*)malloc(sizeof(float)*Width*Width);
52       N=(float*)malloc(sizeof(float)*Width*Width);
53       Pg=(float*)malloc(sizeof(float)*Width*Width); //保存GPU計算結果
54   
55       srand(0);
56   
57       matgen(M,Width); //產生矩陣M
58       matgen(N,Width); //產生矩陣N
59   
60       double timeStart,timeEnd; //定義時間,求時間差用
61       timeStart = clock();
62       MatrixMultiplication_CUDA(M,N,Pg,Width); //GPU上計算
63       timeEnd = clock();
64       ui.textEdit_GPU->setText(QString::number(timeEnd-timeStart)+"ms");
65  
66       free(M);
67       free(N);
68       free(Pg);
69   }
70   
71   void cudaInQt::OnButtonClicked_CPU()
72   {
73       float *M,*N,*Pc;
74       int Width=1024; //1024×1024矩陣乘法
75       M=(float*)malloc(sizeof(float)*Width*Width);
76       N=(float*)malloc(sizeof(float)*Width*Width);
77       Pc=(float*)malloc(sizeof(float)*Width*Width); //保存CPU計算結果
78   
79       srand(0);
80   
81       matgen(M,Width); //產生矩陣M
82       matgen(N,Width); //產生矩陣N
83   
84       double timeStart,timeEnd; //定義時間,求時間差用
85       timeStart = clock();
86       MatrixMultiplication(M,N,Pc,Width); //CPU上計算
87       timeEnd = clock();
88       ui.textEdit_CPU->setText(QString::number(timeEnd-timeStart)+"ms");
89  
90       free(M);
91       free(N);
92       free(Pc);
93   }

5.測試結果

測試時開了其他的應用程序,另外本機配置很戳,看看吧,使用CUDA進行加速甩了使用傳統方法幾條街呢

后注:代碼中有點問題,測試結果也不對,后來發現了,改過的結果見該文http://www.cnblogs.com/Romi/archive/2012/05/17/2506787.html


免責聲明!

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



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