Project
Loading...
Searching...
No Matches
makefile_opencl_compiler.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#define CL_TARGET_OPENCL_VERSION 220
16#define _CRT_SECURE_NO_WARNINGS
17#include "CL/opencl.h"
18#include <cstdlib>
19#include <cstdio>
20#include <cstring>
21#include <string>
22#include <vector>
23
25
26#define quit(arg) \
27 { \
28 fprintf(stderr, arg "\n"); \
29 return (1); \
30 }
31#define DEFAULT_OPENCL_COMPILER_OPTIONS ""
32#define DEFAULT_OUTPUT_FILE "opencl.out"
33
34int32_t main(int argc, char** argv)
35{
36 const char* output_file = DEFAULT_OUTPUT_FILE;
37 std::string compiler_options = DEFAULT_OPENCL_COMPILER_OPTIONS;
38 std::vector<char*> files;
39
40 printf("Passing command line options:\n");
41 bool add_option = false;
42 for (int32_t i = 1; i < argc; i++) {
43 if (add_option) {
44 compiler_options += " ";
45 compiler_options += argv[i];
46 } else if (strcmp(argv[i], "--") == 0) {
47 add_option = true;
48 } else if (strcmp(argv[i], "-output-file") == 0) {
49 if (++i >= argc) {
50 quit("Output file name missing");
51 }
52 output_file = argv[i];
53 } else {
54 fprintf(stderr, "%s\n", argv[i]);
55 files.push_back(argv[i]);
56 }
57 }
58
59 cl_int ocl_error;
60 cl_uint num_platforms;
61 if (clGetPlatformIDs(0, nullptr, &num_platforms) != CL_SUCCESS) {
62 quit("Error getting OpenCL Platform Count");
63 }
64 if (num_platforms == 0) {
65 quit("No OpenCL Platform found");
66 }
67 printf("%d OpenCL Platforms found\n", num_platforms);
68
69 // Query platforms
70 cl_platform_id* platforms = new cl_platform_id[num_platforms];
71 if (platforms == nullptr) {
72 quit("Memory allocation error");
73 }
74 if (clGetPlatformIDs(num_platforms, platforms, nullptr) != CL_SUCCESS) {
75 quit("Error getting OpenCL Platforms");
76 }
77
78 cl_platform_id platform;
79 bool found = false;
80
82 for (uint32_t i_platform = 0; i_platform < num_platforms; i_platform++) {
83 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_PROFILE, 64, pinfo.platform_profile, nullptr);
84 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_VERSION, 64, pinfo.platform_version, nullptr);
85 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_NAME, 64, pinfo.platform_name, nullptr);
86 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_VENDOR, 64, pinfo.platform_vendor, nullptr);
87 printf("Available Platform %u: (%s %s) %s %s\n", i_platform, pinfo.platform_profile, pinfo.platform_version, pinfo.platform_vendor, pinfo.platform_name);
88 if (strcmp(pinfo.platform_vendor, "Advanced Micro Devices, Inc.") == 0 && strcmp(pinfo.platform_version, "OpenCL 2.0 AMD-APP (1800.8)") == 0) {
89 found = true;
90 printf("AMD OpenCL Platform found (%u)\n", i_platform);
91 platform = platforms[i_platform];
92 break;
93 }
94 }
95 if (found == false) {
96 quit("Did not find AMD OpenCL Platform");
97 }
98
99 if (clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, nullptr, &pinfo.count) != CL_SUCCESS) {
100 quit("Error getting OPENCL Device Count");
101 }
102
103 // Query devices
104 cl_device_id* devices = new cl_device_id[pinfo.count];
105 if (devices == nullptr) {
106 quit("Memory allocation error");
107 }
108 if (clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, pinfo.count, devices, nullptr) != CL_SUCCESS) {
109 quit("Error getting OpenCL devices");
110 }
111
113 cl_device_type device_type;
114 cl_uint freq, shaders;
115
116 printf("Available OPENCL devices:\n");
117 for (uint32_t i = 0; i < pinfo.count; i++) {
118 printf("Examining device %u\n", i);
119
120 clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 64, dinfo.device_name, nullptr);
121 clGetDeviceInfo(devices[i], CL_DEVICE_VENDOR, 64, dinfo.device_vendor, nullptr);
122 clGetDeviceInfo(devices[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, nullptr);
123 clGetDeviceInfo(devices[i], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(freq), &freq, nullptr);
124 clGetDeviceInfo(devices[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(shaders), &shaders, nullptr);
125 clGetDeviceInfo(devices[i], CL_DEVICE_ADDRESS_BITS, sizeof(dinfo.nbits), &dinfo.nbits, nullptr);
126 printf("Found Device %u : %s %s (Frequency %d, Shaders %d, %d bit)\n", i, dinfo.device_vendor, dinfo.device_name, (int32_t)freq, (int32_t)shaders, (int32_t)dinfo.nbits);
127 }
128
129 if (files.size() == 0) {
130 quit("Syntax: opencl [-output-file OUTPUT_FILE] FILE1 [FILE2] ... [FILEn] [-- COMPILER_OPTION_1] [COMPILER_OPTION_2] ... [COMPILER_OPTION_N]");
131 }
132
133 char** buffers = (char**)malloc(files.size() * sizeof(char*));
134 if (buffers == nullptr) {
135 quit("Memory allocation error\n");
136 }
137 for (uint32_t i = 0; i < files.size(); i++) {
138 printf("Reading source file %s\n", files[i]);
139 FILE* fp = fopen(files[i], "rb");
140 if (fp == nullptr) {
141 printf("Cannot open %s\n", files[i]);
142 free(buffers);
143 return (1);
144 }
145 fseek(fp, 0, SEEK_END);
146 size_t file_size = ftell(fp);
147 fseek(fp, 0, SEEK_SET);
148
149 buffers[i] = (char*)malloc(file_size + 1);
150 if (buffers[i] == nullptr) {
151 quit("Memory allocation error");
152 }
153 if (fread(buffers[i], 1, file_size, fp) != file_size) {
154 quit("Error reading file");
155 }
156 buffers[i][file_size] = 0;
157 fclose(fp);
158 }
159
160 printf("Creating OpenCL Context\n");
161 // Create OpenCL context
162 cl_context context = clCreateContext(nullptr, pinfo.count, devices, nullptr, nullptr, &ocl_error);
163 if (ocl_error != CL_SUCCESS) {
164 quit("Error creating OpenCL context");
165 }
166
167 printf("Creating OpenCL Program Object\n");
168 // Create OpenCL program object
169 cl_program program = clCreateProgramWithSource(context, (cl_uint)files.size(), (const char**)buffers, nullptr, &ocl_error);
170 if (ocl_error != CL_SUCCESS) {
171 quit("Error creating program object");
172 }
173
174 printf("Compiling OpenCL Program\n");
175 // Compile program
176 ocl_error = clBuildProgram(program, pinfo.count, devices, compiler_options.c_str(), nullptr, nullptr);
177 if (ocl_error != CL_SUCCESS) {
178 fprintf(stderr, "OpenCL Error while building program: %d (Compiler options: %s)\n", ocl_error, compiler_options.c_str());
179 fprintf(stderr, "OpenCL Kernel:\n\n");
180 for (uint32_t i = 0; i < files.size(); i++) {
181 printf("%s\n\n", buffers[i]);
182 }
183
184 for (uint32_t i = 0; i < pinfo.count; i++) {
185 cl_build_status status;
186 clGetProgramBuildInfo(program, devices[i], CL_PROGRAM_BUILD_STATUS, sizeof(status), &status, nullptr);
187 if (status == CL_BUILD_ERROR) {
188 size_t log_size;
189 clGetProgramBuildInfo(program, devices[i], CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size);
190 char* build_log = (char*)malloc(log_size + 1);
191 if (build_log == nullptr) {
192 quit("Memory allocation error");
193 }
194 clGetProgramBuildInfo(program, devices[i], CL_PROGRAM_BUILD_LOG, log_size, build_log, nullptr);
195 fprintf(stderr, "Build Log (device %d):\n\n%s\n\n", i, build_log);
196 free(build_log);
197 }
198 }
199 }
200 for (uint32_t i = 0; i < files.size(); i++) {
201 free(buffers[i]);
202 }
203 free(buffers);
204 if (ocl_error != CL_SUCCESS) {
205 return (1);
206 }
207
208 printf("Obtaining program binaries\n");
209 size_t* binary_sizes = (size_t*)malloc(pinfo.count * sizeof(size_t));
210 if (binary_sizes == nullptr) {
211 quit("Memory allocation error");
212 }
213 clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, pinfo.count * sizeof(size_t), binary_sizes, nullptr);
214 char** binary_buffers = (char**)malloc(pinfo.count * sizeof(char*));
215 if (binary_buffers == nullptr) {
216 quit("Memory allocation error");
217 }
218 for (uint32_t i = 0; i < pinfo.count; i++) {
219 printf("Binary size for device %d: %d\n", i, (int32_t)binary_sizes[i]);
220 binary_buffers[i] = (char*)malloc(binary_sizes[i]);
221 memset(binary_buffers[i], 0, binary_sizes[i]);
222 if (binary_buffers[i] == nullptr) {
223 quit("Memory allocation error");
224 }
225 }
226 clGetProgramInfo(program, CL_PROGRAM_BINARIES, pinfo.count * sizeof(char*), binary_buffers, nullptr);
227
228 printf("Programs obtained successfully, cleaning up opencl\n");
229 clReleaseProgram(program);
230 clReleaseContext(context);
231
232 printf("Writing binaries to file (%s)\n", output_file);
233 FILE* fp;
234 fp = fopen(output_file, "w+b");
235 if (fp == nullptr) {
236 quit("Error opening output file\n");
237 }
238 const char* magic_bytes = "QOCLPB";
239 fwrite(magic_bytes, 1, strlen(magic_bytes) + 1, fp);
240 fwrite(&pinfo, 1, sizeof(pinfo), fp);
241 for (uint32_t i = 0; i < pinfo.count; i++) {
242 clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 64, dinfo.device_name, nullptr);
243 clGetDeviceInfo(devices[i], CL_DEVICE_VENDOR, 64, dinfo.device_vendor, nullptr);
244 dinfo.binary_size = binary_sizes[i];
245 fwrite(&dinfo, 1, sizeof(dinfo), fp);
246 fwrite(binary_buffers[i], 1, binary_sizes[i], fp);
247 }
248 fclose(fp);
249
250 printf("All done, cleaning up remaining buffers\n");
251 for (uint32_t i = 0; i < pinfo.count; i++) {
252 free(binary_buffers[i]);
253 }
254 free(binary_sizes);
255 free(binary_buffers);
256
257 return (0);
258}
int32_t i
GLbitfield GLuint program
Definition glcorearb.h:1905
GLsizei GLsizei GLuint * shaders
Definition glcorearb.h:792
const GLuint * buffers
Definition glcorearb.h:656
#define DEFAULT_OPENCL_COMPILER_OPTIONS
#define quit(arg)
#define DEFAULT_OUTPUT_FILE
#define main