-
Notifications
You must be signed in to change notification settings - Fork 12
/
immolate.c
285 lines (251 loc) · 11.9 KB
/
immolate.c
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#include "lib/immolate.h"
#include <time.h>
int main(int argc, char **argv) {
// Print version
printf_s("Immolate Beta v1.0.1f.1\n");
// Handle CLI arguments
unsigned int platformID = 0;
unsigned int deviceID = 0;
unsigned int numGroups = 16;
cl_char8 startingSeed;
for (int i = 0; i < 8; i++) {
startingSeed.s[i] = '\0';
};
cl_long numSeeds = 2318107019761;
cl_long cutoff = 1;
char* filter = "erratic_flush_five";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "-h")==0) {
printf_s("Valid command line arguments:\n-h Shows this help dialog.\n-f <F> Sets the filter used by Immolate to F. Defaults to erratic_flush_five.\n-s <S> Sets the starting seed to S. Defaults to empty seed. Use \"random\" for a random starting seed.\n-n <N> Sets the number of seeds to search to N. Defaults to full seed pool.\n-c <C> Sets the cutoff score for a seed to be printed to C. Defaults to 1.\n-p <P> Sets the platform ID of the CL device being used to P. Defaults to 0.\n-d <D> Sets the device ID of the CL device being used to D. Defaults to 0.\n-g <G> Sets the number of thread groups to G. Defaults to 16. Increasing this might help Immolate run faster.\n\n--list_devices Lists information about the detected CL devices.");
return 0;
}
if (strcmp(argv[i], "-p")==0) {
platformID = atoi(argv[i+1]);
i++;
}
if (strcmp(argv[i], "-f")==0) {
filter = argv[i+1];
i++;
}
if (strcmp(argv[i], "-d")==0) {
deviceID = atoi(argv[i+1]);
i++;
}
if (strcmp(argv[i], "-g")==0) {
numGroups = atoi(argv[i+1]);
i++;
}
if (strcmp(argv[i], "-n")==0) {
numSeeds = strtoll(argv[i+1], NULL, 10);
i++;
}
if (strcmp(argv[i], "-c")==0) {
cutoff = strtoll(argv[i+1], NULL, 10);
i++;
}
if (strcmp(argv[i], "-s")==0) {
if (strcmp(argv[i+1],"random")==0) {
srand(time(NULL));
char seedCharacters[] = {'1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for (int j = 0; j < 8; j++) {
startingSeed.s[j] = seedCharacters[rand() % 35];
}
} else if (strlen(argv[i+1]) <= 8) {
for (int j = 0; j < strlen(argv[i+1]); j++) {
startingSeed.s[j] = argv[i+1][j];
}
for (int j = strlen(argv[i+1]); j < 8; j++) {
startingSeed.s[j] = '\0';
}
} else {
printf_s("Warning: Inputted seed is not valid, ignoring...\n");
}
i++;
}
if (strcmp(argv[i], "--list_devices")==0) {
cl_int err;
char buf[1024];
cl_uint temp_int;
// Get # of OpenCL Platforms
cl_uint numPlatforms;
err = clGetPlatformIDs(0, NULL, &numPlatforms);
clErrCheck(err, "clGetPlatformIDs - Getting number of available OpenCL platforms");
// Nothing available? Then leave!
if (numPlatforms == 0) {
printf_s("No OpenCL devices found.\n");
return 0;
}
// Now get OpenCL Platforms
cl_platform_id* platforms = malloc(sizeof(cl_platform_id) * numPlatforms);
err = clGetPlatformIDs(numPlatforms, platforms, NULL);
clErrCheck(err, "clGetPlatformIDs - Getting list of availble OpenCL platforms");
int foundDevice = 0;
for (unsigned int p = 0; p < numPlatforms; p++) {
//Now we do the same thing for devices...
cl_uint numDevices;
err = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
clErrCheck(err, "clGetDeviceIDs - Getting number of available OpenCL devices");
if (numDevices > 0) foundDevice = 1;
cl_device_id* devices = malloc(sizeof(cl_device_id) * numDevices);
err = clGetDeviceIDs(platforms[p], CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);
clErrCheck(err, "clGetDeviceIDs - Getting list of available OpenCL devices");
for (unsigned int d = 0; d < numDevices; d++) {
printf_s("Platform ID %i, Device ID %i\n", p, d);
// Get Device Info
err = clGetDeviceInfo(devices[d], CL_DEVICE_NAME, sizeof(buf), &buf, NULL);
clErrCheck(err, "clGetDeviceInfo - Getting device name");
printf_s("Name: %s\n", buf);
err = clGetDeviceInfo(devices[d], CL_DEVICE_VENDOR, sizeof(buf), &buf, NULL);
clErrCheck(err, "clGetDeviceInfo - Getting device vendor");
printf_s("Vendor: %s\n", buf);
err = clGetDeviceInfo(devices[d], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(temp_int), &temp_int, NULL);
clErrCheck(err, "clGetDeviceInfo - Getting device compute units");
printf_s("Compute Units: %i\n", temp_int);
err = clGetDeviceInfo(devices[d], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(temp_int), &temp_int, NULL);
clErrCheck(err, "clGetDeviceInfo - Getting device clock frequency");
printf_s("Clock Frequency: %iMHz\n", temp_int);
}
}
if (foundDevice == 0) {
printf_s("No OpenCL devices found.\n");
}
return 0;
}
}
cl_int err;
// Load the kernel source code into the array ssKernel
FILE *fp;
char *ssKernelCode;
char *ssKernelBuf;
size_t ssKernelSize;
// Get CWD
char executable_dir[MAX_PATH];
char include_path[MAX_PATH+6];
char kernel_path[MAX_PATH+12];
getExecutableDir(executable_dir);
strcpy_s(include_path, sizeof include_path, "-I \"");
strcat_s(include_path, sizeof include_path, executable_dir);
strcat_s(include_path, sizeof include_path, "\"");
strcpy_s(kernel_path, sizeof kernel_path, executable_dir);
strcat_s(kernel_path, sizeof kernel_path, PATH_SEPARATOR);
strcat_s(kernel_path, sizeof kernel_path, "search.cl");
fp = fopen(kernel_path, "r");
if (!fp) {
printf_s("Warning: Kernel not found at ");
printf_s("%s", kernel_path);
printf_s(", attempting working directory...\n");
fp = fopen("search.cl","r");
if (!fp) {
fprintf_s(stderr, "Failed to load kernel.\n");
exit(1);
}
}
ssKernelCode = (char*)malloc(MAX_CODE_SIZE);
ssKernelBuf = (char*)malloc(MAX_CODE_SIZE);
// Set include information
strcpy_s(ssKernelCode, MAX_CODE_SIZE, "#include \"filters/");
strcat_s(ssKernelCode, MAX_CODE_SIZE, filter);
strcat_s(ssKernelCode, MAX_CODE_SIZE, ".cl\"\n\n");
size_t bytes_read = fread( ssKernelBuf, 1, MAX_CODE_SIZE - 1, fp);
ssKernelBuf[bytes_read] = '\0';
strcat_s(ssKernelCode, MAX_CODE_SIZE, ssKernelBuf);
ssKernelSize = strlen(ssKernelCode);
fclose( fp );
free(ssKernelBuf);
// Set up platform and device based on CLI args
// Get # of OpenCL Platforms
cl_uint numPlatforms;
err = clGetPlatformIDs(0, NULL, &numPlatforms);
clErrCheck(err, "clGetPlatformIDs - Getting number of available OpenCL platforms");
// Nothing available? Then leave!
if (numPlatforms == 0) {
printf_s("No OpenCL platforms found.\n");
return 0;
}
if (platformID > numPlatforms-1) {
printf_s("Platform ID %i not found.\n", platformID);
return 0;
}
// Now get OpenCL Platforms
cl_platform_id* platforms = malloc(sizeof(cl_platform_id) * numPlatforms);
err = clGetPlatformIDs(numPlatforms, platforms, NULL);
clErrCheck(err, "clGetPlatformIDs - Getting list of availble OpenCL platforms");
cl_platform_id platform = platforms[platformID];
//Now we do the same thing for devices...
cl_uint numDevices;
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
clErrCheck(err, "clGetDeviceIDs - Getting number of available OpenCL devices");
if (numDevices == 0) {
printf_s("No OpenCL devices found for platform %i.\n", platformID);
return 0;
}
if (deviceID > numDevices-1) {
printf_s("Device ID %i not found.\n", deviceID);
return 0;
}
cl_device_id* devices = malloc(sizeof(cl_device_id) * numDevices);
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, numDevices, devices, NULL);
clErrCheck(err, "clGetDeviceIDs - Getting list of available OpenCL devices");
cl_device_id device = devices[deviceID];
// Create an OpenCL context
cl_context ctx = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
clErrCheck(err, "clCreateContext - Creating OpenCL context");
// Create a command queue
cl_command_queue queue = clCreateCommandQueue(ctx, device, 0, &err);
clErrCheck(err, "clCreateCommandQueue - Creating OpenCL command queue");
// Create a program from kernel source
cl_program ssKernelProgram = clCreateProgramWithSource(ctx, 1, (const char**)&ssKernelCode, (const size_t*)&ssKernelSize, &err);
clErrCheck(err, "clCreateProgramWithSource - Creating OpenCL program");
// Build the program
printf_s("Building program...\n");
err = clBuildProgram(ssKernelProgram, 1, &device, include_path, NULL, NULL);
if (err == CL_BUILD_PROGRAM_FAILURE) { //print build log on error
size_t logLength = 0;
err = clGetProgramBuildInfo(ssKernelProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logLength);
if (err != CL_SUCCESS) {
printf_s("Error getting build log length: %d\n", err);
return EXIT_FAILURE;
}
char *buf = calloc(logLength, sizeof(char));
err = clGetProgramBuildInfo(ssKernelProgram, device, CL_PROGRAM_BUILD_LOG, logLength, buf, NULL);
if (err != CL_SUCCESS) {
printf_s("Error getting build log: %d\n", err);
return EXIT_FAILURE;
}
printf_s("%s", buf);
printf_s("\n");
}
clErrCheck(err, "clBuildProgram - Building OpenCL program");
// Create OpenCL kernel
cl_kernel ssKernel = clCreateKernel(ssKernelProgram, "search", &err);
clErrCheck(err, "clCreateKernel - Creating OpenCL kernel");
// Set arguments
err = clSetKernelArg(ssKernel, 0, sizeof(startingSeed), &startingSeed);
clErrCheck(err, "clSetKernelArg - Adding starting seed argument");
err = clSetKernelArg(ssKernel, 1, sizeof(numSeeds), &numSeeds);
clErrCheck(err, "clSetKernelArg - Adding number of seeds argument");
// Loading a writable buffer to the kernel
cl_mem cutoffBuf = clCreateBuffer(ctx, CL_MEM_READ_WRITE, sizeof(long), NULL, &err);
clErrCheck(err, "clCreateBuffer - Creating cutoff buffer");
clEnqueueWriteBuffer(queue, cutoffBuf, CL_TRUE, 0, sizeof(long), &cutoff, 0, NULL, NULL);
err = clSetKernelArg(ssKernel, 2, sizeof(cl_mem), &cutoffBuf);
clErrCheck(err, "clSetKernelArg - Adding cutoff argument");
// Execute OpenCL kernel
size_t globalSize = numGroups * numGroups;
size_t localSize = numGroups;
printf_s("Starting searcher...\n");
clock_t begin = clock();
err = clEnqueueNDRangeKernel(queue, ssKernel, 1, NULL, &globalSize, &localSize, 0, NULL, NULL);
clErrCheck(err, "clEnqueueNDRangeKernel - Executing OpenCL kernel");
// Clean up
err = clFlush(queue);
err = clFinish(queue);
err = clReleaseKernel(ssKernel);
err = clReleaseProgram(ssKernelProgram);
err = clReleaseCommandQueue(queue);
err = clReleaseContext(ctx);
clock_t end = clock();
double time_spent = (double)(end-begin) / CLOCKS_PER_SEC;
printf("Done in %fs",time_spent);
return EXIT_SUCCESS;
}