summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2013-11-28 10:59:16 +0200
committerTor Lillqvist <tml@collabora.com>2014-01-07 14:12:14 +0200
commit8e3cb2d536adca7de2acde3cc68f25c32fa2b583 (patch)
treeea457b9206b09c2e214d769e965682ef50d34c4d /sc
parentf6b6aeddde04164ca33f2726335fdcefd9c1c69c (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')
-rw-r--r--sc/inc/clkernelthread.hxx16
-rw-r--r--sc/inc/formulacell.hxx6
-rw-r--r--sc/source/core/data/formulacell.cxx31
-rw-r--r--sc/source/core/opencl/formulagroupcl.cxx15
-rw-r--r--sc/source/core/opencl/opbase.hxx66
-rw-r--r--sc/source/core/tool/clkernelthread.cxx12
-rw-r--r--sc/source/core/tool/formulaopt.cxx5
7 files changed, 112 insertions, 39 deletions
diff --git a/sc/inc/clkernelthread.hxx b/sc/inc/clkernelthread.hxx
index 89ae860318f0..8018d3f68a3e 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 656eebb49ac4..dbb52e45b107 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 1451f0248600..c15710fa8ed8 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 )
@@ -1940,6 +1938,9 @@ bool ScFormulaCell::IsMultilineResult()
void ScFormulaCell::MaybeInterpret()
{
+ if (mxGroup && mxGroup->meCalcState == sc::GroupCalcOpenCLKernelCompilationScheduled)
+ return;
+
if (!IsDirtyOrInTableOpDirty())
return;
@@ -3348,7 +3349,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 a17c34cfb9cb..35ba880d2618 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"
@@ -3210,8 +3211,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;
}
@@ -3227,19 +3229,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);
@@ -3247,7 +3243,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 7c21921bb10b..9fd1d5bad461 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 d5a7dd996774..ebeece1086f7 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;