summaryrefslogtreecommitdiffstats
path: root/sc/source/core/opencl/opbase.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/opencl/opbase.cxx')
-rw-r--r--sc/source/core/opencl/opbase.cxx390
1 files changed, 390 insertions, 0 deletions
diff --git a/sc/source/core/opencl/opbase.cxx b/sc/source/core/opencl/opbase.cxx
new file mode 100644
index 000000000..e197ea002
--- /dev/null
+++ b/sc/source/core/opencl/opbase.cxx
@@ -0,0 +1,390 @@
+/* -*- 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/.
+ */
+
+#include <opencl/openclwrapper.hxx>
+#include <formula/vectortoken.hxx>
+#include <sal/log.hxx>
+
+#include "opbase.hxx"
+
+using namespace formula;
+
+namespace sc::opencl {
+
+UnhandledToken::UnhandledToken(
+ const char* m, const std::string& fn, int ln ) :
+ mMessage(m), mFile(fn), mLineNumber(ln) {}
+
+OpenCLError::OpenCLError( const std::string& function, cl_int error, const std::string& file, int line ) :
+ mFunction(function), mError(error), mFile(file), mLineNumber(line)
+{
+ // Not sure if this SAL_INFO() is useful; the place in
+ // CLInterpreterContext::launchKernel() where OpenCLError is
+ // caught already uses SAL_WARN() to display it.
+
+ // SAL_INFO("sc.opencl", "OpenCL error: " << openclwrapper::errorString(mError));
+}
+
+Unhandled::Unhandled( const std::string& fn, int ln ) :
+ mFile(fn), mLineNumber(ln) {}
+
+InvalidParameterCount::InvalidParameterCount( int parameterCount, const std::string& file, int ln ) :
+ mParameterCount(parameterCount), mFile(file), mLineNumber(ln) {}
+
+DynamicKernelArgument::DynamicKernelArgument( const ScCalcConfig& config, const std::string& s,
+ const FormulaTreeNodeRef& ft ) :
+ mCalcConfig(config), mSymName(s), mFormulaTree(ft) { }
+
+std::string DynamicKernelArgument::GenDoubleSlidingWindowDeclRef( bool ) const
+{
+ return std::string("");
+}
+
+/// When Mix, it will be called
+std::string DynamicKernelArgument::GenStringSlidingWindowDeclRef( bool ) const
+{
+ return std::string("");
+}
+
+/// Generate use/references to the argument
+void DynamicKernelArgument::GenDeclRef( std::stringstream& ss ) const
+{
+ ss << mSymName;
+}
+
+void DynamicKernelArgument::GenSlidingWindowFunction( std::stringstream& ) {}
+
+FormulaToken* DynamicKernelArgument::GetFormulaToken() const
+{
+ return mFormulaTree->GetFormulaToken();
+}
+
+std::string DynamicKernelArgument::DumpOpName() const
+{
+ return std::string("");
+}
+
+void DynamicKernelArgument::DumpInlineFun( std::set<std::string>&, std::set<std::string>& ) const {}
+
+const std::string& DynamicKernelArgument::GetName() const
+{
+ return mSymName;
+}
+
+bool DynamicKernelArgument::NeedParallelReduction() const
+{
+ return false;
+}
+
+VectorRef::VectorRef( const ScCalcConfig& config, const std::string& s, const FormulaTreeNodeRef& ft, int idx ) :
+ DynamicKernelArgument(config, s, ft), mpClmem(nullptr), mnIndex(idx)
+{
+ if (mnIndex)
+ {
+ std::stringstream ss;
+ ss << mSymName << "s" << mnIndex;
+ mSymName = ss.str();
+ }
+}
+
+VectorRef::~VectorRef()
+{
+ if (mpClmem)
+ {
+ cl_int err;
+ err = clReleaseMemObject(mpClmem);
+ SAL_WARN_IF(err != CL_SUCCESS, "sc.opencl", "clReleaseMemObject failed: " << openclwrapper::errorString(err));
+ }
+}
+
+/// Generate declaration
+void VectorRef::GenDecl( std::stringstream& ss ) const
+{
+ ss << "__global double *" << mSymName;
+}
+
+/// When declared as input to a sliding window function
+void VectorRef::GenSlidingWindowDecl( std::stringstream& ss ) const
+{
+ VectorRef::GenDecl(ss);
+}
+
+/// When referenced in a sliding window function
+std::string VectorRef::GenSlidingWindowDeclRef( bool nested ) const
+{
+ std::stringstream ss;
+ formula::SingleVectorRefToken* pSVR =
+ dynamic_cast<formula::SingleVectorRefToken*>(DynamicKernelArgument::GetFormulaToken());
+ if (pSVR && !nested)
+ ss << "(gid0 < " << pSVR->GetArrayLength() << "?";
+ ss << mSymName << "[gid0]";
+ if (pSVR && !nested)
+ ss << ":NAN)";
+ return ss.str();
+}
+
+void VectorRef::GenSlidingWindowFunction( std::stringstream& ) {}
+
+size_t VectorRef::GetWindowSize() const
+{
+ FormulaToken* pCur = mFormulaTree->GetFormulaToken();
+ assert(pCur);
+ if (const formula::DoubleVectorRefToken* pCurDVR =
+ dynamic_cast<const formula::DoubleVectorRefToken*>(pCur))
+ {
+ return pCurDVR->GetRefRowSize();
+ }
+ else if (dynamic_cast<const formula::SingleVectorRefToken*>(pCur))
+ {
+ // Prepare intermediate results (on CPU for now)
+ return 1;
+ }
+ else
+ {
+ throw Unhandled(__FILE__, __LINE__);
+ }
+}
+
+std::string VectorRef::DumpOpName() const
+{
+ return std::string("");
+}
+
+void VectorRef::DumpInlineFun( std::set<std::string>&, std::set<std::string>& ) const {}
+
+const std::string& VectorRef::GetName() const
+{
+ return mSymName;
+}
+
+cl_mem VectorRef::GetCLBuffer() const
+{
+ return mpClmem;
+}
+
+bool VectorRef::NeedParallelReduction() const
+{
+ return false;
+}
+
+void Normal::GenSlidingWindowFunction(
+ std::stringstream& ss, const std::string& sSymName, SubArguments& vSubArguments )
+{
+ std::vector<std::string> argVector;
+ ss << "\ndouble " << sSymName;
+ ss << "_" << BinFuncName() << "(";
+ for (size_t i = 0; i < vSubArguments.size(); i++)
+ {
+ if (i)
+ ss << ",";
+ vSubArguments[i]->GenSlidingWindowDecl(ss);
+ argVector.push_back(vSubArguments[i]->GenSlidingWindowDeclRef());
+ }
+ ss << ") {\n\t";
+ ss << "double tmp = " << GetBottom() << ";\n\t";
+ ss << "int gid0 = get_global_id(0);\n\t";
+ ss << "tmp = ";
+ ss << Gen(argVector);
+ ss << ";\n\t";
+ ss << "return tmp;\n";
+ ss << "}";
+}
+
+void CheckVariables::GenTmpVariables(
+ std::stringstream& ss, const SubArguments& vSubArguments )
+{
+ for (size_t i = 0; i < vSubArguments.size(); i++)
+ {
+ ss << " double tmp";
+ ss << i;
+ ss << ";\n";
+ }
+}
+
+void CheckVariables::CheckSubArgumentIsNan( std::stringstream& ss,
+ SubArguments& vSubArguments, int argumentNum )
+{
+ int i = argumentNum;
+ if (vSubArguments[i]->GetFormulaToken()->GetType() ==
+ formula::svSingleVectorRef)
+ {
+ const formula::SingleVectorRefToken* pTmpDVR1 =
+ static_cast<const formula::SingleVectorRefToken*>(vSubArguments[i]->GetFormulaToken());
+ ss << " if(singleIndex>=";
+ ss << pTmpDVR1->GetArrayLength();
+ ss << " ||";
+ ss << "isnan(";
+ ss << vSubArguments[i]->GenSlidingWindowDeclRef(true);
+ ss << "))\n";
+ ss << " tmp";
+ ss << i;
+ ss << "=0;\n else \n";
+ ss << " tmp";
+ ss << i;
+ ss << "=";
+ ss << vSubArguments[i]->GenSlidingWindowDeclRef(true);
+ ss << ";\n";
+ }
+ if (vSubArguments[i]->GetFormulaToken()->GetType() ==
+ formula::svDoubleVectorRef)
+ {
+ const formula::DoubleVectorRefToken* pTmpDVR2 =
+ static_cast<const formula::DoubleVectorRefToken*>(vSubArguments[i]->GetFormulaToken());
+ ss << " if(doubleIndex>=";
+ ss << pTmpDVR2->GetArrayLength();
+ ss << " ||";
+ ss << "isnan(";
+ ss << vSubArguments[i]->GenSlidingWindowDeclRef();
+ ss << "))\n";
+ ss << " tmp";
+ ss << i;
+ ss << "=0;\n else \n";
+ ss << " tmp";
+ ss << i;
+ ss << "=";
+ ss << vSubArguments[i]->GenSlidingWindowDeclRef();
+ ss << ";\n";
+ }
+ if (vSubArguments[i]->GetFormulaToken()->GetType() != formula::svDouble &&
+ vSubArguments[i]->GetFormulaToken()->GetOpCode() == ocPush)
+ return;
+
+ ss << " if(";
+ ss << "isnan(";
+ ss << vSubArguments[i]->GenSlidingWindowDeclRef();
+ ss << "))\n";
+ ss << " tmp";
+ ss << i;
+ ss << "=0;\n else \n";
+ ss << " tmp";
+ ss << i;
+ ss << "=";
+ ss << vSubArguments[i]->GenSlidingWindowDeclRef();
+ ss << ";\n";
+
+}
+
+void CheckVariables::CheckSubArgumentIsNan2( std::stringstream& ss,
+ SubArguments& vSubArguments, int argumentNum, const std::string& p )
+{
+ int i = argumentNum;
+ if (vSubArguments[i]->GetFormulaToken()->GetType() == formula::svDouble)
+ {
+ ss << " tmp";
+ ss << i;
+ ss << "=";
+ vSubArguments[i]->GenDeclRef(ss);
+ ss << ";\n";
+ return;
+ }
+
+ ss << " tmp";
+ ss << i;
+ ss << "= fsum(";
+ vSubArguments[i]->GenDeclRef(ss);
+ if (vSubArguments[i]->GetFormulaToken()->GetType() ==
+ formula::svDoubleVectorRef)
+ ss << "[" << p.c_str() << "]";
+ else if (vSubArguments[i]->GetFormulaToken()->GetType() ==
+ formula::svSingleVectorRef)
+ ss << "[get_group_id(1)]";
+ ss << ", 0);\n";
+}
+
+void CheckVariables::CheckAllSubArgumentIsNan(
+ std::stringstream& ss, SubArguments& vSubArguments )
+{
+ ss << " int k = gid0;\n";
+ for (size_t i = 0; i < vSubArguments.size(); i++)
+ {
+ CheckSubArgumentIsNan(ss, vSubArguments, i);
+ }
+}
+
+void CheckVariables::UnrollDoubleVector( std::stringstream& ss,
+ const std::stringstream& unrollstr, const formula::DoubleVectorRefToken* pCurDVR,
+ int nCurWindowSize )
+{
+ int unrollSize = 16;
+ if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
+ {
+ ss << " loop = (" << nCurWindowSize << " - gid0)/";
+ ss << unrollSize << ";\n";
+ }
+ else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
+ {
+ ss << " loop = (" << nCurWindowSize << " + gid0)/";
+ ss << unrollSize << ";\n";
+
+ }
+ else
+ {
+ ss << " loop = " << nCurWindowSize << "/" << unrollSize << ";\n";
+ }
+
+ ss << " for ( int j = 0;j< loop; j++)\n";
+ ss << " {\n";
+ ss << " int i = ";
+ if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
+ {
+ ss << "gid0 + j * " << unrollSize << ";\n";
+ }
+ else
+ {
+ ss << "j * " << unrollSize << ";\n";
+ }
+
+ if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
+ {
+ ss << " int doubleIndex = i+gid0;\n";
+ }
+ else
+ {
+ ss << " int doubleIndex = i;\n";
+ }
+
+ for (int j = 0; j < unrollSize; j++)
+ {
+ ss << unrollstr.str();
+ ss << "i++;\n";
+ ss << "doubleIndex++;\n";
+ }
+ ss << " }\n";
+ ss << " for (int i = ";
+ if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed())
+ {
+ ss << "gid0 + loop *" << unrollSize << "; i < ";
+ ss << nCurWindowSize << "; i++)\n";
+ }
+ else if (pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
+ {
+ ss << "0 + loop *" << unrollSize << "; i < gid0+";
+ ss << nCurWindowSize << "; i++)\n";
+ }
+ else
+ {
+ ss << "0 + loop *" << unrollSize << "; i < ";
+ ss << nCurWindowSize << "; i++)\n";
+ }
+ ss << " {\n";
+ if (!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
+ {
+ ss << " int doubleIndex = i+gid0;\n";
+ }
+ else
+ {
+ ss << " int doubleIndex = i;\n";
+ }
+ ss << unrollstr.str();
+ ss << " }\n";
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */