11 #ifndef DEVICE_SELECTION_H
12 #define DEVICE_SELECTION_H
16 #define _CRT_SECURE_NO_WARNINGS
24 #include <OpenCL/cl.h>
29 #define DS_DEVICE_NAME_LENGTH 256
33 DS_INVALID_PROFILE = 1000,
35 DS_INVALID_PERF_EVALUATOR_TYPE,
36 DS_INVALID_PERF_EVALUATOR,
37 DS_PERF_EVALUATOR_ERROR,
39 DS_UNKNOWN_DEVICE_TYPE,
40 DS_PROFILE_FILE_ERROR,
41 DS_SCORE_SERIALIZER_ERROR,
42 DS_SCORE_DESERIALIZER_ERROR
47 DS_DEVICE_NATIVE_CPU = 0,
48 DS_DEVICE_OPENCL_DEVICE
54 cl_device_id oclDeviceID;
56 char* oclDriverVersion;
62 unsigned int numDevices;
68 typedef ds_status (*ds_score_release)(
void* score);
69 static ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr) {
70 ds_status status = DS_SUCCESS;
71 if (profile != NULL) {
72 if (profile->devices != NULL && sr != NULL) {
74 for (i = 0; i < profile->numDevices; i++) {
75 free(profile->devices[i].oclDeviceName);
76 free(profile->devices[i].oclDriverVersion);
77 status = sr(profile->devices[i].score);
78 if (status != DS_SUCCESS)
81 free(profile->devices);
89 static ds_status initDSProfile(ds_profile** p,
const char* version) {
92 cl_platform_id* platforms = NULL;
93 cl_device_id* devices = NULL;
94 ds_status status = DS_SUCCESS;
98 if (p == NULL)
return DS_INVALID_PROFILE;
99 ds_profile* profile = (ds_profile*)malloc(
sizeof(ds_profile));
100 if (profile == NULL)
return DS_MEMORY_ERROR;
102 memset(profile, 0,
sizeof(ds_profile));
104 clGetPlatformIDs(0, NULL, &numPlatforms);
105 if (numPlatforms == 0)
108 platforms = (cl_platform_id*)malloc(numPlatforms*
sizeof(cl_platform_id));
109 if (platforms == NULL) {
110 status = DS_MEMORY_ERROR;
113 clGetPlatformIDs(numPlatforms, platforms, NULL);
116 for (i = 0; i < (
unsigned int)numPlatforms; i++) {
118 clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &num);
124 devices = (cl_device_id*)malloc(numDevices*
sizeof(cl_device_id));
125 if (devices == NULL) {
126 status = DS_MEMORY_ERROR;
130 profile->numDevices = numDevices+1;
132 (ds_device*)malloc(profile->numDevices *
sizeof(ds_device));
133 if (profile->devices == NULL) {
134 profile->numDevices = 0;
135 status = DS_MEMORY_ERROR;
138 memset(profile->devices, 0, profile->numDevices*
sizeof(ds_device));
141 for (i = 0; i < (
unsigned int)numPlatforms; i++) {
144 clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, numDevices, devices, &num);
145 for (j = 0; j < num; j++, next++) {
146 char buffer[DS_DEVICE_NAME_LENGTH];
149 profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE;
150 profile->devices[next].oclDeviceID = devices[j];
152 clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME,
153 DS_DEVICE_NAME_LENGTH, &buffer, NULL);
154 length = strlen(buffer);
155 profile->devices[next].oclDeviceName = (
char*)malloc(length+1);
156 memcpy(profile->devices[next].oclDeviceName, buffer, length+1);
158 clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION,
159 DS_DEVICE_NAME_LENGTH, &buffer, NULL);
160 length = strlen(buffer);
161 profile->devices[next].oclDriverVersion = (
char*)malloc(length+1);
162 memcpy(profile->devices[next].oclDriverVersion, buffer, length+1);
165 profile->devices[next].type = DS_DEVICE_NATIVE_CPU;
166 profile->version = version;
171 if (status == DS_SUCCESS) {
176 free(profile->devices);
187 typedef ds_status (*ds_perf_evaluator)(ds_device* device,
void* data);
191 ,DS_EVALUATE_NEW_ONLY
192 } ds_evaluation_type;
194 static ds_status profileDevices(ds_profile* profile,
195 const ds_evaluation_type type,
196 ds_perf_evaluator evaluator,
197 void* evaluatorData,
unsigned int* numUpdates) {
198 ds_status status = DS_SUCCESS;
200 unsigned int updates = 0;
202 if (profile == NULL) {
203 return DS_INVALID_PROFILE;
205 if (evaluator == NULL) {
206 return DS_INVALID_PERF_EVALUATOR;
209 for (i = 0; i < profile->numDevices; i++) {
210 ds_status evaluatorStatus;
213 case DS_EVALUATE_NEW_ONLY:
214 if (profile->devices[i].score != NULL)
break;
216 case DS_EVALUATE_ALL:
217 evaluatorStatus = evaluator(profile->devices+i, evaluatorData);
218 if (evaluatorStatus != DS_SUCCESS) {
219 status = evaluatorStatus;
225 return DS_INVALID_PERF_EVALUATOR_TYPE;
230 *numUpdates = updates;
235 #define DS_TAG_VERSION "<version>"
236 #define DS_TAG_VERSION_END "</version>"
237 #define DS_TAG_DEVICE "<device>"
238 #define DS_TAG_DEVICE_END "</device>"
239 #define DS_TAG_SCORE "<score>"
240 #define DS_TAG_SCORE_END "</score>"
241 #define DS_TAG_DEVICE_TYPE "<type>"
242 #define DS_TAG_DEVICE_TYPE_END "</type>"
243 #define DS_TAG_DEVICE_NAME "<name>"
244 #define DS_TAG_DEVICE_NAME_END "</name>"
245 #define DS_TAG_DEVICE_DRIVER_VERSION "<driver>"
246 #define DS_TAG_DEVICE_DRIVER_VERSION_END "</driver>"
248 #define DS_DEVICE_NATIVE_CPU_STRING "native_cpu"
252 typedef ds_status (*ds_score_serializer)(ds_device* device,
253 void** serializedScore,
254 unsigned int* serializedScoreSize);
255 static ds_status writeProfileToFile(ds_profile* profile,
256 ds_score_serializer serializer,
258 ds_status status = DS_SUCCESS;
260 if (profile == NULL)
return DS_INVALID_PROFILE;
262 FILE* profileFile = fopen(file,
"wb");
263 if (profileFile == NULL) {
264 status = DS_FILE_ERROR;
270 fwrite(DS_TAG_VERSION,
sizeof(
char), strlen(DS_TAG_VERSION), profileFile);
271 fwrite(profile->version,
sizeof(
char), strlen(profile->version), profileFile);
272 fwrite(DS_TAG_VERSION_END,
sizeof(
char), strlen(DS_TAG_VERSION_END), profileFile);
273 fwrite(
"\n",
sizeof(
char), 1, profileFile);
275 for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++) {
276 void* serializedScore;
277 unsigned int serializedScoreSize;
279 fwrite(DS_TAG_DEVICE,
sizeof(
char), strlen(DS_TAG_DEVICE), profileFile);
281 fwrite(DS_TAG_DEVICE_TYPE,
sizeof(
char), strlen(DS_TAG_DEVICE_TYPE),
283 fwrite(&profile->devices[i].type,
sizeof(ds_device_type),1, profileFile);
284 fwrite(DS_TAG_DEVICE_TYPE_END,
sizeof(
char),
285 strlen(DS_TAG_DEVICE_TYPE_END), profileFile);
287 switch(profile->devices[i].type) {
288 case DS_DEVICE_NATIVE_CPU:
301 case DS_DEVICE_OPENCL_DEVICE:
303 fwrite(DS_TAG_DEVICE_NAME,
sizeof(
char), strlen(DS_TAG_DEVICE_NAME),
305 fwrite(profile->devices[i].oclDeviceName,
306 sizeof(
char),strlen(profile->devices[i].oclDeviceName), profileFile);
307 fwrite(DS_TAG_DEVICE_NAME_END,
sizeof(
char),
308 strlen(DS_TAG_DEVICE_NAME_END), profileFile);
310 fwrite(DS_TAG_DEVICE_DRIVER_VERSION,
sizeof(
char),
311 strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile);
312 fwrite(profile->devices[i].oclDriverVersion,
sizeof(
char),
313 strlen(profile->devices[i].oclDriverVersion), profileFile);
314 fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END,
sizeof(
char),
315 strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile);
319 status = DS_UNKNOWN_DEVICE_TYPE;
323 fwrite(DS_TAG_SCORE,
sizeof(
char), strlen(DS_TAG_SCORE), profileFile);
324 status = serializer(profile->devices+i, &serializedScore,
325 &serializedScoreSize);
326 if (status == DS_SUCCESS && serializedScore != NULL &&
327 serializedScoreSize > 0) {
328 fwrite(serializedScore,
sizeof(
char), serializedScoreSize, profileFile);
329 free(serializedScore);
331 fwrite(DS_TAG_SCORE_END,
sizeof(
char), strlen(DS_TAG_SCORE_END), profileFile);
332 fwrite(DS_TAG_DEVICE_END,
sizeof(
char), strlen(DS_TAG_DEVICE_END), profileFile);
333 fwrite(
"\n",
sizeof(
char),1,profileFile);
341 static ds_status readProFile(
const char* fileName,
char** content,
342 size_t* contentSize) {
348 FILE* input = fopen(fileName,
"rb");
350 return DS_FILE_ERROR;
353 fseek(input, 0L, SEEK_END);
356 char* binary = (
char*)malloc(size);
357 if (binary == NULL) {
359 return DS_FILE_ERROR;
361 fread(binary,
sizeof(
char), size, input);
370 static const char* findString(
const char* contentStart,
const char* contentEnd,
371 const char*
string) {
373 const char* currentPosition;
376 stringLength = strlen(
string);
377 currentPosition = contentStart;
378 for(currentPosition = contentStart; currentPosition < contentEnd; currentPosition++) {
379 if (*currentPosition ==
string[0]) {
380 if (currentPosition+stringLength < contentEnd) {
381 if (strncmp(currentPosition,
string, stringLength) == 0) {
382 found = currentPosition;
392 typedef ds_status (*ds_score_deserializer)(ds_device* device,
393 const unsigned char* serializedScore,
394 unsigned int serializedScoreSize);
395 static ds_status readProfileFromFile(ds_profile* profile,
396 ds_score_deserializer deserializer,
399 ds_status status = DS_SUCCESS;
400 char* contentStart = NULL;
401 const char* contentEnd = NULL;
404 if (profile == NULL)
return DS_INVALID_PROFILE;
406 status = readProFile(file, &contentStart, &contentSize);
407 if (status == DS_SUCCESS) {
408 const char* currentPosition;
409 const char* dataStart;
411 size_t versionStringLength;
413 contentEnd = contentStart + contentSize;
414 currentPosition = contentStart;
418 dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION);
419 if (dataStart == NULL) {
420 status = DS_PROFILE_FILE_ERROR;
423 dataStart += strlen(DS_TAG_VERSION);
425 dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END);
426 if (dataEnd == NULL) {
427 status = DS_PROFILE_FILE_ERROR;
431 versionStringLength = strlen(profile->version);
432 if (versionStringLength!=(dataEnd-dataStart)
433 || strncmp(profile->version, dataStart, versionStringLength)!=0) {
435 status = DS_PROFILE_FILE_ERROR;
438 currentPosition = dataEnd+strlen(DS_TAG_VERSION_END);
444 const char* deviceTypeStart;
445 const char* deviceTypeEnd;
446 ds_device_type deviceType;
448 const char* deviceNameStart;
449 const char* deviceNameEnd;
451 const char* deviceScoreStart;
452 const char* deviceScoreEnd;
454 const char* deviceDriverStart;
455 const char* deviceDriverEnd;
457 dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE);
458 if (dataStart == NULL) {
462 dataStart+=strlen(DS_TAG_DEVICE);
463 dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END);
464 if (dataEnd == NULL) {
465 status = DS_PROFILE_FILE_ERROR;
470 deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE);
471 if (deviceTypeStart == NULL) {
472 status = DS_PROFILE_FILE_ERROR;
475 deviceTypeStart+=strlen(DS_TAG_DEVICE_TYPE);
476 deviceTypeEnd = findString(deviceTypeStart, contentEnd,
477 DS_TAG_DEVICE_TYPE_END);
478 if (deviceTypeEnd == NULL) {
479 status = DS_PROFILE_FILE_ERROR;
482 memcpy(&deviceType, deviceTypeStart,
sizeof(ds_device_type));
486 if (deviceType == DS_DEVICE_OPENCL_DEVICE) {
488 deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME);
489 if (deviceNameStart == NULL) {
490 status = DS_PROFILE_FILE_ERROR;
493 deviceNameStart+=strlen(DS_TAG_DEVICE_NAME);
494 deviceNameEnd = findString(deviceNameStart, contentEnd,
495 DS_TAG_DEVICE_NAME_END);
496 if (deviceNameEnd == NULL) {
497 status = DS_PROFILE_FILE_ERROR;
502 deviceDriverStart = findString(dataStart, contentEnd,
503 DS_TAG_DEVICE_DRIVER_VERSION);
504 if (deviceDriverStart == NULL) {
505 status = DS_PROFILE_FILE_ERROR;
508 deviceDriverStart+=strlen(DS_TAG_DEVICE_DRIVER_VERSION);
509 deviceDriverEnd = findString(deviceDriverStart, contentEnd,
510 DS_TAG_DEVICE_DRIVER_VERSION_END);
511 if (deviceDriverEnd == NULL) {
512 status = DS_PROFILE_FILE_ERROR;
517 for (i = 0; i < profile->numDevices; i++) {
518 if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) {
519 size_t actualDeviceNameLength;
520 size_t driverVersionLength;
522 actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName);
523 driverVersionLength = strlen(profile->devices[i].oclDriverVersion);
524 if (actualDeviceNameLength == (deviceNameEnd - deviceNameStart)
525 && driverVersionLength == (deviceDriverEnd - deviceDriverStart)
526 && strncmp(profile->devices[i].oclDeviceName, deviceNameStart,
527 actualDeviceNameLength)==0
528 && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart,
529 driverVersionLength)==0) {
530 deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
531 if (deviceNameStart == NULL) {
532 status = DS_PROFILE_FILE_ERROR;
535 deviceScoreStart+=strlen(DS_TAG_SCORE);
536 deviceScoreEnd = findString(deviceScoreStart, contentEnd,
538 status = deserializer(profile->devices+i,
539 (
const unsigned char*)deviceScoreStart,
540 deviceScoreEnd-deviceScoreStart);
541 if (status != DS_SUCCESS) {
549 else if (deviceType == DS_DEVICE_NATIVE_CPU) {
550 for (i = 0; i < profile->numDevices; i++) {
551 if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU) {
552 deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
553 if (deviceScoreStart == NULL) {
554 status = DS_PROFILE_FILE_ERROR;
557 deviceScoreStart+=strlen(DS_TAG_SCORE);
558 deviceScoreEnd = findString(deviceScoreStart, contentEnd,
560 status = deserializer(profile->devices+i,
561 (
const unsigned char*)deviceScoreStart,
562 deviceScoreEnd-deviceScoreStart);
563 if (status != DS_SUCCESS) {
571 currentPosition = dataEnd+strlen(DS_TAG_DEVICE_END);