[Libreoffice-commits] core.git: sc/inc sc/source

Tor Lillqvist tml at collabora.com
Thu Nov 28 05:14:59 PST 2013


 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 <tml at 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;


More information about the Libreoffice-commits mailing list