sc/inc/clkernelthread.hxx | 16 ++++++- sc/inc/formulacell.hxx | 6 -- sc/source/core/data/formulacell.cxx | 31 +++++++------- sc/source/core/opencl/formulagroupcl.cxx | 15 ++----- sc/source/core/opencl/opbase.hxx | 66 ++++++++++++++++++++++++++++++- sc/source/core/tool/clkernelthread.cxx | 12 ++--- sc/source/core/tool/formulaopt.cxx | 5 ++ 7 files changed, 112 insertions(+), 39 deletions(-)
New commits: commit 78d1f562685c9bb8cd24d272b48e9d2d8c086308 Author: Tor Lillqvist <t...@collabora.com> Date: Thu Nov 28 10:59:16 2013 +0200 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 diff --git a/sc/inc/clkernelthread.hxx b/sc/inc/clkernelthread.hxx index 89ae860..8018d3f 100644 --- a/sc/inc/clkernelthread.hxx +++ b/sc/inc/clkernelthread.hxx @@ -7,11 +7,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef INCLUDED_SC_INC_CLKERNELTHREAD_HXX +#define INCLUDED_SC_INC_CLKERNELTHREAD_HXX + #include <queue> #include <osl/conditn.hxx> #include <salhelper/thread.hxx> +#include <boost/noncopyable.hpp> + +#include "scdllapi.h" #include "formulacell.hxx" namespace sc { @@ -22,7 +28,7 @@ struct CLBuildKernelWorkItem ScFormulaCellGroupRef mxGroup; }; -class CLBuildKernelThread : public salhelper::Thread +class SC_DLLPUBLIC CLBuildKernelThread : public salhelper::Thread, boost::noncopyable { public: CLBuildKernelThread(); @@ -32,12 +38,14 @@ public: void push(CLBuildKernelWorkItem item); + osl::Condition maCompilationDoneCondition; + protected: virtual void execute(); private: - osl::Mutex maMutex; - osl::Condition maCondition; + osl::Mutex maQueueMutex; + osl::Condition maQueueCondition; std::queue<CLBuildKernelWorkItem> maQueue; void produce(); void consume(); @@ -45,4 +53,6 @@ private: } +#endif // INCLUDED_SC_INC_CLKERNELTHREAD_HXX + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 656eebb..dbb52e4 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -57,8 +57,6 @@ struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable mutable size_t mnRefCount; ScTokenArray* mpCode; - osl::Mutex maMutex; - osl::Condition maCompilationDone; sc::CompiledFormula* mpCompiledFormula; ScFormulaCell *mpTopCell; SCROW mnLength; // How many of these do we have ? @@ -76,8 +74,8 @@ struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable void compileCode( ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram ); - static int mnCount; - static rtl::Reference<sc::CLBuildKernelThread> mxCLKernelThread; + static int snCount; + static rtl::Reference<sc::CLBuildKernelThread> sxCompilationThread; }; inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p) diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 6144c09..8c3471e 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 4e48e04..623a36c 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 22a9316..a99e7f4 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 e7bda8a..651d369 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 21a453f..ec6696a 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; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits