summaryrefslogtreecommitdiff
path: root/opencl/source/opencl_device.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'opencl/source/opencl_device.cxx')
-rw-r--r--opencl/source/opencl_device.cxx279
1 files changed, 167 insertions, 112 deletions
diff --git a/opencl/source/opencl_device.cxx b/opencl/source/opencl_device.cxx
index 32a94df5dcb3..af3bc1844e3a 100644
--- a/opencl/source/opencl_device.cxx
+++ b/opencl/source/opencl_device.cxx
@@ -46,15 +46,11 @@
namespace opencl {
+namespace {
+
bool bIsDeviceSelected = false;
ds_device selectedDevice;
-struct LibreOfficeDeviceScore
-{
- double fTime; // small time means faster device
- bool bNoCLErrors; // were there any opencl errors
-};
-
struct LibreOfficeDeviceEvaluationIO
{
std::vector<double> input0;
@@ -182,7 +178,7 @@ double random(double min, double max)
}
/* Populate input */
-void populateInput(LibreOfficeDeviceEvaluationIO* testData)
+void populateInput(std::unique_ptr<LibreOfficeDeviceEvaluationIO>& testData)
{
double* input0 = &testData->input0[0];
double* input1 = &testData->input1[0];
@@ -196,49 +192,22 @@ void populateInput(LibreOfficeDeviceEvaluationIO* testData)
input3[i] = random(0, i);
}
}
-/* Encode score object as byte string */
-ds_status serializeScore(ds_device* device, void** serializedScore, unsigned int* serializedScoreSize)
-{
- *serializedScoreSize = sizeof(LibreOfficeDeviceScore);
- *serializedScore = static_cast<void*>(new unsigned char[*serializedScoreSize]);
- memcpy(*serializedScore, device->score, *serializedScoreSize);
- return DS_SUCCESS;
-}
-
-/* Parses byte string and stores in score object */
-ds_status deserializeScore(ds_device* device, const unsigned char* serializedScore, unsigned int serializedScoreSize)
-{
- // check that serializedScoreSize == sizeof(LibreOfficeDeviceScore);
- device->score = new LibreOfficeDeviceScore;
- memcpy(device->score, serializedScore, serializedScoreSize);
- return DS_SUCCESS;
-}
-
-/* Releases memory held by score */
-ds_status releaseScore(void* score)
-{
- if (nullptr != score)
- {
- delete static_cast<LibreOfficeDeviceScore*>(score);
- }
- return DS_SUCCESS;
-}
/* Evaluate devices */
-ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
+ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOfficeDeviceEvaluationIO>& testData)
{
- if (DS_DEVICE_OPENCL_DEVICE == device->type)
+ if (rDevice.eType == DeviceType::OpenCLDevice)
{
/* Evaluating an OpenCL device */
- SAL_INFO("opencl.device", "Device: \"" << device->oclDeviceName << "\" (OpenCL) evaluation...");
+ SAL_INFO("opencl.device", "Device: \"" << rDevice.sDeviceName << "\" (OpenCL) evaluation...");
cl_int clStatus;
/* Check for 64-bit float extensions */
size_t aDevExtInfoSize = 0;
- clStatus = clGetDeviceInfo(device->oclDeviceID, CL_DEVICE_EXTENSIONS, 0, nullptr, &aDevExtInfoSize);
+ clStatus = clGetDeviceInfo(rDevice.aDeviceID, CL_DEVICE_EXTENSIONS, 0, nullptr, &aDevExtInfoSize);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
std::unique_ptr<char[]> aExtInfo(new char[aDevExtInfoSize]);
- clStatus = clGetDeviceInfo(device->oclDeviceID, CL_DEVICE_EXTENSIONS, sizeof(char) * aDevExtInfoSize, aExtInfo.get(), nullptr);
+ clStatus = clGetDeviceInfo(rDevice.aDeviceID, CL_DEVICE_EXTENSIONS, sizeof(char) * aDevExtInfoSize, aExtInfo.get(), nullptr);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
bool bKhrFp64Flag = false;
bool bAmdFp64Flag = false;
@@ -268,9 +237,8 @@ ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
if (!bKhrFp64Flag && !bAmdFp64Flag)
{
/* No 64-bit float support */
- device->score = static_cast<void*>(new LibreOfficeDeviceScore);
- static_cast<LibreOfficeDeviceScore*>(device->score)->fTime = DBL_MAX;
- static_cast<LibreOfficeDeviceScore*>(device->score)->bNoCLErrors = true;
+ rDevice.fTime = DBL_MAX;
+ rDevice.bErrors = false;
SAL_INFO("opencl.device", "... no fp64 support");
}
else
@@ -278,30 +246,29 @@ ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
/* 64-bit float support present */
/* Create context and command queue */
- cl_context clContext = clCreateContext(nullptr, 1, &device->oclDeviceID, nullptr, nullptr, &clStatus);
+ cl_context clContext = clCreateContext(nullptr, 1, &rDevice.aDeviceID, nullptr, nullptr, &clStatus);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateContext");
- cl_command_queue clQueue = clCreateCommandQueue(clContext, device->oclDeviceID, 0, &clStatus);
+ cl_command_queue clQueue = clCreateCommandQueue(clContext, rDevice.aDeviceID, 0, &clStatus);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateCommandQueue");
/* Build program */
cl_program clProgram = clCreateProgramWithSource(clContext, 1, &source, sourceSize, &clStatus);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateProgramWithSource");
- clStatus = clBuildProgram(clProgram, 1, &device->oclDeviceID, buildOption, nullptr, nullptr);
+ clStatus = clBuildProgram(clProgram, 1, &rDevice.aDeviceID, buildOption, nullptr, nullptr);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clBuildProgram");
if (CL_SUCCESS != clStatus)
{
/* Build program failed */
size_t length;
char* buildLog;
- clStatus = clGetProgramBuildInfo(clProgram, device->oclDeviceID, CL_PROGRAM_BUILD_LOG, 0, nullptr, &length);
+ clStatus = clGetProgramBuildInfo(clProgram, rDevice.aDeviceID, CL_PROGRAM_BUILD_LOG, 0, nullptr, &length);
buildLog = static_cast<char*>(malloc(length));
- clGetProgramBuildInfo(clProgram, device->oclDeviceID, CL_PROGRAM_BUILD_LOG, length, buildLog, &length);
+ clGetProgramBuildInfo(clProgram, rDevice.aDeviceID, CL_PROGRAM_BUILD_LOG, length, buildLog, &length);
SAL_INFO("opencl.device", "Build Errors:\n" << buildLog);
free(buildLog);
- device->score = static_cast<void*>(new LibreOfficeDeviceScore);
- static_cast<LibreOfficeDeviceScore*>(device->score)->fTime = DBL_MAX;
- static_cast<LibreOfficeDeviceScore*>(device->score)->bNoCLErrors = false;
+ rDevice.fTime = DBL_MAX;
+ rDevice.bErrors = true;
}
else
{
@@ -310,7 +277,6 @@ ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
timerStart(&kernelTime);
/* Run kernel */
- LibreOfficeDeviceEvaluationIO* testData = static_cast<LibreOfficeDeviceEvaluationIO*>(evalData);
cl_kernel clKernel = clCreateKernel(clProgram, "DynamicKernel", &clStatus);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateKernel");
cl_mem clResult = clCreateBuffer(clContext, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_double) * testData->outputSize, &testData->output[0], &clStatus);
@@ -345,9 +311,8 @@ ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
clReleaseMemObject(clResult);
clReleaseKernel(clKernel);
- device->score = static_cast<void*>(new LibreOfficeDeviceScore);
- static_cast<LibreOfficeDeviceScore*>(device->score)->fTime = timerCurrent(&kernelTime);
- static_cast<LibreOfficeDeviceScore*>(device->score)->bNoCLErrors = true;
+ rDevice.fTime = timerCurrent(&kernelTime);
+ rDevice.bErrors = false;
}
clReleaseProgram(clProgram);
@@ -362,7 +327,6 @@ ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
timer kernelTime;
timerStart(&kernelTime);
- LibreOfficeDeviceEvaluationIO* testData = static_cast<LibreOfficeDeviceEvaluationIO*>(evalData);
for (unsigned long j = 0; j < testData->outputSize; j++)
{
double fAverage = 0.0f;
@@ -384,28 +348,45 @@ ds_status evaluateScoreForDevice(ds_device* device, void* evalData)
// slower than the above.
float fInterpretTailFactor = 10.0;
- device->score = static_cast<void*>(new LibreOfficeDeviceScore);
- static_cast<LibreOfficeDeviceScore*>(device->score)->fTime = timerCurrent(&kernelTime);
- static_cast<LibreOfficeDeviceScore*>(device->score)->bNoCLErrors = true;
-
- static_cast<LibreOfficeDeviceScore*>(device->score)->fTime *= fInterpretTailFactor;
+ rDevice.fTime = timerCurrent(&kernelTime);
+ rDevice.fTime *= fInterpretTailFactor;
+ rDevice.bErrors = false;
}
return DS_SUCCESS;
}
+ds_status profileDevices(std::unique_ptr<ds_profile>& pProfile, std::unique_ptr<LibreOfficeDeviceEvaluationIO>& pTestData)
+{
+ ds_status status = DS_SUCCESS;
+
+ if (!pProfile)
+ return DS_INVALID_PROFILE;
+
+ for (ds_device& rDevice : pProfile->devices)
+ {
+ ds_status evaluatorStatus = evaluateScoreForDevice(rDevice, pTestData);
+ if (evaluatorStatus != DS_SUCCESS)
+ {
+ status = evaluatorStatus;
+ return status;
+ }
+ }
+ return status;
+}
+
/* Pick best device */
-ds_status pickBestDevice(ds_profile* profile, int* bestDeviceIdx)
+ds_status pickBestDevice(std::unique_ptr<ds_profile>& profile, int& rBestDeviceIndex)
{
double bestScore = DBL_MAX;
- *bestDeviceIdx = -1;
- for (unsigned int d = 0; d < profile->numDevices; d++)
+ rBestDeviceIndex = -1;
+
+ for (unsigned int d = 0; d < profile->devices.size(); d++)
{
- ds_device device = profile->devices[d];
- LibreOfficeDeviceScore *pScore = static_cast<LibreOfficeDeviceScore*>(device.score);
+ ds_device& device = profile->devices[d];
// Check blacklist and whitelist for actual devices
- if (device.type == DS_DEVICE_OPENCL_DEVICE)
+ if (device.eType == DeviceType::OpenCLDevice)
{
// There is a silly impedance mismatch here. Why do we
// need two different ways to describe an OpenCL platform
@@ -415,32 +396,32 @@ ds_status pickBestDevice(ds_profile* profile, int* bestDeviceIdx)
OpenCLDeviceInfo aDevice;
// We know that only the below fields are used by checkForKnownBadCompilers()
- aPlatform.maVendor = OUString(device.oclPlatformVendor, strlen(device.oclPlatformVendor), RTL_TEXTENCODING_UTF8);
- aDevice.maName = OUString(device.oclDeviceName, strlen(device.oclDeviceName), RTL_TEXTENCODING_UTF8);
- aDevice.maDriver = OUString(device.oclDriverVersion, strlen(device.oclDriverVersion), RTL_TEXTENCODING_UTF8);
+ aPlatform.maVendor = OStringToOUString(device.sPlatformVendor, RTL_TEXTENCODING_UTF8);
+ aDevice.maName = OStringToOUString(device.sDeviceName, RTL_TEXTENCODING_UTF8);
+ aDevice.maDriver = OStringToOUString(device.sDriverVersion, RTL_TEXTENCODING_UTF8);
// If blacklisted or not whitelisted, ignore it
if (OpenCLConfig::get().checkImplementation(aPlatform, aDevice))
{
- SAL_INFO("opencl.device", "Device[" << d << "] " << device.oclDeviceName << " is blacklisted or not whitelisted");
- pScore->fTime = DBL_MAX;
- pScore->bNoCLErrors = true;
+ SAL_INFO("opencl.device", "Device[" << d << "] " << device.sDeviceName << " is blacklisted or not whitelisted");
+ device.fTime = DBL_MAX;
+ device.bErrors = false;
}
}
double fScore = DBL_MAX;
- if (pScore)
+ if (device.fTime >= 0.0 || device.fTime == DBL_MAX)
{
- fScore = pScore->fTime;
+ fScore = device.fTime;
}
else
{
SAL_INFO("opencl.device", "Unusual null score");
}
- if (DS_DEVICE_OPENCL_DEVICE == device.type)
+ if (device.eType == DeviceType::OpenCLDevice)
{
- SAL_INFO("opencl.device", "Device[" << d << "] " << device.oclDeviceName << " (OpenCL) score is " << fScore);
+ SAL_INFO("opencl.device", "Device[" << d << "] " << device.sDeviceName << " (OpenCL) score is " << fScore);
}
else
{
@@ -449,59 +430,135 @@ ds_status pickBestDevice(ds_profile* profile, int* bestDeviceIdx)
if (fScore < bestScore)
{
bestScore = fScore;
- *bestDeviceIdx = d;
+ rBestDeviceIndex = d;
}
}
- if (DS_DEVICE_OPENCL_DEVICE == profile->devices[*bestDeviceIdx].type)
+ if (profile->devices[rBestDeviceIndex].eType == DeviceType::OpenCLDevice)
{
- SAL_INFO("opencl.device", "Selected Device[" << *bestDeviceIdx << "]: " << profile->devices[*bestDeviceIdx].oclDeviceName << "(OpenCL).");
+ SAL_INFO("opencl.device", "Selected Device[" << rBestDeviceIndex << "]: " << profile->devices[rBestDeviceIndex].sDeviceName << "(OpenCL).");
}
else
{
- SAL_INFO("opencl.device", "Selected Device[" << *bestDeviceIdx << "]: CPU (Native).");
+ SAL_INFO("opencl.device", "Selected Device[" << rBestDeviceIndex << "]: CPU (Native).");
}
-
return DS_SUCCESS;
}
/* Return device ID for matching device name */
-int matchDevice(ds_profile* profile, char* deviceName)
+int matchDevice(std::unique_ptr<ds_profile>& profile, char* deviceName)
{
int deviceMatch = -1;
- for (unsigned int d = 0; d < profile->numDevices - 1; d++)
+ for (unsigned int d = 0; d < profile->devices.size() - 1; d++)
{
- if ((std::string(profile->devices[d].oclDeviceName)).find(deviceName) != std::string::npos) deviceMatch = d;
+ if ((std::string(profile->devices[d].sDeviceName.getStr())).find(deviceName) != std::string::npos)
+ deviceMatch = d;
}
- if (std::string("NATIVE_CPU").find(deviceName) != std::string::npos) deviceMatch = profile->numDevices - 1;
+ if (std::string("NATIVE_CPU").find(deviceName) != std::string::npos)
+ deviceMatch = profile->devices.size() - 1;
return deviceMatch;
}
-/*************************************************************************/
-/* EXTERNAL FUNCTIONS */
-/*************************************************************************/
-ds_device getDeviceSelection(const char* sProfilePath, bool bForceSelection)
+class LogWriter
+{
+private:
+ SvFileStream maStream;
+public:
+ LogWriter(OUString aFileName)
+ : maStream(aFileName, StreamMode::WRITE)
+ {}
+
+ void text(const OString& rText)
+ {
+ maStream.WriteOString(rText);
+ maStream.WriteChar('\n');
+ }
+
+ void log(const OString& rKey, const OString& rValue)
+ {
+ maStream.WriteOString(rKey);
+ maStream.WriteCharPtr(": ");
+ maStream.WriteOString(rValue);
+ maStream.WriteChar('\n');
+ }
+
+ void log(const OString& rKey, const OUString& rValue)
+ {
+ log(rKey, OUStringToOString(rValue, RTL_TEXTENCODING_UTF8));
+ }
+
+ void log(const OString& rKey, int rValue)
+ {
+ log(rKey, OString::number(rValue));
+ }
+
+ void log(const OString& rKey, bool rValue)
+ {
+ log(rKey, OString::boolean(rValue));
+ }
+};
+
+
+void writeDevicesLog(std::unique_ptr<ds_profile>& rProfile, OUString sProfilePath, int nSelectedIndex)
+{
+ OUString aCacheFile(sProfilePath + "opencl_devices.log");
+ LogWriter aWriter(aCacheFile);
+
+ int nIndex = 0;
+
+ for (ds_device& rDevice : rProfile->devices)
+ {
+ if (rDevice.eType == DeviceType::OpenCLDevice)
+ {
+ aWriter.log("Device Index", nIndex);
+ aWriter.log(" Selected", nIndex == nSelectedIndex);
+ aWriter.log(" Device Name", rDevice.sDeviceName);
+ aWriter.log(" Device Vendor", rDevice.sDeviceVendor);
+ aWriter.log(" Device Version", rDevice.sDeviceVersion);
+ aWriter.log(" Driver Version", rDevice.sDriverVersion);
+ aWriter.log(" Device Type", rDevice.sDeviceType);
+ aWriter.log(" Device Extensions", rDevice.sDeviceExtensions);
+ aWriter.log(" Device OpenCL C Version", rDevice.sDeviceOpenCLVersion);
+
+ aWriter.log(" Device Available", rDevice.bDeviceAvailable);
+ aWriter.log(" Device Compiler Available", rDevice.bDeviceCompilerAvailable);
+ aWriter.log(" Device Linker Available", rDevice.bDeviceLinkerAvailable);
+
+ aWriter.log(" Platform Name", rDevice.sPlatformName);
+ aWriter.log(" Platform Vendor", rDevice.sPlatformVendor);
+ aWriter.log(" Platform Version", rDevice.sPlatformVersion);
+ aWriter.log(" Platform Profile", rDevice.sPlatformProfile);
+ aWriter.log(" Platform Extensions", rDevice.sPlatformExtensions);
+ aWriter.text("");
+ }
+ nIndex++;
+ }
+}
+
+} // end anonymous namespace
+
+ds_device getDeviceSelection(OUString sProfilePath, bool bForceSelection)
{
/* Run only if device is not yet selected */
if (!bIsDeviceSelected || bForceSelection)
{
/* Setup */
- ds_profile* profile = nullptr;
- initDSProfile(&profile, "LibreOffice v0.1");
+ std::unique_ptr<ds_profile> aProfile;
+ ds_status status;
+ status = initDSProfile(aProfile, "LibreOffice v1");
- if (!profile)
+ if (status != DS_SUCCESS)
{
// failed to initialize profile.
- selectedDevice.type = DS_DEVICE_NATIVE_CPU;
+ selectedDevice.eType = DeviceType::NativeCPU;
return selectedDevice;
}
/* Try reading scores from file */
- std::string tmpStr(sProfilePath);
- const char* fileName = tmpStr.append("sc_opencl_device_profile.dat").c_str();
- ds_status status;
+ OUString sFilePath = sProfilePath + OUString("opencl_profile.xml");
+
if (!bForceSelection)
{
- status = readProfileFromFile(profile, deserializeScore, fileName);
+ status = readProfile(sFilePath, aProfile);
}
else
{
@@ -512,7 +569,7 @@ ds_device getDeviceSelection(const char* sProfilePath, bool bForceSelection)
{
if (!bForceSelection)
{
- SAL_INFO("opencl.device", "Profile file not available (" << fileName << "); performing profiling.");
+ SAL_INFO("opencl.device", "Profile file not available (" << sFilePath << "); performing profiling.");
}
/* Populate input data for micro-benchmark */
@@ -524,23 +581,22 @@ ds_device getDeviceSelection(const char* sProfilePath, bool bForceSelection)
testData->input2.resize(testData->inputSize);
testData->input3.resize(testData->inputSize);
testData->output.resize(testData->outputSize);
- populateInput(testData.get());
+ populateInput(testData);
/* Perform evaluations */
- unsigned int numUpdates;
- status = profileDevices(profile, DS_EVALUATE_ALL, evaluateScoreForDevice, static_cast<void*>(testData.get()), &numUpdates);
+ status = profileDevices(aProfile, testData);
if (DS_SUCCESS == status)
{
/* Write scores to file */
- status = writeProfileToFile(profile, serializeScore, fileName);
+ status = writeProfile(sFilePath, aProfile);
if (DS_SUCCESS == status)
{
- SAL_INFO("opencl.device", "Scores written to file (" << fileName << ").");
+ SAL_INFO("opencl.device", "Scores written to file (" << sFilePath << ").");
}
else
{
- SAL_INFO("opencl.device", "Error saving scores to file (" << fileName << "); scores not written to file.");
+ SAL_INFO("opencl.device", "Error saving scores to file (" << sFilePath << "); scores not written to file.");
}
}
else
@@ -550,25 +606,25 @@ ds_device getDeviceSelection(const char* sProfilePath, bool bForceSelection)
}
else
{
- SAL_INFO("opencl.device", "Profile read from file (" << fileName << ").");
+ SAL_INFO("opencl.device", "Profile read from file (" << sFilePath << ").");
}
/* Pick best device */
int bestDeviceIdx;
- pickBestDevice(profile, &bestDeviceIdx);
+ pickBestDevice(aProfile, bestDeviceIdx);
/* Override if necessary */
char* overrideDeviceStr = getenv("SC_OPENCL_DEVICE_OVERRIDE");
if (nullptr != overrideDeviceStr)
{
- int overrideDeviceIdx = matchDevice(profile, overrideDeviceStr);
+ int overrideDeviceIdx = matchDevice(aProfile, overrideDeviceStr);
if (-1 != overrideDeviceIdx)
{
SAL_INFO("opencl.device", "Overriding Device Selection (SC_OPENCL_DEVICE_OVERRIDE=" << overrideDeviceStr << ").");
bestDeviceIdx = overrideDeviceIdx;
- if (DS_DEVICE_OPENCL_DEVICE == profile->devices[bestDeviceIdx].type)
+ if (aProfile->devices[bestDeviceIdx].eType == DeviceType::OpenCLDevice)
{
- SAL_INFO("opencl.device", "Selected Device[" << bestDeviceIdx << "]: " << profile->devices[bestDeviceIdx].oclDeviceName << " (OpenCL).");
+ SAL_INFO("opencl.device", "Selected Device[" << bestDeviceIdx << "]: " << aProfile->devices[bestDeviceIdx].sDeviceName << " (OpenCL).");
}
else
{
@@ -582,11 +638,10 @@ ds_device getDeviceSelection(const char* sProfilePath, bool bForceSelection)
}
/* Final device selection */
- selectedDevice = profile->devices[bestDeviceIdx];
+ selectedDevice = aProfile->devices[bestDeviceIdx];
bIsDeviceSelected = true;
- /* Release profile */
- releaseDSProfile(profile, releaseScore);
+ writeDevicesLog(aProfile, sProfilePath, bestDeviceIdx);
}
return selectedDevice;
}