日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCL 第5课:向量相加

發布時間:2023/12/13 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCL 第5课:向量相加 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCL程序分為兩個部份,一部份是內核代碼,負責具體算法。另一部份是主程序負責初始化OpenCL和準備數據。主程序加載內核代碼,并按照即定方法進行運算。

內核代碼可以寫在主程序里面,也可以寫在另一個文本文件里,有點像DX中的HLSL和OPENGL里的GLSL。哈哈,明白意思就行了。我們用第一種方法,把代碼跟源程序分開寫。

調用OpenCL大至分7個步驟

1:初始化OpenCL

2:創建上下文設備

3:創建命令隊列

4:創建數據緩沖區

5:將數據上傳到緩沖區

6:加載編譯代碼,創建內核調用函數

7:設置參數,執行內核

8:讀回計算結果。

下面我們通過一個向量相加的程序來了解OpenCL 。有A,B兩個四維向量,相加后值存在C向量里。OpenCL會根據用戶提供的維數,將向量分解成多個任務分發給多個CPU計算。

源碼分兩部份

(一)vecadd.cl核心代碼。

?
1 2 3 4 5 6 7 8 __kernel void vecAdd(__global int* A, ????????__global int* B, ????????__global int* C) { ????//獲取當前工作項所在位置(線程索引號) ????int idx = get_global_id(0); ????C[idx] = A[idx] + B[idx]; }

__kernel 指明這是一個OpenCL內核,__global 說明指針指向的是全局的設備內存空間,其它的就是C語言的函數的語法。kernel必須返回空類型。

?

(二)main.cpp代碼

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 #include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <CL/cl.h>//包含CL的頭文件 using namespace std; //四維向量 #define elements 4 //從外部文件獲取cl內核代碼 bool GetFileData(const char* fname,string& str) { ????FILE* fp = fopen(fname,"r"); ????if(fp==NULL) ????{ ????????printf("no found file\n"); ????????return false; ????} ????int n=0; ????while(feof(fp)==0) ????{ ????????str += fgetc(fp); ????} ????return true; } int main() { ????//先讀外部CL核心代碼,如果失敗則退出。 ????//代碼存buf_code里面 ????string code_file; ????if(false == GetFileData("vecadd.cl",code_file)) ????????return 0; ????char* buf_code = new char[code_file.size()]; ????strcpy(buf_code,code_file.c_str()); ????buf_code[code_file.size()-1] = NULL; ????//聲明CL所需變量。 ????cl_device_id device; ????cl_platform_id platform_id = NULL; ????cl_context context; ????cl_command_queue cmdQueue; ????cl_mem bufferA,bufferB,bufferC; ????cl_program program; ????cl_kernel kernel = NULL; ????//我們使用的是一維向量 ????//設定向量大小(維數) ????size_t globalWorkSize[1]; ????globalWorkSize[0] = elements; ????cl_int err; ????/* ????????定義輸入變量和輸出變量,并設定初值 ????*/ ????int* buf_A = new int[elements]; ????int* buf_B = new int[elements]; ????int* buf_C = new int[elements]; ????size_t datasize = sizeof(int) * elements; ????buf_A[0] = 1; ????buf_A[1] = 2; ????buf_A[2] = 3; ????buf_A[3] = 4; ????buf_B[0] = 5; ????buf_B[1] = 6; ????buf_B[2] = 7; ????buf_B[3] = 8; ????//step 1:初始化OpenCL ????err = clGetPlatformIDs(1,&platform_id,NULL); ????if(err!=CL_SUCCESS) ????{ ????????cout<<"clGetPlatformIDs error"<<endl; ????????return 0; ????} ????//這次我們只用CPU來進行并行運算,當然你也可以該成GPU ????clGetDeviceIDs(platform_id,CL_DEVICE_TYPE_CPU,1,&device,NULL); ????//step 2:創建上下文 ????context = clCreateContext(NULL,1,&device,NULL,NULL,NULL); ????//step 3:創建命令隊列 ????cmdQueue = clCreateCommandQueue(context,device,0,NULL); ????//step 4:創建數據緩沖區 ????bufferA = clCreateBuffer(context, ?????????????????????????????CL_MEM_READ_ONLY, ?????????????????????????????datasize,NULL,NULL); ????bufferB = clCreateBuffer(context, ?????????????????????????????CL_MEM_READ_ONLY, ?????????????????????????????datasize,NULL,NULL); ????bufferC = clCreateBuffer(context, ?????????????????????????????CL_MEM_WRITE_ONLY, ?????????????????????????????datasize,NULL,NULL); ????//step 5:將數據上傳到緩沖區 ????clEnqueueWriteBuffer(cmdQueue, ?????????????????????????bufferA,CL_FALSE, ?????????????????????????0,datasize, ?????????????????????????buf_A,0, ?????????????????????????NULL,NULL); ????clEnqueueWriteBuffer(cmdQueue, ?????????????????????????bufferB,CL_FALSE, ?????????????????????????0,datasize, ?????????????????????????buf_B,0, ?????????????????????????NULL,NULL); ????//step 6:加載編譯代碼,創建內核調用函數 ????program = clCreateProgramWithSource(context,1, ????????????????????????????????????????(const char**)&buf_code, ????????????????????????????????????????NULL,NULL); ????clBuildProgram(program,1,&device,NULL,NULL,NULL); ????kernel = clCreateKernel(program,"vecAdd",NULL); ????//step 7:設置參數,執行內核 ????clSetKernelArg(kernel,0,sizeof(cl_mem),&bufferA); ????clSetKernelArg(kernel,1,sizeof(cl_mem),&bufferB); ????clSetKernelArg(kernel,2,sizeof(cl_mem),&bufferC); ????clEnqueueNDRangeKernel(cmdQueue,kernel, ???????????????????????????1,NULL, ???????????????????????????globalWorkSize, ???????????????????????????NULL,0,NULL,NULL); ????//step 8:取回計算結果 ????clEnqueueReadBuffer(cmdQueue,bufferC,CL_TRUE,0, ????????????????????????datasize,buf_C,0,NULL,NULL); ????//輸出計算結果 ????cout<<"["<<buf_A[0]<<","<<buf_A[1]<<","<<buf_A[2]<<","<<buf_A[3]<<"]+[" ????<<buf_B[0]<<","<<buf_B[1]<<","<<buf_B[2]<<","<<buf_B[3]<<"]=[" ????<<buf_C[0]<<","<<buf_C[1]<<","<<buf_C[2]<<","<<buf_C[3]<<"]"<<endl; ????//釋放所有調用和內存 ????clReleaseKernel(kernel); ????clReleaseProgram(program); ????clReleaseCommandQueue(cmdQueue); ????clReleaseMemObject(bufferA); ????clReleaseMemObject(bufferB); ????clReleaseMemObject(bufferC); ????clReleaseContext(context); ????delete buf_A; ????delete buf_B; ????delete buf_C; ????delete buf_code; ????return 0; }

運算結果:

?[1,2,3,4] + [5,6,7,8] = [6,8,10,12]

總結

以上是生活随笔為你收集整理的OpenCL 第5课:向量相加的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。