Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #ifdef _WIN32
11 : #include <windows.h>
12 : #elif defined __MACH__
13 : #include <mach/mach_time.h>
14 : #else
15 : #include <sys/time.h>
16 : #endif
17 : #include <time.h>
18 : #include <math.h>
19 : #include <float.h>
20 : #include <iostream>
21 : #include <sstream>
22 : #include <vector>
23 : #include <boost/scoped_ptr.hpp>
24 :
25 : #include "opencl_device.hxx"
26 :
27 :
28 : #define INPUTSIZE 15360
29 : #define OUTPUTSIZE 15360
30 :
31 : #define STRINGIFY(...) #__VA_ARGS__"\n"
32 : //#define LOG_PRINTF(x) (std::cout << x << std::endl)
33 : #define LOG_PRINTF(x)
34 :
35 : #define DS_CHECK_STATUS(status, name) \
36 : if (CL_SUCCESS != status) \
37 : { \
38 : LOG_PRINTF("[OCL] Error code is " << status << " at " << name); \
39 : }
40 :
41 : namespace sc { namespace OpenCLDevice {
42 :
43 : bool bIsInited = false;
44 : bool bIsDeviceSelected = false;
45 : ds_device selectedDevice;
46 :
47 : struct LibreOfficeDeviceScore
48 : {
49 : double fTime; // small time means faster device
50 : bool bNoCLErrors; // were there any opencl errors
51 : };
52 :
53 0 : struct LibreOfficeDeviceEvaluationIO
54 : {
55 : std::vector<double> input0;
56 : std::vector<double> input1;
57 : std::vector<double> input2;
58 : std::vector<double> input3;
59 : std::vector<double> output;
60 : unsigned long inputSize;
61 : unsigned long outputSize;
62 : };
63 :
64 : struct timer
65 : {
66 : #ifdef _WIN32
67 : LARGE_INTEGER start;
68 : #else
69 : long long start;
70 : #endif
71 : };
72 :
73 : const char* source = STRINGIFY(
74 : \n#if defined(KHR_DP_EXTENSION)
75 : \n#pragma OPENCL EXTENSION cl_khr_fp64 : enable
76 : \n#elif defined(AMD_DP_EXTENSION)
77 : \n#pragma OPENCL EXTENSION cl_amd_fp64 : enable
78 : \n#endif
79 : \n
80 : int isNan(fp_t a) { return a != a; }
81 : fp_t fsum(fp_t a, fp_t b) { return a + b; }
82 :
83 : fp_t fAverage(__global fp_t* input)
84 : {
85 : fp_t sum = 0;
86 : int count = 0;
87 : for (int i = 0; i < INPUTSIZE; i++)
88 : {
89 : if (!isNan(input[i]))
90 : {
91 : sum = fsum(input[i], sum);
92 : count += 1;
93 : }
94 : }
95 : return sum / (fp_t)count;
96 : }
97 : fp_t fMin(__global fp_t* input)
98 : {
99 : fp_t min = MAXFLOAT;
100 : for (int i = 0; i < INPUTSIZE; i++)
101 : {
102 : if (!isNan(input[i]))
103 : {
104 : min = fmin(input[i], min);
105 : }
106 : }
107 : return min;
108 : }
109 : fp_t fSoP(__global fp_t* input0, __global fp_t* input1)
110 : {
111 : fp_t sop = 0.0;
112 : for (int i = 0; i < INPUTSIZE; i++)
113 : {
114 : sop += (isNan(input0[i]) ? 0 : input0[i]) * (isNan(input1[i]) ? 0 : input1[i]);
115 : }
116 : return sop;
117 : }
118 : __kernel void DynamicKernel(
119 : __global fp_t* result, __global fp_t* input0, __global fp_t* input1, __global fp_t* input2, __global fp_t* input3)
120 : {
121 : int gid0 = get_global_id(0);
122 : fp_t tmp0 = fAverage(input0);
123 : fp_t tmp1 = fMin(input1) * fSoP(input2, input3);
124 : result[gid0] = fsum(tmp0, tmp1);
125 : }
126 : );
127 :
128 0 : size_t sourceSize[] = { strlen(source) };
129 :
130 : /*************************************************************************/
131 : /* INTERNAL FUNCTIONS */
132 : /*************************************************************************/
133 : /* Timer functions - start timer */
134 0 : void timerStart(timer* mytimer)
135 : {
136 : #ifdef _WIN32
137 : QueryPerformanceCounter(&mytimer->start);
138 : #elif defined __MACH__
139 : mytimer->start = mach_absolute_time();
140 : #else
141 : struct timespec s;
142 0 : clock_gettime(CLOCK_MONOTONIC, &s);
143 0 : mytimer->start = (long long)s.tv_sec * (long long)1.0E6 + (long long)s.tv_nsec / (long long)1.0E3;
144 : #endif
145 0 : }
146 :
147 : /* Timer functions - get current value */
148 0 : double timerCurrent(timer* mytimer)
149 : {
150 : #ifdef _WIN32
151 : LARGE_INTEGER stop, frequency;
152 : QueryPerformanceCounter(&stop);
153 : QueryPerformanceFrequency(&frequency);
154 : double time = ((double)(stop.QuadPart - mytimer->start.QuadPart) / frequency.QuadPart);
155 : #elif defined __MACH__
156 : static mach_timebase_info_data_t info = { 0, 0 };
157 : if (info.numer == 0)
158 : mach_timebase_info(&info);
159 : long long stop = mach_absolute_time();
160 : double time = ((stop - mytimer->start) * (double) info.numer / info.denom) / 1.0E9;
161 : #else
162 : struct timespec s;
163 : long long stop;
164 0 : clock_gettime(CLOCK_MONOTONIC, &s);
165 0 : stop = (long long)s.tv_sec * (long long)1.0E6 + (long long)s.tv_nsec / (long long)1.0E3;
166 0 : double time = ((double)(stop - mytimer->start) / 1.0E6);
167 : #endif
168 0 : return time;
169 : }
170 :
171 : /* Random number generator */
172 0 : double random(double min, double max)
173 : {
174 0 : return floor(((double)rand() / ((unsigned int)RAND_MAX + 1)) * (max - min + 1) + min);
175 : }
176 :
177 : /* Populate input */
178 0 : void populateInput(LibreOfficeDeviceEvaluationIO* testData)
179 : {
180 0 : srand((unsigned int)time(NULL));
181 0 : double* input0 = &testData->input0[0];
182 0 : double* input1 = &testData->input1[0];
183 0 : double* input2 = &testData->input2[0];
184 0 : double* input3 = &testData->input3[0];
185 0 : for (unsigned long i = 0; i < testData->inputSize; i++)
186 : {
187 0 : input0[i] = random(0, i);
188 0 : input1[i] = random(0, i);
189 0 : input2[i] = random(0, i);
190 0 : input3[i] = random(0, i);
191 : }
192 0 : }
193 : /* Encode score object as byte string */
194 0 : ds_status serializeScore(ds_device* device, void** serializedScore, unsigned int* serializedScoreSize)
195 : {
196 0 : *serializedScoreSize = sizeof(LibreOfficeDeviceScore);
197 0 : *serializedScore = (void*)new unsigned char[*serializedScoreSize];
198 0 : memcpy(*serializedScore, device->score, *serializedScoreSize);
199 0 : return DS_SUCCESS;
200 : }
201 :
202 : /* Parses byte string and stores in score object */
203 0 : ds_status deserializeScore(ds_device* device, const unsigned char* serializedScore, unsigned int serializedScoreSize)
204 : {
205 : // check that serializedScoreSize == sizeof(LibreOfficeDeviceScore);
206 0 : device->score = new LibreOfficeDeviceScore;
207 0 : memcpy(device->score, serializedScore, serializedScoreSize);
208 0 : return DS_SUCCESS;
209 : }
210 :
211 : /* Releases memory held by score */
212 0 : ds_status releaseScore(void* score)
213 : {
214 0 : if (NULL != score)
215 : {
216 0 : delete (LibreOfficeDeviceScore*)score;
217 : }
218 0 : return DS_SUCCESS;
219 : }
220 :
221 : /* Evaluate devices */
222 0 : ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
223 : {
224 0 : if (DS_DEVICE_OPENCL_DEVICE == device->type)
225 : {
226 : /* Evaluating an OpenCL device */
227 : LOG_PRINTF("[DS] Device: \"" << device->oclDeviceName << "\" (OpenCL) evaluation...");
228 : cl_int clStatus;
229 : cl_context clContext;
230 : cl_command_queue clQueue;
231 : cl_program clProgram;
232 : cl_kernel clKernel;
233 :
234 : /* Check for 64-bit float extensions */
235 0 : size_t aDevExtInfoSize = 0;
236 0 : clStatus = clGetDeviceInfo(device->oclDeviceID, CL_DEVICE_EXTENSIONS, 0, NULL, &aDevExtInfoSize);
237 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
238 :
239 0 : char* aExtInfo = new char[aDevExtInfoSize];
240 0 : clStatus = clGetDeviceInfo(device->oclDeviceID, CL_DEVICE_EXTENSIONS, sizeof(char) * aDevExtInfoSize, aExtInfo, NULL);
241 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
242 :
243 0 : bool bKhrFp64Flag = false;
244 0 : bool bAmdFp64Flag = false;
245 0 : const char* buildOption = NULL;
246 0 : std::string tmpStr("-Dfp_t=double -Dfp_t4=double4 -Dfp_t16=double16 -DINPUTSIZE=");
247 0 : std::ostringstream tmpOStrStr;
248 0 : tmpOStrStr << std::dec << INPUTSIZE;
249 0 : tmpStr.append(tmpOStrStr.str());
250 :
251 0 : if ((std::string(aExtInfo)).find("cl_khr_fp64") != std::string::npos)
252 : {
253 0 : bKhrFp64Flag = true;
254 : //buildOption = "-D KHR_DP_EXTENSION -Dfp_t=double -Dfp_t4=double4 -Dfp_t16=double16";
255 0 : tmpStr.append(" -DKHR_DP_EXTENSION");
256 0 : buildOption = tmpStr.c_str();
257 : }
258 0 : else if ((std::string(aExtInfo)).find("cl_amd_fp64") != std::string::npos)
259 : {
260 0 : bAmdFp64Flag = true;
261 : //buildOption = "-D AMD_DP_EXTENSION -Dfp_t=double -Dfp_t4=double4 -Dfp_t16=double16";
262 0 : tmpStr.append(" -DAMD_DP_EXTENSION");
263 0 : buildOption = tmpStr.c_str();
264 : }
265 0 : delete[] aExtInfo;
266 :
267 0 : if (!bKhrFp64Flag && !bAmdFp64Flag)
268 : {
269 : /* No 64-bit float support */
270 0 : device->score = (void*)new LibreOfficeDeviceScore;
271 0 : ((LibreOfficeDeviceScore*)device->score)->fTime = DBL_MAX;
272 0 : ((LibreOfficeDeviceScore*)device->score)->bNoCLErrors = true;
273 : }
274 : else
275 : {
276 : /* 64-bit float support present */
277 :
278 : /* Create context and command queue */
279 0 : clContext = clCreateContext(NULL, 1, &device->oclDeviceID, NULL, NULL, &clStatus);
280 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateContext");
281 0 : clQueue = clCreateCommandQueue(clContext, device->oclDeviceID, 0, &clStatus);
282 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateCommandQueue");
283 :
284 : /* Build program */
285 0 : clProgram = clCreateProgramWithSource(clContext, 1, &source, sourceSize, &clStatus);
286 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateProgramWithSource");
287 0 : clStatus = clBuildProgram(clProgram, 1, &device->oclDeviceID, buildOption, NULL, NULL);
288 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clBuildProgram");
289 0 : if (CL_SUCCESS != clStatus)
290 : {
291 : /* Build program failed */
292 : size_t length;
293 : char* buildLog;
294 0 : clStatus = clGetProgramBuildInfo(clProgram, device->oclDeviceID, CL_PROGRAM_BUILD_LOG, 0, NULL, &length);
295 0 : buildLog = (char*)malloc(length);
296 0 : clStatus = clGetProgramBuildInfo(clProgram, device->oclDeviceID, CL_PROGRAM_BUILD_LOG, length, buildLog, &length);
297 : LOG_PRINTF("[OCL] Build Errors" << std::endl << buildLog);
298 0 : free(buildLog);
299 :
300 0 : device->score = (void*)new LibreOfficeDeviceScore;
301 0 : ((LibreOfficeDeviceScore*)device->score)->fTime = DBL_MAX;
302 0 : ((LibreOfficeDeviceScore*)device->score)->bNoCLErrors = false;
303 : }
304 : else
305 : {
306 : /* Build program succeeded */
307 : timer kernelTime;
308 0 : timerStart(&kernelTime);
309 :
310 : /* Run kernel */
311 0 : LibreOfficeDeviceEvaluationIO* testData = (LibreOfficeDeviceEvaluationIO*)evalData;
312 0 : clKernel = clCreateKernel(clProgram, "DynamicKernel", &clStatus);
313 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateKernel");
314 0 : cl_mem clResult = clCreateBuffer(clContext, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_double) * testData->outputSize, &testData->output[0], &clStatus);
315 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateBuffer::clResult");
316 0 : cl_mem clInput0 = clCreateBuffer(clContext, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_double) * testData->inputSize, &testData->input0[0], &clStatus);
317 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateBuffer::clInput0");
318 0 : cl_mem clInput1 = clCreateBuffer(clContext, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_double) * testData->inputSize, &testData->input1[0], &clStatus);
319 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateBuffer::clInput1");
320 0 : cl_mem clInput2 = clCreateBuffer(clContext, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_double) * testData->inputSize, &testData->input2[0], &clStatus);
321 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateBuffer::clInput2");
322 0 : cl_mem clInput3 = clCreateBuffer(clContext, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_double) * testData->inputSize, &testData->input3[0], &clStatus);
323 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateBuffer::clInput3");
324 0 : clStatus = clSetKernelArg(clKernel, 0, sizeof(cl_mem), (void*)&clResult);
325 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clSetKernelArg::clResult");
326 0 : clStatus = clSetKernelArg(clKernel, 1, sizeof(cl_mem), (void*)&clInput0);
327 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clSetKernelArg::clInput0");
328 0 : clStatus = clSetKernelArg(clKernel, 2, sizeof(cl_mem), (void*)&clInput1);
329 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clSetKernelArg::clInput1");
330 0 : clStatus = clSetKernelArg(clKernel, 3, sizeof(cl_mem), (void*)&clInput2);
331 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clSetKernelArg::clInput2");
332 0 : clStatus = clSetKernelArg(clKernel, 4, sizeof(cl_mem), (void*)&clInput3);
333 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clSetKernelArg::clInput3");
334 0 : size_t globalWS[1] = { testData->outputSize };
335 0 : size_t localSize[1] = { 64 };
336 0 : clStatus = clEnqueueNDRangeKernel(clQueue, clKernel, 1, 0, globalWS, localSize, 0, NULL, NULL);
337 0 : DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clEnqueueNDRangeKernel");
338 0 : clFinish(clQueue);
339 0 : clReleaseMemObject(clInput3);
340 0 : clReleaseMemObject(clInput2);
341 0 : clReleaseMemObject(clInput1);
342 0 : clReleaseMemObject(clInput0);
343 0 : clReleaseMemObject(clResult);
344 0 : clReleaseKernel(clKernel);
345 :
346 0 : device->score = (void*)new LibreOfficeDeviceScore;
347 0 : ((LibreOfficeDeviceScore*)device->score)->fTime = timerCurrent(&kernelTime);
348 0 : ((LibreOfficeDeviceScore*)device->score)->bNoCLErrors = true;
349 : }
350 :
351 0 : clReleaseProgram(clProgram);
352 0 : clReleaseCommandQueue(clQueue);
353 0 : clReleaseContext(clContext);
354 0 : }
355 : }
356 : else
357 : {
358 : /* Evaluating an Native CPU device */
359 : LOG_PRINTF("[DS] Device: \"CPU\" (Native) evaluation...");
360 : timer kernelTime;
361 0 : timerStart(&kernelTime);
362 :
363 0 : LibreOfficeDeviceEvaluationIO* testData = (LibreOfficeDeviceEvaluationIO*)evalData;
364 0 : for (unsigned long j = 0; j < testData->outputSize; j++)
365 : {
366 0 : double fAverage = 0.0f;
367 0 : double fMin = DBL_MAX;
368 0 : double fSoP = 0.0f;
369 0 : for (unsigned long i = 0; i < testData->inputSize; i++)
370 : {
371 0 : fAverage += testData->input0[i];
372 0 : fMin = ((fMin < testData->input1[i]) ? fMin : testData->input1[i]);
373 0 : fSoP += testData->input2[i] * testData->input3[i];
374 : }
375 0 : fAverage /= testData->inputSize;
376 0 : testData->output[j] = fAverage + (fMin * fSoP);
377 : }
378 :
379 : // InterpretTail - the S/W fallback is nothing like as efficient
380 : // as any good openCL implementation: no SIMD, tons of branching
381 : // in the inner loops etc. Generously characterise it as only 10x
382 : // slower than the above.
383 0 : float fInterpretTailFactor = 10.0;
384 :
385 0 : device->score = (void*)new LibreOfficeDeviceScore;
386 0 : ((LibreOfficeDeviceScore*)device->score)->fTime = timerCurrent(&kernelTime);
387 0 : ((LibreOfficeDeviceScore*)device->score)->bNoCLErrors = true;
388 :
389 0 : ((LibreOfficeDeviceScore*)device->score)->fTime *= fInterpretTailFactor;
390 : }
391 0 : return DS_SUCCESS;
392 : }
393 :
394 : /* Pick best device */
395 0 : ds_status pickBestDevice(ds_profile* profile, int* bestDeviceIdx)
396 : {
397 0 : double bestScore = DBL_MAX;
398 0 : *bestDeviceIdx = -1;
399 :
400 0 : for (unsigned int d = 0; d < profile->numDevices; d++)
401 : {
402 0 : ds_device device = profile->devices[d];
403 0 : LibreOfficeDeviceScore *pScore = (LibreOfficeDeviceScore*)device.score;
404 :
405 0 : double fScore = DBL_MAX;
406 0 : if (pScore)
407 : {
408 0 : fScore = pScore->fTime;
409 : }
410 : else
411 : {
412 : LOG_PRINTF("Unusual null score");
413 : }
414 :
415 0 : if (DS_DEVICE_OPENCL_DEVICE == device.type)
416 : {
417 : LOG_PRINTF("[DS] Device[" << d << "] " << device.oclDeviceName << " (OpenCL) score is " << fScore);
418 : }
419 : else
420 : {
421 : LOG_PRINTF("[DS] Device[" << d << "] CPU (Native) score is " << fScore);
422 : }
423 0 : if (fScore < bestScore)
424 : {
425 0 : bestScore = fScore;
426 0 : *bestDeviceIdx = d;
427 : }
428 : }
429 0 : if (DS_DEVICE_OPENCL_DEVICE == profile->devices[*bestDeviceIdx].type)
430 : {
431 : LOG_PRINTF("[DS] Selected Device[" << *bestDeviceIdx << "]: " << profile->devices[*bestDeviceIdx].oclDeviceName << "(OpenCL).");
432 : }
433 : else
434 : {
435 : LOG_PRINTF("[DS] Selected Device[" << *bestDeviceIdx << "]: CPU (Native).");
436 : }
437 :
438 0 : return DS_SUCCESS;
439 : }
440 :
441 : /* Return device ID for matching device name */
442 0 : int matchDevice(ds_profile* profile, char* deviceName)
443 : {
444 0 : int deviceMatch = -1;
445 0 : for (unsigned int d = 0; d < profile->numDevices - 1; d++)
446 : {
447 0 : if ((std::string(profile->devices[d].oclDeviceName)).find(deviceName) != std::string::npos) deviceMatch = d;
448 : }
449 0 : if (std::string("NATIVE_CPU").find(deviceName) != std::string::npos) deviceMatch = profile->numDevices - 1;
450 0 : return deviceMatch;
451 : }
452 :
453 : /*************************************************************************/
454 : /* EXTERNAL FUNCTIONS */
455 : /*************************************************************************/
456 0 : ds_device getDeviceSelection(const char* sProfilePath, bool bForceSelection)
457 : {
458 : /* Run only if device is not yet selected */
459 0 : if (!bIsDeviceSelected || bForceSelection)
460 : {
461 : /* Setup */
462 : ds_status status;
463 0 : ds_profile* profile = NULL;
464 0 : status = initDSProfile(&profile, "LibreOffice v0.1");
465 :
466 0 : if (!profile)
467 : {
468 : // failed to initialize profile.
469 0 : selectedDevice.type = DS_DEVICE_NATIVE_CPU;
470 0 : return selectedDevice;
471 : }
472 :
473 : /* Try reading scores from file */
474 0 : std::string tmpStr(sProfilePath);
475 0 : const char* fileName = tmpStr.append("sc_opencl_device_profile.dat").c_str();
476 0 : if (!bForceSelection)
477 : {
478 0 : status = readProfileFromFile(profile, deserializeScore, fileName);
479 : }
480 : else
481 : {
482 0 : status = DS_INVALID_PROFILE;
483 : LOG_PRINTF("[DS] Performing forced profiling.");
484 : }
485 0 : if (DS_SUCCESS != status)
486 : {
487 0 : if (!bForceSelection)
488 : {
489 : LOG_PRINTF("[DS] Profile file not available (" << fileName << "); performing profiling.");
490 : }
491 :
492 : /* Populate input data for micro-benchmark */
493 0 : boost::scoped_ptr<LibreOfficeDeviceEvaluationIO> testData(new LibreOfficeDeviceEvaluationIO);
494 0 : testData->inputSize = INPUTSIZE;
495 0 : testData->outputSize = OUTPUTSIZE;
496 0 : testData->input0.resize(testData->inputSize);
497 0 : testData->input1.resize(testData->inputSize);
498 0 : testData->input2.resize(testData->inputSize);
499 0 : testData->input3.resize(testData->inputSize);
500 0 : testData->output.resize(testData->outputSize);
501 0 : populateInput(testData.get());
502 :
503 : /* Perform evaluations */
504 : unsigned int numUpdates;
505 0 : status = profileDevices(profile, DS_EVALUATE_ALL, evaluateScoreForDevice, (void*)testData.get(), &numUpdates);
506 :
507 0 : if (DS_SUCCESS == status)
508 : {
509 : /* Write scores to file */
510 0 : status = writeProfileToFile(profile, serializeScore, fileName);
511 : if (DS_SUCCESS == status)
512 : {
513 : LOG_PRINTF("[DS] Scores written to file (" << fileName << ").");
514 : }
515 : else
516 : {
517 : LOG_PRINTF("[DS] Error saving scores to file (" << fileName << "); scores not written to file.");
518 : }
519 : }
520 : else
521 : {
522 : LOG_PRINTF("[DS] Unable to evaluate performance; scores not written to file.");
523 0 : }
524 : }
525 : else
526 : {
527 : LOG_PRINTF("[DS] Profile read from file (" << fileName << ").");
528 : }
529 :
530 : /* Pick best device */
531 : int bestDeviceIdx;
532 0 : pickBestDevice(profile, &bestDeviceIdx);
533 :
534 : /* Overide if necessary */
535 0 : char* overrideDeviceStr = getenv("SC_OPENCL_DEVICE_OVERRIDE");
536 0 : if (NULL != overrideDeviceStr)
537 : {
538 0 : int overrideDeviceIdx = matchDevice(profile, overrideDeviceStr);
539 0 : if (-1 != overrideDeviceIdx)
540 : {
541 : LOG_PRINTF("[DS] Overriding Device Selection (SC_OPENCL_DEVICE_OVERRIDE=" << overrideDeviceStr << ").");
542 0 : bestDeviceIdx = overrideDeviceIdx;
543 0 : if (DS_DEVICE_OPENCL_DEVICE == profile->devices[bestDeviceIdx].type)
544 : {
545 : LOG_PRINTF("[DS] Selected Device[" << bestDeviceIdx << "]: " << profile->devices[bestDeviceIdx].oclDeviceName << " (OpenCL).");
546 : }
547 : else
548 : {
549 : LOG_PRINTF("[DS] Selected Device[" << bestDeviceIdx << "]: CPU (Native).");
550 : }
551 : }
552 : else
553 : {
554 : LOG_PRINTF("[DS] Ignoring invalid SC_OPENCL_DEVICE_OVERRIDE=" << overrideDeviceStr << ").");
555 : }
556 : }
557 :
558 : /* Final device selection */
559 0 : selectedDevice = profile->devices[bestDeviceIdx];
560 0 : bIsDeviceSelected = true;
561 :
562 : /* Release profile */
563 0 : status = releaseDSProfile(profile, releaseScore);
564 : }
565 0 : return selectedDevice;
566 : }
567 :
568 0 : }}
569 :
570 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|