admin
2023-01-02 954ead41d9391bca28a3cc4f9592f73f25b3bbc8
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#include <stdio.h>
#include <stdlib.h>
#include <CL/cl.h>
 
const int ARRAY_SIZE = 1000;
/*
1. ´´½¨Æ½Ì¨
2. ´´½¨É豸
3. ¸ù¾ÝÉ豸´´½¨ÉÏÏÂÎÄ
*/
cl_context CreateContext(cl_device_id* device) {
    cl_int errNum;
    cl_uint numPlateforms;
    cl_platform_id firstPlatformId;
    cl_context context = NULL;
    errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlateforms);
 
    if (errNum != CL_SUCCESS || numPlateforms <= 0) {
        printf("Failed to find any OpenCL platforms.\n");
        return NULL;
    }
    errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_GPU, 1, device, NULL);
    if (errNum != CL_SUCCESS) {
        printf("There is no GPU , trying CPU...\n");
        errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_CPU, 1, device, NULL);
 
    }
    if (errNum != CL_SUCCESS) {
        printf("There is NO CPU or GPU\n");
        return NULL;
    }
    context = clCreateContext(NULL, 1, device, NULL, NULL, &errNum);
    if (errNum != CL_SUCCESS) {
        printf("Create context error\n");
        return NULL;
    }
    return context;
}
/*
@ ÔÚÉÏÏÂÎÄ¿ÉÓõĵÚÒ»¸öÉ豸Öд´½¨ÃüÁî¶ÓÁÐ
*/
 
cl_command_queue CreateCommandQueue(cl_context context, cl_device_id device) {
    cl_int errNum;
    cl_command_queue commandQueue = NULL;
    //commandQueue = clCreateCommandQueue(context, device, 0, NULL);
    // OpenCL 2.0 µÄÓ÷¨
    commandQueue = clCreateCommandQueueWithProperties(context, device, 0, NULL);
    if (commandQueue == NULL) {
        printf("Failed to create commandQueue for device 0\n");
        return NULL;
    }
    return commandQueue;
}
 
char* ReadKernelSourceFile(const char* filename, size_t* length) {
    FILE* file = NULL;
    size_t sourceLenth;
    char* sourceString;
    int ret;
    fopen_s(&file, filename, "rb");
 
    if (file == NULL) {
        printf("%s at %d : Can't open %s \n", __FILE__, __LINE__ - 2, filename);
        return NULL;
    }
    //ÖØ¶¨Î»µ½Îļþĩβ
    fseek(file, 0, SEEK_END);
    sourceLenth = ftell(file);
    //ÖØ¶¨Î»µ½Îļþ¿ªÍ·
    fseek(file, 0, SEEK_SET);
    sourceString = (char*)malloc(sourceLenth + 1);
    sourceString[0] = '\0';
    ret = fread(sourceString, sourceLenth, 1, file);
    if (ret == 0) {
        printf("%s at %d : Cant't read source %s\n", __FILE__, __LINE__ - 2, filename);
        return NULL;
    }
    fclose(file);
    if (length != 0) {
        *length = sourceLenth;
    }
    sourceString[sourceLenth] = '\0';
    return sourceString;
 
 
}
cl_program CreateProgram(cl_context context, cl_device_id device, const char* filename) {
    cl_int errNum;
    cl_program program;
    //¼Ç¼´óСµÄÊý¾ÝÀàÐÍ
    size_t program_length;
    char* const source = ReadKernelSourceFile(filename, &program_length);
    program = clCreateProgramWithSource(context, 1, (const char**)&source, NULL, NULL);
 
    if (program == NULL) {
        printf("Failed to creae CL program from source.\n");
        return NULL;
    }
    errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
    if (errNum != CL_SUCCESS) {
        char buildLog[16384];
        clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, sizeof(buildLog), buildLog, NULL);
        printf("Error in kernel : %s \n", buildLog);
        clReleaseProgram(program);
        return NULL;
    }
    return program;
}
/*
@ ´´½¨ÄÚ´æ¶ÔÏó
*/
bool  CreateMemObjects(cl_context context, cl_mem memObjects[3], float* a, float* b) {
    memObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * ARRAY_SIZE, a, NULL);
    memObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * ARRAY_SIZE, b, NULL);
    memObjects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * ARRAY_SIZE, NULL, NULL);
    if (memObjects[0] == NULL || memObjects[1] == NULL || memObjects[2] == NULL) {
        printf("Error creating memeory objects.\n");
        return false;
 
    }
    return true;
}
/*
@ Çå³þOpenCL×ÊÔ´
*/
void CleanUp(cl_context context, cl_command_queue commandQueue, cl_program program, cl_kernel kernel, cl_mem memObjects[3]) {
    for (int i = 0; i < 3; i++) {
        if (memObjects[i] != 0) {
            clReleaseMemObject(memObjects[i]);
        }
    }
 
    if (commandQueue != 0) {
        clReleaseCommandQueue(commandQueue);
    }
    if (kernel != 0) {
        clReleaseKernel(kernel);
    }
    if (program != 0) {
        clReleaseProgram(program);
    }
    if (context != 0) {
        clReleaseContext(context);
    }
}
 
/*mainº¯Êý*/
int main__(int argc, char** agrv) {
    cl_context context = 0;
    cl_command_queue commandQueue = 0;
    cl_program program = 0;
    cl_device_id device = 0;
    cl_kernel kernel = 0;
    cl_mem memObjects[3] = { 0,0,0 };
    cl_int errNum;
    //´´½¨OpenCLÉÏÏÂÎÄ
    context = CreateContext(&device);
    if (context == NULL) {
        printf("Failed to create OpenCL context\n");
        return 1;
    }
    //»ñµÃOpenCLÉ豸£¬²¢´´½¨ÃüÁî¶ÓÁÐ
    commandQueue = CreateCommandQueue(context, device);
    if (commandQueue == NULL) {
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
    }
    //´´½¨OpenCL³ÌÐò
    program = CreateProgram(context, device, "kernel.cl");
    if (program == NULL) {
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
    }
    kernel = clCreateKernel(program, "vector_add", NULL);
    if (kernel == NULL) {
        printf("Failed to create kernel\n");
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
 
    }
    //´´½¨OpenCLÄÚ´æ¶ÔÏó
    float result[ARRAY_SIZE];
    float a[ARRAY_SIZE];
    float b[ARRAY_SIZE];
    for (int i = 0; i < ARRAY_SIZE; i++) {
        a[i] = (float)i;
        b[i] = (float)(i * 2);
    }
    if (!CreateMemObjects(context, memObjects, a, b)) {
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
    }
    //ÉèÖÃÄں˲ÎÊý
    errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObjects[0]);
    errNum |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObjects[1]);
    errNum |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObjects[2]);
 
    if (errNum != CL_SUCCESS) {
        printf("Error setting kernel arguments.\n");
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
    }
    size_t globalWorkSize[1] = { ARRAY_SIZE };
    size_t localWorkSize[1] = { 1 };
    //Ö´ÐÐÄÚºË
    errNum = clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL, globalWorkSize, localWorkSize, 0, NULL, NULL);
    if (errNum != CL_SUCCESS) {
        printf("Error queueing kernel for execution\n");
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
    }
    //½«¼ÆËãµÄ½á¹û¿½±´µ½Ö÷»úÉÏ
    errNum = clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE, 0, ARRAY_SIZE * sizeof(float), result, 0, NULL, NULL);
    if (errNum != CL_SUCCESS) {
        printf("Error reading result buffer.\n");
        CleanUp(context, commandQueue, program, kernel, memObjects);
        return 1;
    }
    for (int i = 0; i < ARRAY_SIZE; i++) {
        printf("i=%d:%f\n", i, result[i]);
    }
    printf("Executed program succesfully\n");
    CleanUp(context, commandQueue, program, kernel, memObjects);
    return 0;
}