本專欄是通過注解程序的方法學習OpenCL,我覺得一個一個地去摳原理也不是辦法,干脆直接學習程序,然后把相關原理都直接注解到程序語句當中。
原創地址:http://blog.csdn.net/kenden23/article/details/14101657
一開始要配置好環境,我的是nvidia,所以就按照我的電腦舉例,AMD應該也差不多。
1. 首先要到nvidia網站下載適合你顯卡的最新驅動,安裝好
2. 還是在nvidia網站下載好CUDA開發包,安裝好
3. 如果默認安裝路徑的話,路徑應該是在:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0
4. 打開這個目錄會發現里面有include和lib文件夾,這就是我們需要配置在visual studio中的文件
5. 打開visual studio(版本基本都無關系,我用的是vs2012),新建一個win32空項目。按下alt+F7打開項目屬性,也可以點擊項目文件右鍵,選擇屬性。
6. 在屬性頁里面找到“C/C++”的“常規”項,點擊,右邊有“附加包含目錄”,然后編輯,添加目錄:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\include
7.在屬性頁里面找到“連接器”,點擊其“常規”項,右邊有“附加庫目錄”,然后也是編輯,添加目錄:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\lib\Win32,如果是64位系統可以是:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.0\lib\x64。
8. 在屬性頁里找到“常規”項, 右邊“附加依賴項”,編輯,添加lib文件:OpenCL.lib
9. 然后就可以新建源文件,在源文件里面添加相關的OpenCl程序,就可以調試OpenCL程序了。
下面就可以開始學習程序了。
下面是個入門程序,已經注釋好了,注釋包括了基本原理的解析,可以通過直接閱讀和調試程序學習OpenCL了。
本程序是讀取電腦中的支持OpenCL的硬件nvidia和intel和AMD等信息,然后顯示在屏幕上。
- #include?<stdio.h>??
- #include?<stdlib.h>??
- #include?<string.h>??
- #include?<iostream>??
- ??
- #ifdef?MAC??
- #include?<OpenCL/cl.h>??
- #else??
- #include?<CL/cl.h>??
- #endif??
- ??
- int?main()?{??
- ??
- ????/*?Host?data?structures?*/??
- ????cl_platform_id?*platforms;??
- ????//每一個cl_platform_id?結構表示一個在主機上的OpenCL執行平臺,就是指電腦中支持OpenCL的硬件,如nvidia顯卡,intel?CPU和顯卡,AMD顯卡和CPU等??
- ????cl_uint?num_platforms;??
- ????cl_int?i,?err,?platform_index?=?-1;??
- ??
- ????/*?Extension?data?*/??
- ????char*?ext_data;???????????????????????????
- ????size_t?ext_size;?????
- ????const?char?icd_ext[]?=?"cl_khr_icd";??
- ??
- ????//要使platform工作,需要兩個步驟。1?需要為cl_platform_id結構分配內存空間。2?需要調用clGetPlatformIDs初始化這些數據結構。一般還需要步驟0:詢問主機上有多少platforms??
- ??
- ????/*?Find?number?of?platforms?*/??
- ????//返回值如果為-1就說明調用函數失敗,如果為0標明成功??
- ????//第二個參數為NULL代表要咨詢主機上有多少個platform,并使用num_platforms取得實際flatform數量。??
- ????//第一個參數為1,代表我們需要取最多1個platform。可以改為任意大如:INT_MAX整數最大值。但是據說0,否則會報錯,實際測試好像不會報錯。下面是步驟0:詢問主機有多少platforms??
- ????err?=?clGetPlatformIDs(5,?NULL,?&num_platforms);??????????
- ????if(err?<?0)?{??????????
- ????????perror("Couldn't?find?any?platforms.");???????????
- ????????exit(1);??????????????????????????????
- ????}?????????????????????????????????????
- ??
- ????printf("I?have?platforms:?%d\n",?num_platforms);?//本人計算機上顯示為2,有intel和nvidia兩個平臺??
- ??
- ????/*?Access?all?installed?platforms?*/??
- ????//步驟1?創建cl_platform_id,并分配空間??
- ????platforms?=?(cl_platform_id*)?????????????????????
- ????????malloc(sizeof(cl_platform_id)?*?num_platforms);???
- ????//步驟2?第二個參數用指針platforms存儲platform??
- ????clGetPlatformIDs(num_platforms,?platforms,?NULL);?????????
- ??
- ????/*?Find?extensions?of?all?platforms?*/??
- ????//獲取額外的平臺信息。上面已經取得了平臺id了,那么就可以進一步獲取更加詳細的信息了。??
- ????//一個for循環獲取所有的主機上的platforms信息??
- ????for(i=0;?i<num_platforms;?i++)???
- ????{??
- ????????/*?Find?size?of?extension?data?*/??
- ????????//也是和前面一樣,先設置第三和第四個參數為0和NULL,然后就可以用第五個參數ext_size獲取額外信息的長度了。??
- ????????err?=?clGetPlatformInfo(platforms[i],?????????????
- ????????????CL_PLATFORM_EXTENSIONS,?0,?NULL,?&ext_size);??????
- ????????if(err?<?0)???
- ????????{??
- ????????????perror("Couldn't?read?extension?data.");??????????????
- ????????????exit(1);??
- ????????}?????
- ??
- ????????printf("The?size?of?extension?data?is:?%d\n",?ext_size);//我的計算機顯示224.??
- ??
- ????????/*?Access?extension?data?*/????
- ????????//這里的ext_data相當于一個緩存,存儲相關信息。??
- ????????ext_data?=?(char*)malloc(ext_size);???
- ????????//這個函數就是獲取相關信息的函數,第二個參數指明了需要什么樣的信息,如這里的CL_PLATFORM_EXTENSIONS表示是opencl支持的擴展功能信息。我計算機輸出一大串,機器比較新(專門為了學圖形學而購置的電腦),支持的東西比較多。??
- ????????clGetPlatformInfo(platforms[i],?CL_PLATFORM_EXTENSIONS,???????
- ????????????ext_size,?ext_data,?NULL);????????????????
- ????????printf("Platform?%d?supports?extensions:?%s\n",?i,?ext_data);??
- ??
- ????????//這里是輸出生產商的名字,比如我顯卡信息是:NVIDIA?CUDA??
- ????????char?*name?=?(char*)malloc(ext_size);??
- ????????clGetPlatformInfo(platforms[i],?CL_PLATFORM_NAME,?????
- ????????????ext_size,?name,?NULL);????????????????
- ????????printf("Platform?%d?name:?%s\n",?i,?name);??
- ??
- ????????//這里是供應商信息,我顯卡信息:NVIDIA?Corporation??
- ????????char?*vendor?=?(char*)malloc(ext_size);??
- ????????clGetPlatformInfo(platforms[i],?CL_PLATFORM_VENDOR,???????
- ????????????ext_size,?vendor,?NULL);??????????????????
- ????????printf("Platform?%d?vendor:?%s\n",?i,?vendor);??
- ??
- ????????//最高支持的OpenCL版本,本機顯示:OpenCL1.1?CUDA?4.2.1??
- ????????char?*version?=?(char*)malloc(ext_size);??
- ????????clGetPlatformInfo(platforms[i],?CL_PLATFORM_VERSION,??????
- ????????????ext_size,?version,?NULL);?????????????????
- ????????printf("Platform?%d?version:?%s\n",?i,?version);??
- ??
- ????????//這個只有兩個值:full?profile?和?embeded?profile??
- ????????char?*profile?=?(char*)malloc(ext_size);??
- ????????clGetPlatformInfo(platforms[i],?CL_PLATFORM_PROFILE,??????
- ????????????ext_size,?profile,?NULL);?????????????????
- ????????printf("Platform?%d?full?profile?or?embeded?profile?:?%s\n",?i,?profile);??
- ??
- ????????/*?Look?for?ICD?extension?*/?????
- ????????//如果支持ICD這一擴展功能的platform,輸出顯示,本機的Intel和Nvidia都支持這一擴展功能??
- ????????if(strstr(ext_data,?icd_ext)?!=?NULL)???
- ????????????platform_index?=?i;??
- ????????std::cout<<"Platform_index?=?"<<platform_index<<std::endl;??
- ????????/*?Display?whether?ICD?extension?is?supported?*/??
- ????????if(platform_index?>?-1)??
- ????????????printf("Platform?%d?supports?the?%s?extension.\n",???
- ????????????platform_index,?icd_ext);??
- ??
- ????????std::cout<<std::endl;??
- ??
- ????????//釋放空間??
- ????????free(ext_data);??
- ????????free(name);??
- ????????free(vendor);??
- ????????free(version);??
- ????????free(profile);??
- ????}??
- ??????????
- ????if(platform_index?<=?-1)??
- ????????printf("No?platforms?support?the?%s?extension.\n",?icd_ext);??
- ??
- ????/*?Deallocate?resources?*/??
- ????free(platforms);??
- ????return?0;??
- }???
每個電腦的輸出結果不一樣的,我電腦的輸出結果是: