summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/opencl/OpenCLZone.hxx52
-rw-r--r--include/opencl/openclwrapper.hxx4
-rw-r--r--officecfg/registry/schema/org/openoffice/Office/Common.xcs6
-rw-r--r--opencl/Library_opencl.mk2
-rw-r--r--opencl/inc/opencl_device_selection.h4
-rw-r--r--opencl/source/OpenCLZone.cxx46
-rw-r--r--opencl/source/opencl_device.cxx23
-rw-r--r--opencl/source/openclwrapper.cxx107
-rw-r--r--sc/source/core/tool/formulagroup.cxx17
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/source/app/svmain.cxx5
11 files changed, 213 insertions, 54 deletions
diff --git a/include/opencl/OpenCLZone.hxx b/include/opencl/OpenCLZone.hxx
new file mode 100644
index 000000000000..1fbc666f4df0
--- /dev/null
+++ b/include/opencl/OpenCLZone.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_OPENCL_INC_OPENCL_ZONE_HXX
+#define INCLUDED_OPENCL_INC_OPENCL_ZONE_HXX
+
+#include <opencl/opencldllapi.h>
+
+// FIXME: post back-port, templatize me and share with OpenGLZone.
+class OPENCL_DLLPUBLIC OpenCLZone
+{
+ /// how many times have we entered a CL zone
+ static volatile sal_uInt64 gnEnterCount;
+ /// how many times have we left a new CL zone
+ static volatile sal_uInt64 gnLeaveCount;
+
+ static void enter()
+ {
+ gnEnterCount++;
+ }
+ static void leave()
+ {
+ gnLeaveCount--;
+ }
+public:
+ OpenCLZone()
+ {
+ gnEnterCount++;
+ }
+
+ ~OpenCLZone()
+ {
+ gnLeaveCount++;
+ }
+
+ static bool isInZone()
+ {
+ return gnEnterCount != gnLeaveCount;
+ }
+
+ static void hardDisable();
+};
+
+#endif // INCLUDED_OPENCL_INC_OPENCL_ZONE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/opencl/openclwrapper.hxx b/include/opencl/openclwrapper.hxx
index b83c1fc2ff00..b173d89ba2f3 100644
--- a/include/opencl/openclwrapper.hxx
+++ b/include/opencl/openclwrapper.hxx
@@ -64,11 +64,13 @@ OPENCL_DLLPUBLIC const std::vector<OpenCLPlatformInfo>& fillOpenCLInfo();
*
* @param pDeviceId the id of the opencl device of type cl_device_id, NULL means use software calculation
* @param bAutoSelect use the algorithm to select the best OpenCL device
+ * @param rOutSelectedDeviceVersionIDString returns the selected device's version string.
*
* @return returns true if there is a valid opencl device that has been set up
*/
OPENCL_DLLPUBLIC bool switchOpenCLDevice(const OUString* pDeviceId, bool bAutoSelect,
- bool bForceEvaluation);
+ bool bForceEvaluation,
+ OUString& rOutSelectedDeviceVersionIDString);
OPENCL_DLLPUBLIC void getOpenCLDeviceInfo(size_t& rDeviceId, size_t& rPlatformId);
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 8d64602e1fca..19827da86454 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -5605,6 +5605,12 @@
</info>
<value oor:separator=";">Linux//Advanced Micro Devices, Inc\.//1445\.5 \(sse2,avx\);//Advanced Micro Devices, Inc\.//;//Intel\(R\) Corporation//;//NVIDIA Corporation//</value>
</prop>
+ <prop oor:name="SelectedOpenCLDeviceIdentifier" oor:type="xs:string" oor:nillable="false">
+ <info>
+ <desc>The OpenCL device identifier of a device that was successfully selected and passed the OpenCL calculation tests.</desc>
+ </info>
+ <value>none</value>
+ </prop>
<prop oor:name="UseSwInterpreter" oor:type="xs:boolean" oor:nillable="false">
<info>
<desc>Determines whether Software Interpreter can be used to speed
diff --git a/opencl/Library_opencl.mk b/opencl/Library_opencl.mk
index 501be304cfaf..039ec0125e53 100644
--- a/opencl/Library_opencl.mk
+++ b/opencl/Library_opencl.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_Library_use_libraries,opencl,\
comphelper \
cppu \
sal \
+ salhelper \
tl \
))
@@ -46,6 +47,7 @@ $(eval $(call gb_Library_add_exception_objects,opencl,\
opencl/source/openclwrapper \
opencl/source/opencl_device \
opencl/source/platforminfo \
+ opencl/source/OpenCLZone \
))
ifeq ($(OS),LINUX)
diff --git a/opencl/inc/opencl_device_selection.h b/opencl/inc/opencl_device_selection.h
index 0522d768ba78..74d8d3767d97 100644
--- a/opencl/inc/opencl_device_selection.h
+++ b/opencl/inc/opencl_device_selection.h
@@ -24,6 +24,8 @@
#include <tools/stream.hxx>
#include <rtl/math.hxx>
+#include <opencl/OpenCLZone.hxx>
+
#include <vector>
enum ds_status
@@ -132,6 +134,8 @@ inline bool getDeviceInfoBool(cl_device_id aDeviceId, cl_device_info aDeviceInfo
inline ds_status initDSProfile(std::unique_ptr<ds_profile>& rProfile, OString const & rVersion)
{
+ OpenCLZone zone;
+
int numDevices;
cl_uint numPlatforms;
std::vector<cl_platform_id> platforms;
diff --git a/opencl/source/OpenCLZone.cxx b/opencl/source/OpenCLZone.cxx
new file mode 100644
index 000000000000..dc3a9522380b
--- /dev/null
+++ b/opencl/source/OpenCLZone.cxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <opencl/OpenCLZone.hxx>
+
+#include <memory>
+
+#include <officecfg/Office/Common.hxx>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+
+// FIXME: templatize me vs. OpenGLZone.
+
+sal_uInt64 volatile OpenCLZone::gnEnterCount = 0;
+sal_uInt64 volatile OpenCLZone::gnLeaveCount = 0;
+
+/**
+ * Called from a signal handler if we get
+ * a crash or hang in some CL code.
+ */
+void OpenCLZone::hardDisable()
+{
+ // protect ourselves from double calling etc.
+ static bool bDisabled = false;
+ if (!bDisabled)
+ {
+ bDisabled = true;
+
+ std::shared_ptr<comphelper::ConfigurationChanges> xChanges(comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::UseOpenCL::set(false, xChanges);
+ xChanges->commit();
+
+ // Force synchronous config write
+ auto xConfProvider = css::configuration::theDefaultProvider::get(comphelper::getProcessComponentContext());
+ css::uno::Reference<css::util::XFlushable> xFlushable(xConfProvider, css::uno::UNO_QUERY_THROW);
+ xFlushable->flush();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/opencl/source/opencl_device.cxx b/opencl/source/opencl_device.cxx
index 3dc9a29413ad..cfeb290645ea 100644
--- a/opencl/source/opencl_device.cxx
+++ b/opencl/source/opencl_device.cxx
@@ -31,6 +31,8 @@
#include <sal/log.hxx>
#include <rtl/math.hxx>
+#include <opencl/OpenCLZone.hxx>
+
#include "opencl_device.hxx"
#define INPUTSIZE 15360
@@ -201,14 +203,21 @@ ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOffice
/* Evaluating an OpenCL device */
SAL_INFO("opencl.device", "Device: \"" << rDevice.sDeviceName << "\" (OpenCL) evaluation...");
cl_int clStatus;
+
/* Check for 64-bit float extensions */
- size_t aDevExtInfoSize = 0;
- clStatus = clGetDeviceInfo(rDevice.aDeviceID, CL_DEVICE_EXTENSIONS, 0, nullptr, &aDevExtInfoSize);
- DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
+ std::unique_ptr<char[]> aExtInfo;
+ {
+ size_t aDevExtInfoSize = 0;
+
+ OpenCLZone zone;
+ clStatus = clGetDeviceInfo(rDevice.aDeviceID, CL_DEVICE_EXTENSIONS, 0, nullptr, &aDevExtInfoSize);
+ DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
+
+ aExtInfo.reset(new char[aDevExtInfoSize]);
+ clStatus = clGetDeviceInfo(rDevice.aDeviceID, CL_DEVICE_EXTENSIONS, sizeof(char) * aDevExtInfoSize, aExtInfo.get(), nullptr);
+ DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clGetDeviceInfo");
+ }
- std::unique_ptr<char[]> aExtInfo(new char[aDevExtInfoSize]);
- 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;
const char* buildOption = nullptr;
@@ -245,6 +254,8 @@ ds_status evaluateScoreForDevice(ds_device& rDevice, std::unique_ptr<LibreOffice
{
/* 64-bit float support present */
+ OpenCLZone zone;
+
/* Create context and command queue */
cl_context clContext = clCreateContext(nullptr, 1, &rDevice.aDeviceID, nullptr, nullptr, &clStatus);
DS_CHECK_STATUS(clStatus, "evaluateScoreForDevice::clCreateContext");
diff --git a/opencl/source/openclwrapper.cxx b/opencl/source/openclwrapper.cxx
index a54d86a70fc4..db6c7e51c09a 100644
--- a/opencl/source/openclwrapper.cxx
+++ b/opencl/source/openclwrapper.cxx
@@ -21,6 +21,7 @@
#include <rtl/ustring.hxx>
#include <sal/config.h>
#include <sal/log.hxx>
+#include <opencl/OpenCLZone.hxx>
#include <memory>
#include <unicode/regex.h>
@@ -81,15 +82,19 @@ OString generateMD5(const void* pData, size_t length)
OString getCacheFolder()
{
- OUString url("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/cache/");
- rtl::Bootstrap::expandMacros(url);
+ static OString aCacheFolder;
- osl::Directory::create(url);
+ if (aCacheFolder.isEmpty())
+ {
+ OUString url("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/cache/");
+ rtl::Bootstrap::expandMacros(url);
- return rtl::OUStringToOString(url, RTL_TEXTENCODING_UTF8);
-}
+ osl::Directory::create(url);
-OString maCacheFolder = getCacheFolder();
+ aCacheFolder = rtl::OUStringToOString(url, RTL_TEXTENCODING_UTF8);
+ }
+ return aCacheFolder;
+}
}
@@ -131,8 +136,7 @@ OString createFileName(cl_device_id deviceId, const char* clFileName)
OString aString = OString(deviceName) + driverVersion + platformVersion;
OString aHash = generateMD5(aString.getStr(), aString.getLength());
- return maCacheFolder + fileName + "-" +
- aHash + ".bin";
+ return getCacheFolder() + fileName + "-" + aHash + ".bin";
}
std::vector<std::shared_ptr<osl::File> > binaryGenerated( const char * clFileName, cl_context context )
@@ -266,6 +270,8 @@ bool initOpenCLAttr( OpenCLEnv * env )
void releaseOpenCLEnv( GPUEnv *gpuInfo )
{
+ OpenCLZone zone;
+
if ( !bIsInited )
{
return;
@@ -318,7 +324,7 @@ bool buildProgram(const char* buildOption, GPUEnv* gpuInfo, int idx)
return false;
}
- OString aBuildLogFileURL = maCacheFolder + "kernel-build.log";
+ OString aBuildLogFileURL = getCacheFolder() + "kernel-build.log";
osl::File aBuildLogFile(rtl::OStringToOUString(aBuildLogFileURL, RTL_TEXTENCODING_UTF8));
osl::FileBase::RC status = aBuildLogFile.open(
osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
@@ -409,6 +415,8 @@ namespace {
void checkDeviceForDoubleSupport(cl_device_id deviceId, bool& bKhrFp64, bool& bAmdFp64)
{
+ OpenCLZone zone;
+
bKhrFp64 = false;
bAmdFp64 = false;
@@ -441,6 +449,8 @@ void checkDeviceForDoubleSupport(cl_device_id deviceId, bool& bKhrFp64, bool& bA
bool initOpenCLRunEnv( GPUEnv *gpuInfo )
{
+ OpenCLZone zone;
+
bool bKhrFp64 = false;
bool bAmdFp64 = false;
@@ -689,7 +699,7 @@ void findDeviceInfoFromDeviceId(cl_device_id aDeviceId, size_t& rDeviceId, size_
}
-bool switchOpenCLDevice(const OUString* pDevice, bool bAutoSelect, bool bForceEvaluation)
+bool switchOpenCLDevice(const OUString* pDevice, bool bAutoSelect, bool bForceEvaluation, OUString& rOutSelectedDeviceVersionIDString)
{
if(fillOpenCLInfo().empty())
return false;
@@ -712,7 +722,6 @@ bool switchOpenCLDevice(const OUString* pDevice, bool bAutoSelect, bool bForceEv
if ( aSelectedDevice.eType != DeviceType::OpenCLDevice)
return false;
pDeviceId = aSelectedDevice.aDeviceID;
-
}
if(gpuEnv.mpDevID == pDeviceId)
@@ -722,54 +731,62 @@ bool switchOpenCLDevice(const OUString* pDevice, bool bAutoSelect, bool bForceEv
return pDeviceId != nullptr;
}
+ cl_context context;
cl_platform_id platformId;
- cl_int nState = clGetDeviceInfo(pDeviceId, CL_DEVICE_PLATFORM,
- sizeof(platformId), &platformId, nullptr);
-
- cl_context_properties cps[3];
- cps[0] = CL_CONTEXT_PLATFORM;
- cps[1] = reinterpret_cast<cl_context_properties>(platformId);
- cps[2] = 0;
- cl_context context = clCreateContext( cps, 1, &pDeviceId, nullptr, nullptr, &nState );
- if (nState != CL_SUCCESS)
- SAL_WARN("opencl", "clCreateContext failed: " << errorString(nState));
+ cl_command_queue command_queue[OPENCL_CMDQUEUE_SIZE];
- if(nState != CL_SUCCESS || context == nullptr)
{
- if(context != nullptr)
- clReleaseContext(context);
+ OpenCLZone zone;
+ cl_int nState = clGetDeviceInfo(pDeviceId, CL_DEVICE_PLATFORM,
+ sizeof(platformId), &platformId, nullptr);
+
+ cl_context_properties cps[3];
+ cps[0] = CL_CONTEXT_PLATFORM;
+ cps[1] = reinterpret_cast<cl_context_properties>(platformId);
+ cps[2] = 0;
+ context = clCreateContext( cps, 1, &pDeviceId, nullptr, nullptr, &nState );
+ if (nState != CL_SUCCESS)
+ SAL_WARN("opencl", "clCreateContext failed: " << errorString(nState));
- SAL_WARN("opencl", "failed to set/switch opencl device");
- return false;
- }
- SAL_INFO("opencl", "Created context " << context << " for platform " << platformId << ", device " << pDeviceId);
+ if(nState != CL_SUCCESS || context == nullptr)
+ {
+ if(context != nullptr)
+ clReleaseContext(context);
- cl_command_queue command_queue[OPENCL_CMDQUEUE_SIZE];
- for (int i = 0; i < OPENCL_CMDQUEUE_SIZE; ++i)
- {
- command_queue[i] = clCreateCommandQueue(
- context, pDeviceId, 0, &nState);
- if (nState != CL_SUCCESS)
- SAL_WARN("opencl", "clCreateCommandQueue failed: " << errorString(nState));
+ SAL_WARN("opencl", "failed to set/switch opencl device");
+ return false;
+ }
+ SAL_INFO("opencl", "Created context " << context << " for platform " << platformId << ", device " << pDeviceId);
- if (command_queue[i] == nullptr || nState != CL_SUCCESS)
+ for (int i = 0; i < OPENCL_CMDQUEUE_SIZE; ++i)
{
- // Release all command queues created so far.
- for (int j = 0; j <= i; ++j)
+ command_queue[i] = clCreateCommandQueue(
+ context, pDeviceId, 0, &nState);
+ if (nState != CL_SUCCESS)
+ SAL_WARN("opencl", "clCreateCommandQueue failed: " << errorString(nState));
+
+ if (command_queue[i] == nullptr || nState != CL_SUCCESS)
{
- if (command_queue[j])
+ // Release all command queues created so far.
+ for (int j = 0; j <= i; ++j)
{
- clReleaseCommandQueue(command_queue[j]);
- command_queue[j] = nullptr;
+ if (command_queue[j])
+ {
+ clReleaseCommandQueue(command_queue[j]);
+ command_queue[j] = nullptr;
+ }
}
+
+ clReleaseContext(context);
+ SAL_WARN("opencl", "failed to set/switch opencl device");
+ return false;
}
- clReleaseContext(context);
- SAL_WARN("opencl", "failed to set/switch opencl device");
- return false;
+ SAL_INFO("opencl", "Created command queue " << command_queue[i] << " for context " << context);
}
- SAL_INFO("opencl", "Created command queue " << command_queue[i] << " for context " << context);
+ OString sDeviceID = getDeviceInfoString(pDeviceId, CL_DEVICE_VENDOR) + " " + getDeviceInfoString(pDeviceId, CL_DRIVER_VERSION);
+ rOutSelectedDeviceVersionIDString = OStringToOUString(sDeviceID, RTL_TEXTENCODING_UTF8);
}
setOpenCLCmdQueuePosition(0); // Call this just to avoid the method being deleted from unused function deleter.
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index e382e7a6ab60..49415042dd9c 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -32,7 +32,7 @@
#include <vector>
#if HAVE_FEATURE_OPENCL
-#include <opencl/openclwrapper.hxx>
+# include <opencl/openclwrapper.hxx>
#endif
namespace sc {
@@ -327,12 +327,25 @@ bool FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool
return false;
}
- bool bSuccess = ::opencl::switchOpenCLDevice(&rDeviceId, bAutoSelect, bForceEvaluation);
+ OUString aSelectedCLDeviceVersionID;
+ bool bSuccess = ::opencl::switchOpenCLDevice(&rDeviceId, bAutoSelect, bForceEvaluation, aSelectedCLDeviceVersionID);
+
if (!bSuccess)
return false;
delete msInstance;
msInstance = new sc::opencl::FormulaGroupInterpreterOpenCL();
+
+ if (aSelectedCLDeviceVersionID != officecfg::Office::Common::Misc::SelectedOpenCLDeviceIdentifier::get())
+ {
+ // perform OpenCL calculation tests
+
+ // save the device
+ std::shared_ptr<comphelper::ConfigurationChanges> xBatch(comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Misc::SelectedOpenCLDeviceIdentifier::set(aSelectedCLDeviceVersionID, xBatch);
+ xBatch->commit();
+ }
+
return true;
}
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 307c371e5092..56a4d2b97e70 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -82,6 +82,7 @@ $(eval $(call gb_Library_use_libraries,vcl,\
cppuhelper \
i18nlangtag \
i18nutil \
+ $(if $(filter OPENCL,$(BUILD_TYPE)),opencl) \
cppu \
sal \
salhelper \
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index 10b7f91e8fcd..cc5a32c8b7a0 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -85,6 +85,7 @@
#include <cppuhelper/implbase.hxx>
#include <uno/current_context.hxx>
+#include <opencl/OpenCLZone.hxx>
#include <opengl/zone.hxx>
#include <opengl/watchdog.hxx>
@@ -120,6 +121,10 @@ oslSignalAction SAL_CALL VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo
if (OpenGLZone::isInZone())
OpenGLZone::hardDisable();
#endif
+#if HAVE_FEATURE_OPENCL
+ if (OpenCLZone::isInZone())
+ OpenCLZone::hardDisable();
+#endif
}
// RC