summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2013-11-07 18:09:58 +0200
committerMichael Meeks <michael.meeks@collabora.com>2013-11-20 18:23:02 +0000
commit8764c9e91a27f9953be2a5cab54e08cc2eb35278 (patch)
tree8b89316897df3c08435b597cd71551e1c18173bf /sc
parent13a8fac05425f9d66c643f25faa49c1f17c62474 (diff)
Refactoring in preparation for threaded OpenCL kernel compilation
Introduce a new abstract class CompiledFormula, of which the (existing) class BinaryKernel, that represents one OpenCL kernel, is a concrete subclass. Change-Id: I70fd26fa4bd3de026276727bf9fa8ed01bfb62c9
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/formulacell.hxx7
-rw-r--r--sc/inc/formulagroup.hxx13
-rw-r--r--sc/inc/types.hxx1
-rw-r--r--sc/source/core/data/formulacell.cxx1
-rw-r--r--sc/source/core/inc/dynamickernel.hxx104
-rw-r--r--sc/source/core/opencl/formulagroupcl.cxx140
-rw-r--r--sc/source/core/tool/formulagroup.cxx11
7 files changed, 206 insertions, 71 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index c2e578b902ff..b32f25066ce5 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -38,6 +38,12 @@ struct RefUpdateInsertTabContext;
struct RefUpdateDeleteTabContext;
struct RefUpdateMoveTabContext;
+namespace opencl {
+
+class DynamicKernel;
+
+}
+
}
class ScProgress;
@@ -49,6 +55,7 @@ struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable
mutable size_t mnRefCount;
ScTokenArray* mpCode;
+ sc::opencl::DynamicKernel* mpDynamicKernel;
SCROW mnStart; // Start offset of that cell
SCROW mnLength; // How many of these do we have ?
short mnFormatType;
diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index 7c1636457809..faccbfb58fa1 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -75,6 +75,13 @@ struct FormulaGroupContext : boost::noncopyable
};
/**
+ * Abstract base class for a "compiled" formula
+ */
+class SC_DLLPUBLIC CompiledFormula
+{
+};
+
+/**
* Abstract base class for vectorised formula group interpreters,
* plus a global instance factory.
*/
@@ -92,6 +99,9 @@ class SC_DLLPUBLIC FormulaGroupInterpreter
static void enableOpenCL(bool bEnable);
virtual ScMatrixRef inverseMatrix(const ScMatrix& rMat) = 0;
+ virtual CompiledFormula* createCompiledFormula(ScDocument& rDoc,
+ const ScAddress& rTopPos,
+ ScTokenArray& rCode) = 0;
virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode) = 0;
};
@@ -103,6 +113,9 @@ public:
virtual ~FormulaGroupInterpreterSoftware() {}
virtual ScMatrixRef inverseMatrix(const ScMatrix& rMat);
+ virtual CompiledFormula* createCompiledFormula(ScDocument& rDoc,
+ const ScAddress& rTopPos,
+ ScTokenArray& rCode) SAL_OVERRIDE;
virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode);
};
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 045d6b128580..170434124163 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -59,6 +59,7 @@ const sal_uInt16 MatrixEdgeOpen = 32;
enum GroupCalcState
{
GroupCalcEnabled,
+ GroupCalcOpenCLKernelBinaryCreated,
GroupCalcRunning,
GroupCalcDisabled
};
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index ab6dda9799ff..7c48a00a073c 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -385,6 +385,7 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD
ScFormulaCellGroup::ScFormulaCellGroup() :
mnRefCount(0),
mpCode(NULL),
+ mpDynamicKernel(NULL),
mnStart(0),
mnLength(0),
mnFormatType(NUMBERFORMAT_NUMBER),
diff --git a/sc/source/core/inc/dynamickernel.hxx b/sc/source/core/inc/dynamickernel.hxx
new file mode 100644
index 000000000000..e926be556af1
--- /dev/null
+++ b/sc/source/core/inc/dynamickernel.hxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SC_SOURCE_CORE_INC_DYNAMICKERNEL_HXX
+#define INCLUDED_SC_SOURCE_CORE_INC_DYNAMICKERNEL_HXX
+
+#include <config_features.h>
+
+#include "formulagroup.hxx"
+
+#if !HAVE_FEATURE_OPENCL
+
+namespace sc { namespace opencl {
+
+class DynamikcKernel : public CompiledFormula
+{
+}
+
+} // namespace opencl
+
+} // namespace sc
+
+#else
+
+#include "clew.h"
+
+#include "document.hxx"
+#include "opbase.hxx"
+
+namespace sc { namespace opencl {
+
+class DynamicKernelArgument;
+class SlidingFunctionBase;
+
+/// Holds the symbol table for a given dynamic kernel
+class SymbolTable {
+public:
+ typedef std::map<const formula::FormulaToken *,
+ boost::shared_ptr<DynamicKernelArgument> > ArgumentMap;
+ // This avoids instability caused by using pointer as the key type
+ typedef std::list< boost::shared_ptr<DynamicKernelArgument> > ArgumentList;
+ SymbolTable(void):mCurId(0) {}
+ template <class T>
+ const DynamicKernelArgument *DeclRefArg(FormulaTreeNodeRef, SlidingFunctionBase* pCodeGen);
+ /// Used to generate sliding window helpers
+ void DumpSlidingWindowFunctions(std::stringstream &ss);
+ /// Memory mapping from host to device and pass buffers to the given kernel as
+ /// arguments
+ void Marshal(cl_kernel, int, cl_program);
+private:
+ unsigned int mCurId;
+ ArgumentMap mSymbols;
+ ArgumentList mParams;
+};
+
+class DynamicKernel : public CompiledFormula
+{
+public:
+ DynamicKernel(FormulaTreeNodeRef r):mpRoot(r),
+ mpProgram(NULL), mpKernel(NULL), mpResClmem(NULL) {}
+ static DynamicKernel *create(ScDocument& rDoc,
+ const ScAddress& rTopPos,
+ ScTokenArray& rCode);
+ /// Code generation in OpenCL
+ void CodeGen();
+ /// Produce kernel hash
+ std::string GetMD5(void);
+ /// Create program, build, and create kerenl
+ /// TODO cache results based on kernel body hash
+ /// TODO: abstract OpenCL part out into OpenCL wrapper.
+ void CreateKernel(void);
+ /// Prepare buffers, marshal them to GPU, and launch the kernel
+ /// TODO: abstract OpenCL part out into OpenCL wrapper.
+ void Launch(size_t nr);
+ ~DynamicKernel();
+ cl_mem GetResultBuffer(void) const { return mpResClmem; }
+private:
+ void TraverseAST(FormulaTreeNodeRef);
+ FormulaTreeNodeRef mpRoot;
+ SymbolTable mSyms;
+ std::string mKernelSignature, mKernelHash;
+ std::string mFullProgramSrc;
+ cl_program mpProgram;
+ cl_kernel mpKernel;
+ cl_mem mpResClmem; // Results
+ std::set<std::string> inlineDecl;
+ std::set<std::string> inlineFun;
+};
+
+}
+
+}
+
+#endif // HAVE_FEATURE_OPENCL
+
+#endif // INCLUDED_SC_SOURCE_CORE_INC_DYNAMICKERNEL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 40df1aeecd95..17536b68c428 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -16,6 +16,7 @@
#include "formula/vectortoken.hxx"
#include "scmatrix.hxx"
+#include "dynamickernel.hxx"
#include "openclwrapper.hxx"
#include "op_financial.hxx"
@@ -44,6 +45,7 @@
#include <boost/scoped_ptr.hpp>
+#undef NO_FALLBACK_TO_SWINTERP /* undef this for non-TDD runs */
using namespace formula;
@@ -2377,33 +2379,16 @@ DynamicKernelSoPArguments::DynamicKernelSoPArguments(
};
}
}
-/// Holds the symbol table for a given dynamic kernel
-class SymbolTable {
-public:
- typedef std::map<const FormulaToken *,
- boost::shared_ptr<DynamicKernelArgument> > ArgumentMap;
- // This avoids instability caused by using pointer as the key type
- typedef std::list< boost::shared_ptr<DynamicKernelArgument> > ArgumentList;
- SymbolTable(void):mCurId(0) {}
- template <class T>
- const DynamicKernelArgument *DeclRefArg(FormulaTreeNodeRef, SlidingFunctionBase* pCodeGen);
- /// Used to generate sliding window helpers
- void DumpSlidingWindowFunctions(std::stringstream &ss)
- {
+
+/// Used to generate sliding window helpers
+void SymbolTable::DumpSlidingWindowFunctions(std::stringstream &ss)
+{
for(ArgumentList::iterator it = mParams.begin(), e= mParams.end(); it!=e;
++it) {
(*it)->GenSlidingWindowFunction(ss);
ss << "\n";
}
- }
- /// Memory mapping from host to device and pass buffers to the given kernel as
- /// arguments
- void Marshal(cl_kernel, int, cl_program);
-private:
- unsigned int mCurId;
- ArgumentMap mSymbols;
- ArgumentList mParams;
-};
+}
void SymbolTable::Marshal(cl_kernel k, int nVectorWidth, cl_program pProgram)
{
@@ -2414,13 +2399,9 @@ void SymbolTable::Marshal(cl_kernel k, int nVectorWidth, cl_program pProgram)
}
}
-/// Code generation
-class DynamicKernel {
-public:
- DynamicKernel(FormulaTreeNodeRef r):mpRoot(r),
- mpProgram(NULL), mpKernel(NULL), mpResClmem(NULL) {}
/// Code generation in OpenCL
- void CodeGen() {
+void DynamicKernel::CodeGen()
+{
// Travese the tree of expression and declare symbols used
const DynamicKernelArgument *DK= mSyms.DeclRefArg<
DynamicKernelSoPArguments>(mpRoot, new OpNop);
@@ -2456,10 +2437,11 @@ public:
#if 1
std::cerr<< "Program to be compiled = \n" << mFullProgramSrc << "\n";
#endif
- }
- /// Produce kernel hash
- std::string GetMD5(void)
- {
+}
+
+/// Produce kernel hash
+std::string DynamicKernel::GetMD5(void)
+{
#ifdef MD5_KERNEL
if (mKernelHash.empty()) {
std::stringstream md5s;
@@ -2478,15 +2460,12 @@ public:
#else
return "";
#endif
- }
- /// Create program, build, and create kerenl
- /// TODO cache results based on kernel body hash
- /// TODO: abstract OpenCL part out into OpenCL wrapper.
- void CreateKernel(void);
- /// Prepare buffers, marshal them to GPU, and launch the kernel
- /// TODO: abstract OpenCL part out into OpenCL wrapper.
- void Launch(size_t nr)
- {
+}
+
+/// Prepare buffers, marshal them to GPU, and launch the kernel
+/// TODO: abstract OpenCL part out into OpenCL wrapper.
+void DynamicKernel::Launch(size_t nr)
+{
// Obtain cl context
KernelEnv kEnv;
OpenclDevice::setKernelEnv(&kEnv);
@@ -2507,21 +2486,7 @@ public:
global_work_size, NULL, 0, NULL, NULL);
if (CL_SUCCESS != err)
throw OpenCLError(err);
- }
- ~DynamicKernel();
- cl_mem GetResultBuffer(void) const { return mpResClmem; }
-private:
- void TraverseAST(FormulaTreeNodeRef);
- FormulaTreeNodeRef mpRoot;
- SymbolTable mSyms;
- std::string mKernelSignature, mKernelHash;
- std::string mFullProgramSrc;
- cl_program mpProgram;
- cl_kernel mpKernel;
- cl_mem mpResClmem; // Results
- std::set<std::string> inlineDecl;
- std::set<std::string> inlineFun;
-};
+}
DynamicKernel::~DynamicKernel()
{
@@ -2606,9 +2571,11 @@ public:
}
virtual ScMatrixRef inverseMatrix( const ScMatrix& rMat );
+ virtual CompiledFormula* createCompiledFormula(ScDocument& rDoc,
+ const ScAddress& rTopPos,
+ ScTokenArray& rCode);
virtual bool interpret( ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode );
- DynamicKernel *mpKernel;
};
ScMatrixRef FormulaGroupInterpreterOpenCL::inverseMatrix( const ScMatrix& )
@@ -2616,11 +2583,10 @@ ScMatrixRef FormulaGroupInterpreterOpenCL::inverseMatrix( const ScMatrix& )
return NULL;
}
-bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc,
- const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup,
- ScTokenArray& rCode )
+DynamicKernel* DynamicKernel::create(ScDocument& rDoc,
+ const ScAddress& rTopPos,
+ ScTokenArray& rCode)
{
- // printf("Vector width = %d\n", xGroup->mnLength);
// Constructing "AST"
FormulaTokenIterator aCode = rCode;
std::list<FormulaToken *> list;
@@ -2641,7 +2607,7 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc,
if(m_TempFormula->GetOpCode()!=ocPush)
{
if(m_hash_map.find(m_TempFormula)==m_hash_map.end())
- return false;
+ return NULL;
m_currNode->Children.push_back(m_hash_map[m_TempFormula]);
}
else
@@ -2661,20 +2627,55 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc,
FormulaTreeNodeRef Root = FormulaTreeNodeRef(new FormulaTreeNode(NULL));
Root->Children.push_back(m_hash_map[list.back()]);
+
+ DynamicKernel* pDynamicKernel = new DynamicKernel(Root);
+
+ if (!pDynamicKernel)
+ return NULL;
+
// Code generation
- mpKernel = new DynamicKernel(Root);
+ try {
+ pDynamicKernel->CodeGen();
+ }
+ catch (const UnhandledToken &ut) {
+ std::cerr << "\nDynamic formual compiler: unhandled token: ";
+ std::cerr << ut.mMessage << "\n";
+#ifdef NO_FALLBACK_TO_SWINTERP
+ assert(false);
+#else
+ free(pDynamicKernel);
+ return NULL;
+#endif
+ }
+ return pDynamicKernel;
+}
+
+CompiledFormula* FormulaGroupInterpreterOpenCL::createCompiledFormula(ScDocument& rDoc,
+ const ScAddress& rTopPos,
+ ScTokenArray& rCode)
+{
+ return sc::opencl::DynamicKernel::create(rDoc, rTopPos, rCode);
+}
+
+bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc,
+ const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup,
+ ScTokenArray& rCode )
+{
+ // printf("Vector width = %d\n", xGroup->mnLength);
+ DynamicKernel *pKernel = DynamicKernel::create(rDoc, rTopPos, rCode);
+ if (!pKernel)
+ return false;
try {
- mpKernel->CodeGen();
// Obtain cl context
KernelEnv kEnv;
OpenclDevice::setKernelEnv(&kEnv);
// Compile kernel here!!!
- mpKernel->CreateKernel();
+ pKernel->CreateKernel();
// Run the kernel.
- mpKernel->Launch(xGroup->mnLength);
+ pKernel->Launch(xGroup->mnLength);
// Map results back
- cl_mem res = mpKernel->GetResultBuffer();
+ cl_mem res = pKernel->GetResultBuffer();
cl_int err;
double *resbuf = (double*)clEnqueueMapBuffer(kEnv.mpkCmdQueue,
res,
@@ -2687,9 +2688,8 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc,
err = clEnqueueUnmapMemObject(kEnv.mpkCmdQueue, res, resbuf, 0, NULL, NULL);
if (err != CL_SUCCESS)
throw OpenCLError(err);
- delete mpKernel;
+ delete pKernel;
}
-#undef NO_FALLBACK_TO_SWINTERP /* undef this for non-TDD runs */
catch (const UnhandledToken &ut) {
std::cerr << "\nDynamic formual compiler: unhandled token: ";
std::cerr << ut.mMessage << "\n";
@@ -2758,6 +2758,6 @@ SAL_DLLPUBLIC_EXPORT bool SAL_CALL switchOpenClDevice(
return sc::opencl::switchOpenclDevice(pDeviceId, bAutoSelect);
}
-}
+} // extern "C"
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 8eb1fdec7bd3..a31558526d60 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -16,6 +16,7 @@
#include "compiler.hxx"
#include "interpre.hxx"
#include "scmatrix.hxx"
+#include "dynamickernel.hxx"
#include "formula/vectortoken.hxx"
#include "rtl/bootstrap.hxx"
@@ -284,6 +285,13 @@ ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMa
return ScMatrixRef();
}
+CompiledFormula* FormulaGroupInterpreterSoftware::createCompiledFormula(ScDocument& /* rDoc */,
+ const ScAddress& /* rTopPos */,
+ ScTokenArray& /* rCode */)
+{
+ return NULL;
+}
+
bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup,
ScTokenArray& rCode)
@@ -486,6 +494,7 @@ public:
FormulaGroupInterpreterOpenCLMissing() : FormulaGroupInterpreter() {}
virtual ~FormulaGroupInterpreterOpenCLMissing() {}
virtual ScMatrixRef inverseMatrix(const ScMatrix&) { return ScMatrixRef(); }
+ virtual CompiledFormula* createCompiledFormula(ScDocument&, const ScAddress&, ScTokenArray&) SAL_OVERRIDE { return NULL; }
virtual bool interpret(ScDocument&, const ScAddress&, const ScFormulaCellGroupRef&, ScTokenArray&) { return false; }
};
@@ -651,6 +660,6 @@ void FormulaGroupInterpreter::enableOpenCL(bool bEnable)
ScInterpreter::SetGlobalConfig(aConfig);
}
-}
+} // namespace sc
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */