OpenCL內存對象:
OpenCL內存對象就是一些OpenCL數據,這些數據一般在設備內存中,能夠被拷入也能夠被拷出。OpenCL內存對象包括buffer對象和image對象。
buffer對象:連續的內存塊----順序存儲,能夠通過指針、行列式等直接訪問。
image對象:是2維或3維的內存對象,只能通過read_image() 或 write_image()來讀取。image對象可以是可讀或可寫的,但不能同時既可讀又可寫。
該函數會在指定的context上創建一個buffer對象,image對象相對比較復雜,留在后面再講。
flags參數指定buffer對象的讀寫屬性,host_ptr可以是NULL,如果不為NULL,一般是一個有效的host buffer對象,這時,函數創建OpenCL buffer對象后,會把對應host buffer的內容拷貝到OpenCL buffer中。
在Kernel執行之前,host中原始輸入數據必須顯式的傳到device中,Kernel執行完后,結果也要從device內存中傳回到host內存中。我們主要通過函數clEnqueue{Read|Write}{Buffer|Image}來實現這兩種操作。從host到device,我們用clEnqueueWrite,從device到host,我們用clEnqueueRead。clEnqueueWrite命令包括初始化內存對象以及把host 數據傳到device內存這兩種操作。當然,像前面一段說的那樣,也可以把host buffer指針直接用在CreateBuffer函數中來實現隱式的數據寫操作。
這個函數初始化OpenCL內存對象,並把相應的數據寫到OpenCL內存關聯的設備內存中。其中,blocking_write參數指定是數拷貝完成后函數才返回還是數據開始拷貝后就立即返回(阻塞模式於非阻塞模式)。Events參數指定這個函數執行之前,必須要完成的Event(比如先要創建OpenCL內存對象的Event)。
OpenCL程序對象:
程序對象就是通過讀入Kernel函數源代碼或二進制文件,然后在指定的設備上進行編譯而產生的OpenCL對象。
這個函數通過源代碼(strings),創建一個程序對象,其中counts指定源代碼串的數量,lengths指定源代碼串的長度(為NULL結束的串時,可以省略)。當然,我們還必須自己編寫一個從文件中讀取源代碼串的函數。
對context中的每個設備,這個函數編譯、連接源代碼對象,產生device可以執行的文件,對GPU而言就是設備對應shader匯編。如果device_list參數被提供,則只對這些設備進行編譯連接。options參數主要提供一些附加的編譯選項,比如宏定義、優化開關標志等等。
如果程序編譯失敗,我們能夠根據返回的狀態,通過調用clGetProgramBuildInfo來得到錯誤信息。
加上創建內存對象以及程序對象的代碼如下:
1:
2: #include "stdafx.h"
3: #include <CL/cl.h>
4: #include <stdio.h>
5: #include <stdlib.h>
6: #include <time.h>
7: #include <iostream>
8: #include <fstream>
9:
10: using namespace std;
11: #define NWITEMS 262144
12:
13: #pragma comment (lib,"OpenCL.lib")
14:
15: //把文本文件讀入一個string中
16: int convertToString(const char *filename, std::string& s)
17: {
18: size_t size;
19: char* str;
20:
21: std::fstream f(filename, (std::fstream::in | std::fstream::binary));
22:
23: if(f.is_open())
24: {
25: size_t fileSize;
26: f.seekg(0, std::fstream::end);
27: size = fileSize = (size_t)f.tellg();
28: f.seekg(0, std::fstream::beg);
29:
30: str = new char[size+1];
31: if(!str)
32: {
33: f.close();
34: return NULL;
35: }
36:
37: f.read(str, fileSize);
38: f.close();
39: str[size] = '\0';
40:
41: s = str;
42: delete[] str;
43: return 0;
44: }
45: printf("Error: Failed to open file %s\n", filename);
46: return 1;
47: }
48:
49: int main(int argc, char* argv[])
50: {
51: //在host內存中創建三個緩沖區
52: float *buf1 = 0;
53: float *buf2 = 0;
54: float *buf = 0;
55:
56: buf1 =(float *)malloc(NWITEMS * sizeof(float));
57: buf2 =(float *)malloc(NWITEMS * sizeof(float));
58: buf =(float *)malloc(NWITEMS * sizeof(float));
59:
60: //初始化buf1和buf2的內容
61: int i;
62: srand( (unsigned)time( NULL ) );
63: for(i = 0; i < NWITEMS; i++)
64: buf1[i] = rand()%65535;
65:
66: srand( (unsigned)time( NULL ) +1000);
67: for(i = 0; i < NWITEMS; i++)
68: buf2[i] = rand()%65535;
69:
70: cl_uint status;
71: cl_platform_id platform;
72:
73: //創建平台對象
74: status = clGetPlatformIDs( 1, &platform, NULL );
75:
76: cl_device_id device;
77:
78: //創建GPU設備
79: clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU,
80: 1,
81: &device,
82: NULL);
83: //創建context
84: cl_context context = clCreateContext( NULL,
85: 1,
86: &device,
87: NULL, NULL, NULL);
88: //創建命令隊列
89: cl_command_queue queue = clCreateCommandQueue( context,
90: device,
91: CL_QUEUE_PROFILING_ENABLE, NULL );
92: //創建三個OpenCL內存對象,並把buf1的內容通過隱式拷貝的方式
93: //拷貝到clbuf1,buf2的內容通過顯示拷貝的方式拷貝到clbuf2
94: cl_mem clbuf1 = clCreateBuffer(context,
95: CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
96: NWITEMS*sizeof(cl_float),buf1,
97: NULL );
98:
99: cl_mem clbuf2 = clCreateBuffer(context,
100: CL_MEM_READ_ONLY ,
101: NWITEMS*sizeof(cl_float),NULL,
102: NULL );
103:
104: status = clEnqueueWriteBuffer(queue, clbuf2, 1,
105: 0, NWITEMS*sizeof(cl_float), buf2, 0, 0, 0);
106:
107: cl_mem buffer = clCreateBuffer( context,
108: CL_MEM_WRITE_ONLY,
109: NWITEMS * sizeof(cl_float),
110: NULL, NULL );
111:
112: const char * filename = "add.cl";
113: std::string sourceStr;
114: status = convertToString(filename, sourceStr);
115: const char * source = sourceStr.c_str();
116: size_t sourceSize[] = { strlen(source) };
117:
118: //創建程序對象
119: cl_program program = clCreateProgramWithSource(
120: context,
121: 1,
122: &source,
123: sourceSize,
124: NULL);
125: //編譯程序對象
126: status = clBuildProgram( program, 1, &device, NULL, NULL, NULL );
127: if(status != 0)
128: {
129: printf("clBuild failed:%d\n", status);
130: char tbuf[0x10000];
131: clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0x10000, tbuf, NULL);
132: printf("\n%s\n", tbuf);
133: return -1;
134: }
135:
136:
137:
138: if(buf)
139: free(buf);
140: if(buf1)
141: free(buf1);
142: if(buf2)
143: free(buf2);
144:
145: //刪除OpenCL資源對象
146: clReleaseMemObject(clbuf1);
147: clReleaseMemObject(clbuf2);
148: clReleaseMemObject(buffer);
149: clReleaseProgram(program);
150: clReleaseCommandQueue(queue);
151: clReleaseContext(context);
152: return 0;
153: }
154: