summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2013-11-28 10:59:16 +0200
committerTor Lillqvist <tml@collabora.com>2013-11-28 15:12:10 +0200
commit78d1f562685c9bb8cd24d272b48e9d2d8c086308 (patch)
treef0dd6462cbbfb199af04d33c3998931041e18e60 /sc/source/core
parentf7ef84640258e4ee6ddc4cc5cbf58a2d89860afa (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.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
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;