diff options
author | Tor Lillqvist <tml@collabora.com> | 2013-11-28 10:59:16 +0200 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2013-11-28 15:12:10 +0200 |
commit | 78d1f562685c9bb8cd24d272b48e9d2d8c086308 (patch) | |
tree | f0dd6462cbbfb199af04d33c3998931041e18e60 /sc/source/core | |
parent | f7ef84640258e4ee6ddc4cc5cbf58a2d89860afa (diff) |
Background OpenCL compilation re-factoring
Don't use a mutex and condition in each ScFormulaCellGroup.
Not sure at all if this crack works, and I hate every moment spent on it, but
at least it is still behind an environment variable.
Change-Id: I70c917d47112e3a2ed010de4d123a4155f71c004
Diffstat (limited to 'sc/source/core')
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 31 | ||||
-rw-r--r-- | sc/source/core/opencl/formulagroupcl.cxx | 15 | ||||
-rw-r--r-- | sc/source/core/opencl/opbase.hxx | 66 | ||||
-rw-r--r-- | sc/source/core/tool/clkernelthread.cxx | 12 | ||||
-rw-r--r-- | sc/source/core/tool/formulaopt.cxx | 5 |
5 files changed, 97 insertions, 32 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 6144c09fae14..8c3471e60c1e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -401,8 +401,8 @@ static osl::Mutex& getOpenCLCompilationThreadMutex() return *pMutex; } -int ScFormulaCellGroup::mnCount = 0; -rtl::Reference<sc::CLBuildKernelThread> ScFormulaCellGroup::mxCLKernelThread; +int ScFormulaCellGroup::snCount = 0; +rtl::Reference<sc::CLBuildKernelThread> ScFormulaCellGroup::sxCompilationThread; ScFormulaCellGroup::ScFormulaCellGroup() : mnRefCount(0), @@ -421,11 +421,11 @@ ScFormulaCellGroup::ScFormulaCellGroup() : if (ScInterpreter::GetGlobalConfig().mbOpenCLEnabled) { osl::MutexGuard aGuard(getOpenCLCompilationThreadMutex()); - if (mnCount++ == 0) + if (snCount++ == 0) { - assert(!mxCLKernelThread.is()); - mxCLKernelThread.set(new sc::CLBuildKernelThread); - mxCLKernelThread->launch(); + assert(!sxCompilationThread.is()); + sxCompilationThread.set(new sc::CLBuildKernelThread); + sxCompilationThread->launch(); } } } @@ -436,13 +436,13 @@ ScFormulaCellGroup::~ScFormulaCellGroup() if (ScInterpreter::GetGlobalConfig().mbOpenCLEnabled) { osl::MutexGuard aGuard(getOpenCLCompilationThreadMutex()); - if (--mnCount == 0 && mxCLKernelThread.is()) + if (--snCount == 0 && sxCompilationThread.is()) { - assert(mxCLKernelThread.is()); - mxCLKernelThread->finish(); - mxCLKernelThread->join(); + assert(sxCompilationThread.is()); + sxCompilationThread->finish(); + sxCompilationThread->join(); SAL_INFO("sc.opencl", "OpenCL kernel compilation thread has finished"); - mxCLKernelThread.clear(); + sxCompilationThread.clear(); } } delete mpCode; @@ -450,13 +450,11 @@ ScFormulaCellGroup::~ScFormulaCellGroup() void ScFormulaCellGroup::scheduleCompilation() { - osl::ResettableMutexGuard aGuard(maMutex); meCalcState = sc::GroupCalcOpenCLKernelCompilationScheduled; sc::CLBuildKernelWorkItem aWorkItem; aWorkItem.meWhatToDo = sc::CLBuildKernelWorkItem::COMPILE; aWorkItem.mxGroup = this; - aGuard.clear(); - mxCLKernelThread->push(aWorkItem); + sxCompilationThread->push(aWorkItem); } void ScFormulaCellGroup::setCode( const ScTokenArray& rCode ) @@ -1933,6 +1931,9 @@ bool ScFormulaCell::IsMultilineResult() void ScFormulaCell::MaybeInterpret() { + if (mxGroup && mxGroup->meCalcState == sc::GroupCalcOpenCLKernelCompilationScheduled) + return; + if (!IsDirtyOrInTableOpDirty()) return; @@ -3341,7 +3342,7 @@ ScFormulaCellGroupRef ScFormulaCell::CreateCellGroup( SCROW nLen, bool bInvarian mxGroup->mbInvariant = bInvariant; mxGroup->mnLength = nLen; mxGroup->mpCode = pCode; // Move this to the shared location. - if (mxGroup->mxCLKernelThread.is()) + if (mxGroup->sxCompilationThread.is()) mxGroup->scheduleCompilation(); return mxGroup; } diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx index 4e48e04a084e..623a36cc6e37 100644 --- a/sc/source/core/opencl/formulagroupcl.cxx +++ b/sc/source/core/opencl/formulagroupcl.cxx @@ -8,6 +8,7 @@ */ #include "formulagroup.hxx" +#include "clkernelthread.hxx" #include "grouptokenconverter.hxx" #include "document.hxx" #include "formulacell.hxx" @@ -2796,8 +2797,9 @@ CompiledFormula* FormulaGroupInterpreterOpenCL::createCompiledFormula(ScDocument { ScTokenArray *pCode = new ScTokenArray(); ScGroupTokenConverter aConverter(*pCode, rDoc, *xGroup->mpTopCell, rTopPos); - if (!aConverter.convert(rCode)) + if (!aConverter.convert(rCode) || pCode->GetLen() == 0) { + delete pCode; return NULL; } @@ -2812,19 +2814,13 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, { DynamicKernel *pKernel; - osl::ResettableMutexGuard aGuard(xGroup->maMutex); if (xGroup->meCalcState == sc::GroupCalcOpenCLKernelCompilationScheduled || xGroup->meCalcState == sc::GroupCalcOpenCLKernelBinaryCreated) { if (xGroup->meCalcState == sc::GroupCalcOpenCLKernelCompilationScheduled) { - aGuard.clear(); - xGroup->maCompilationDone.wait(); - xGroup->maCompilationDone.reset(); - } - else - { - aGuard.clear(); + ScFormulaCellGroup::sxCompilationThread->maCompilationDoneCondition.wait(); + ScFormulaCellGroup::sxCompilationThread->maCompilationDoneCondition.reset(); } pKernel = static_cast<DynamicKernel*>(xGroup->mpCompiledFormula); @@ -2832,7 +2828,6 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, else { assert(xGroup->meCalcState == sc::GroupCalcRunning); - aGuard.clear(); pKernel = static_cast<DynamicKernel*>(createCompiledFormula(rDoc, rTopPos, xGroup, rCode)); } diff --git a/sc/source/core/opencl/opbase.hxx b/sc/source/core/opencl/opbase.hxx index 22a9316f9015..a99e7f47d54e 100644 --- a/sc/source/core/opencl/opbase.hxx +++ b/sc/source/core/opencl/opbase.hxx @@ -10,6 +10,8 @@ #ifndef SC_OPENCL_OPBASE_HXX #define SC_OPENCL_OPBASE_HXX +#include <sal/log.hxx> + #include "clcc/clew.h" #include "formula/token.hxx" @@ -41,8 +43,70 @@ public: /// Failed in marshaling class OpenCLError { +private: + const char *strerror(cl_int i) + { +#define CASE(val) case val: return #val + switch (i) + { + CASE(CL_SUCCESS); + CASE(CL_DEVICE_NOT_FOUND); + CASE(CL_DEVICE_NOT_AVAILABLE); + CASE(CL_COMPILER_NOT_AVAILABLE); + CASE(CL_MEM_OBJECT_ALLOCATION_FAILURE); + CASE(CL_OUT_OF_RESOURCES); + CASE(CL_OUT_OF_HOST_MEMORY); + CASE(CL_PROFILING_INFO_NOT_AVAILABLE); + CASE(CL_MEM_COPY_OVERLAP); + CASE(CL_IMAGE_FORMAT_MISMATCH); + CASE(CL_IMAGE_FORMAT_NOT_SUPPORTED); + CASE(CL_BUILD_PROGRAM_FAILURE); + CASE(CL_MAP_FAILURE); + CASE(CL_INVALID_VALUE); + CASE(CL_INVALID_DEVICE_TYPE); + CASE(CL_INVALID_PLATFORM); + CASE(CL_INVALID_DEVICE); + CASE(CL_INVALID_CONTEXT); + CASE(CL_INVALID_QUEUE_PROPERTIES); + CASE(CL_INVALID_COMMAND_QUEUE); + CASE(CL_INVALID_HOST_PTR); + CASE(CL_INVALID_MEM_OBJECT); + CASE(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR); + CASE(CL_INVALID_IMAGE_SIZE); + CASE(CL_INVALID_SAMPLER); + CASE(CL_INVALID_BINARY); + CASE(CL_INVALID_BUILD_OPTIONS); + CASE(CL_INVALID_PROGRAM); + CASE(CL_INVALID_PROGRAM_EXECUTABLE); + CASE(CL_INVALID_KERNEL_NAME); + CASE(CL_INVALID_KERNEL_DEFINITION); + CASE(CL_INVALID_KERNEL); + CASE(CL_INVALID_ARG_INDEX); + CASE(CL_INVALID_ARG_VALUE); + CASE(CL_INVALID_ARG_SIZE); + CASE(CL_INVALID_KERNEL_ARGS); + CASE(CL_INVALID_WORK_DIMENSION); + CASE(CL_INVALID_WORK_GROUP_SIZE); + CASE(CL_INVALID_WORK_ITEM_SIZE); + CASE(CL_INVALID_GLOBAL_OFFSET); + CASE(CL_INVALID_EVENT_WAIT_LIST); + CASE(CL_INVALID_EVENT); + CASE(CL_INVALID_OPERATION); + CASE(CL_INVALID_GL_OBJECT); + CASE(CL_INVALID_BUFFER_SIZE); + CASE(CL_INVALID_MIP_LEVEL); + CASE(CL_INVALID_GLOBAL_WORK_SIZE); + default: + return "Unknown OpenCL error code"; + } +#undef CASE + } + public: - OpenCLError(cl_int err): mError(err) {} + OpenCLError(cl_int err): mError(err) + { + SAL_INFO("sc.opencl", "OpenCLError:" << mError << ": " << strerror(mError)); + } cl_int mError; }; diff --git a/sc/source/core/tool/clkernelthread.cxx b/sc/source/core/tool/clkernelthread.cxx index e7bda8a432ab..651d3690a5ac 100644 --- a/sc/source/core/tool/clkernelthread.cxx +++ b/sc/source/core/tool/clkernelthread.cxx @@ -35,10 +35,10 @@ void CLBuildKernelThread::execute() while (!done) { SAL_INFO("sc.opencl.thread", "waiting for condition"); - maCondition.wait(); + maQueueCondition.wait(); SAL_INFO("sc.opencl.thread", "got condition"); - osl::ResettableMutexGuard aGuard(maMutex); - maCondition.reset(); + osl::ResettableMutexGuard aGuard(maQueueMutex); + maQueueCondition.reset(); while (!maQueue.empty()) { CLBuildKernelWorkItem aWorkItem = maQueue.front(); @@ -57,7 +57,7 @@ void CLBuildKernelThread::execute() *aWorkItem.mxGroup->mpCode); aWorkItem.mxGroup->meCalcState = sc::GroupCalcOpenCLKernelBinaryCreated; SAL_INFO("sc.opencl.thread", "group " << aWorkItem.mxGroup << " compilation done"); - aWorkItem.mxGroup->maCompilationDone.set(); + maCompilationDoneCondition.set(); break; case CLBuildKernelWorkItem::FINISH: SAL_INFO("sc.opencl.thread", "told to finish"); @@ -72,9 +72,9 @@ void CLBuildKernelThread::execute() void CLBuildKernelThread::push(CLBuildKernelWorkItem item) { - osl::MutexGuard guard(maMutex); + osl::MutexGuard guard(maQueueMutex); maQueue.push(item); - maCondition.set(); + maQueueCondition.set(); } void CLBuildKernelThread::produce() diff --git a/sc/source/core/tool/formulaopt.cxx b/sc/source/core/tool/formulaopt.cxx index 21a453f50c59..ec6696a497fc 100644 --- a/sc/source/core/tool/formulaopt.cxx +++ b/sc/source/core/tool/formulaopt.cxx @@ -412,6 +412,11 @@ void ScFormulaCfg::UpdateFromProperties( const Sequence<OUString>& aNames ) { sal_Bool bVal = GetCalcConfig().mbOpenCLEnabled; pValues[nProp] >>= bVal; +#if 0 // Don't remove please unless the SC_BACKGROUND_COMPILATION env var thing goes away. + // The intent here is that tml when running CppunitTest_sc_opencl_test turns this on. + if (getenv("SC_BACKGROUND_COMPILATION") != NULL) + bVal = sal_True; +#endif GetCalcConfig().mbOpenCLEnabled = bVal; } break; |