summaryrefslogtreecommitdiff
path: root/sc/source/core/opencl/formulagroupcl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/opencl/formulagroupcl.cxx')
-rw-r--r--sc/source/core/opencl/formulagroupcl.cxx213
1 files changed, 113 insertions, 100 deletions
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 4f274749484b..967f52c4ce43 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -299,73 +299,8 @@ size_t VectorRef::Marshal( cl_kernel k, int argno, int, cl_program )
return 1;
}
-/// Arguments that are actually compile-time constant string
-/// Currently, only the hash is passed.
-/// TBD(IJSUNG): pass also length and the actual string if there is a
-/// hash function collision
-
-/// FIXME: This idea of passing of hashes of uppercased strings into OpenCL code is fairly potent
-/// crack. It is hopefully not used at all any more, but noticing that there are string arguments
-/// automatically disables use of OpenCL for a formula group. If at some point there are resources
-/// to drain the OpenCL swamp, this should go away.
-
namespace {
-class ConstStringArgument : public DynamicKernelArgument
-{
-public:
- ConstStringArgument( const ScCalcConfig& config, const std::string& s,
- const FormulaTreeNodeRef& ft ) :
- DynamicKernelArgument(config, s, ft) { }
- /// Generate declaration
- virtual void GenDecl( outputstream& ss ) const override
- {
- ss << "unsigned " << mSymName;
- }
- virtual void GenDeclRef( outputstream& ss ) const override
- {
- ss << GenSlidingWindowDeclRef();
- }
- virtual void GenSlidingWindowDecl( outputstream& ss ) const override
- {
- GenDecl(ss);
- }
- virtual std::string GenSlidingWindowDeclRef( bool = false ) const override
- {
- outputstream ss;
- if (GetFormulaToken()->GetType() != formula::svString)
- throw Unhandled(__FILE__, __LINE__);
- FormulaToken* Tok = GetFormulaToken();
- ss << Tok->GetString().getString().toAsciiUpperCase().hashCode() << "U";
- return ss.str();
- }
- virtual size_t GetWindowSize() const override
- {
- return 1;
- }
- /// Pass the 32-bit hash of the string to the kernel
- virtual size_t Marshal( cl_kernel k, int argno, int, cl_program ) override
- {
- OpenCLZone zone;
- FormulaToken* ref = mFormulaTree->GetFormulaToken();
- cl_uint hashCode = 0;
- if (ref->GetType() != formula::svString)
- {
- throw Unhandled(__FILE__, __LINE__);
- }
-
- const OUString s = ref->GetString().getString().toAsciiUpperCase();
- hashCode = s.hashCode();
-
- // Pass the scalar result back to the rest of the formula kernel
- SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": cl_uint: " << hashCode << "(" << DebugPeekData(ref) << ")" );
- cl_int err = clSetKernelArg(k, argno, sizeof(cl_uint), static_cast<void*>(&hashCode));
- if (CL_SUCCESS != err)
- throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
- return 1;
- }
-};
-
class DynamicKernelPiArgument : public DynamicKernelArgument
{
public:
@@ -773,9 +708,65 @@ threefry2x32 (threefry2x32_ctr_t in, threefry2x32_key_t k)\n\
}
};
-}
+// Arguments that are actually compile-time constant string
+class ConstStringArgument : public DynamicKernelArgument
+{
+public:
+ ConstStringArgument( const ScCalcConfig& config, const std::string& s,
+ const FormulaTreeNodeRef& ft ) :
+ DynamicKernelArgument(config, s, ft) { }
+ /// Generate declaration
+ virtual void GenDecl( outputstream& ss ) const override
+ {
+ ss << "double " << mSymName;
+ }
+ virtual void GenDeclRef( outputstream& ss ) const override
+ {
+ ss << GenSlidingWindowDeclRef();
+ }
+ virtual void GenSlidingWindowDecl( outputstream& ss ) const override
+ {
+ GenDecl(ss);
+ }
+ virtual std::string GenSlidingWindowDeclRef( bool = false ) const override
+ {
+ outputstream ss;
+ if (GetFormulaToken()->GetType() != formula::svString)
+ throw Unhandled(__FILE__, __LINE__);
+ FormulaToken* Tok = GetFormulaToken();
+ ss << GetStringId(Tok->GetString().getData());
+ return ss.str();
+ }
+ virtual std::string GenIsString( bool = false ) const override
+ {
+ return "true";
+ }
+ virtual size_t GetWindowSize() const override
+ {
+ return 1;
+ }
+ virtual size_t Marshal( cl_kernel k, int argno, int, cl_program ) override
+ {
+ FormulaToken* ref = mFormulaTree->GetFormulaToken();
+ if (ref->GetType() != formula::svString)
+ {
+ throw Unhandled(__FILE__, __LINE__);
+ }
+ cl_double stringId = GetStringId(ref->GetString().getData());
+
+ // Pass the scalar result back to the rest of the formula kernel
+ SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno
+ << ": stringId: " << stringId << " (" << DebugPeekData(ref) << ")" );
+ cl_int err = clSetKernelArg(k, argno, sizeof(cl_double), static_cast<void*>(&stringId));
+ if (CL_SUCCESS != err)
+ throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
+ return 1;
+ }
+};
+
+} // namespace
-/// Marshal a string vector reference
+// Marshal a string vector reference
size_t DynamicKernelStringArgument::Marshal( cl_kernel k, int argno, int, cl_program )
{
OpenCLZone zone;
@@ -800,12 +791,12 @@ size_t DynamicKernelStringArgument::Marshal( cl_kernel k, int argno, int, cl_pro
nStrings = pDVR->GetArrayLength();
vRef = pDVR->GetArrays()[mnIndex];
}
- size_t szHostBuffer = nStrings * sizeof(cl_int);
- cl_uint* pHashBuffer = nullptr;
+ size_t szHostBuffer = nStrings * sizeof(cl_double);
+ cl_double* pStringIdsBuffer = nullptr;
if (vRef.mpStringArray != nullptr)
{
- // Marshal strings. Right now we pass hashes of these string
+ // Marshal strings. See GetStringId().
mpClmem = clCreateBuffer(kEnv.mpkContext,
cl_mem_flags(CL_MEM_READ_ONLY) | CL_MEM_ALLOC_HOST_PTR,
szHostBuffer, nullptr, &err);
@@ -813,7 +804,7 @@ size_t DynamicKernelStringArgument::Marshal( cl_kernel k, int argno, int, cl_pro
throw OpenCLError("clCreateBuffer", err, __FILE__, __LINE__);
SAL_INFO("sc.opencl", "Created buffer " << mpClmem << " size " << szHostBuffer);
- pHashBuffer = static_cast<cl_uint*>(clEnqueueMapBuffer(
+ pStringIdsBuffer = static_cast<cl_double*>(clEnqueueMapBuffer(
kEnv.mpkCmdQueue, mpClmem, CL_TRUE, CL_MAP_WRITE, 0,
szHostBuffer, 0, nullptr, nullptr, &err));
if (CL_SUCCESS != err)
@@ -822,20 +813,15 @@ size_t DynamicKernelStringArgument::Marshal( cl_kernel k, int argno, int, cl_pro
for (size_t i = 0; i < nStrings; i++)
{
if (vRef.mpStringArray[i])
- {
- const OUString tmp(vRef.mpStringArray[i]);
- pHashBuffer[i] = tmp.hashCode();
- }
+ pStringIdsBuffer[i] = GetStringId(vRef.mpStringArray[i]);
else
- {
- pHashBuffer[i] = 0;
- }
+ rtl::math::setNan(&pStringIdsBuffer[i]);
}
}
else
{
if (nStrings == 0)
- szHostBuffer = sizeof(cl_int); // a dummy small value
+ szHostBuffer = sizeof(cl_double); // a dummy small value
// Marshal as a buffer of NANs
mpClmem = clCreateBuffer(kEnv.mpkContext,
cl_mem_flags(CL_MEM_READ_ONLY) | CL_MEM_ALLOC_HOST_PTR,
@@ -844,27 +830,54 @@ size_t DynamicKernelStringArgument::Marshal( cl_kernel k, int argno, int, cl_pro
throw OpenCLError("clCreateBuffer", err, __FILE__, __LINE__);
SAL_INFO("sc.opencl", "Created buffer " << mpClmem << " size " << szHostBuffer);
- pHashBuffer = static_cast<cl_uint*>(clEnqueueMapBuffer(
+ pStringIdsBuffer = static_cast<cl_double*>(clEnqueueMapBuffer(
kEnv.mpkCmdQueue, mpClmem, CL_TRUE, CL_MAP_WRITE, 0,
szHostBuffer, 0, nullptr, nullptr, &err));
if (CL_SUCCESS != err)
throw OpenCLError("clEnqueueMapBuffer", err, __FILE__, __LINE__);
- for (size_t i = 0; i < szHostBuffer / sizeof(cl_int); i++)
- pHashBuffer[i] = 0;
+ for (size_t i = 0; i < szHostBuffer / sizeof(cl_double); i++)
+ rtl::math::setNan(&pStringIdsBuffer[i]);
}
err = clEnqueueUnmapMemObject(kEnv.mpkCmdQueue, mpClmem,
- pHashBuffer, 0, nullptr, nullptr);
+ pStringIdsBuffer, 0, nullptr, nullptr);
if (CL_SUCCESS != err)
throw OpenCLError("clEnqueueUnmapMemObject", err, __FILE__, __LINE__);
- SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": cl_mem: " << mpClmem << " (" << DebugPeekData(ref,mnIndex) << ")");
+ SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": cl_mem: " << mpClmem
+ << " (stringIds: " << DebugPeekDoubles(pStringIdsBuffer, nStrings) << " "
+ << DebugPeekData(ref,mnIndex) << ")");
err = clSetKernelArg(k, argno, sizeof(cl_mem), static_cast<void*>(&mpClmem));
if (CL_SUCCESS != err)
throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
return 1;
}
+std::string DynamicKernelStringArgument::GenIsString( bool nested ) const
+{
+ if( nested )
+ return "!isnan(" + mSymName + "[gid0])";
+ FormulaToken* ref = mFormulaTree->GetFormulaToken();
+ size_t nStrings = 0;
+ if (ref->GetType() == formula::svSingleVectorRef)
+ {
+ const formula::SingleVectorRefToken* pSVR =
+ static_cast<const formula::SingleVectorRefToken*>(ref);
+ nStrings = pSVR->GetArrayLength();
+ }
+ else if (ref->GetType() == formula::svDoubleVectorRef)
+ {
+ const formula::DoubleVectorRefToken* pDVR =
+ static_cast<const formula::DoubleVectorRefToken*>(ref);
+ nStrings = pDVR->GetArrayLength();
+ }
+ else
+ return "!isnan(" + mSymName + "[gid0])";
+ outputstream ss;
+ ss << "(gid0 < " << nStrings << "? !isnan(" << mSymName << "[gid0]):NAN)";
+ return ss.str();
+}
+
namespace {
/// A mixed string/numeric vector
@@ -903,18 +916,22 @@ public:
ss << ")";
return ss.str();
}
- virtual std::string GenDoubleSlidingWindowDeclRef( bool = false ) const override
+ virtual std::string GenDoubleSlidingWindowDeclRef( bool nested = false ) const override
{
outputstream ss;
- ss << VectorRef::GenSlidingWindowDeclRef();
+ ss << VectorRef::GenSlidingWindowDeclRef( nested );
return ss.str();
}
- virtual std::string GenStringSlidingWindowDeclRef( bool = false ) const override
+ virtual std::string GenStringSlidingWindowDeclRef( bool nested = false ) const override
{
outputstream ss;
- ss << mStringArgument.GenSlidingWindowDeclRef();
+ ss << mStringArgument.GenSlidingWindowDeclRef( nested );
return ss.str();
}
+ virtual std::string GenIsString( bool nested = false ) const override
+ {
+ return mStringArgument.GenIsString( nested );
+ }
virtual size_t Marshal( cl_kernel k, int argno, int vw, cl_program p ) override
{
int i = VectorRef::Marshal(k, argno, vw, p);
@@ -3513,19 +3530,19 @@ class CLInterpreterContext
SCROW mnGroupLength;
public:
- explicit CLInterpreterContext(SCROW nGroupLength)
- : mpKernel(nullptr)
+ explicit CLInterpreterContext(SCROW nGroupLength, std::shared_ptr<DynamicKernel> pKernel )
+ : mpKernelStore(std::move(pKernel))
+ , mpKernel(mpKernelStore.get())
, mnGroupLength(nGroupLength) {}
- bool isValid() const
+ ~CLInterpreterContext()
{
- return mpKernel != nullptr;
+ DynamicKernelArgument::ClearStringIds();
}
- void setManagedKernel( std::shared_ptr<DynamicKernel> pKernel )
+ bool isValid() const
{
- mpKernelStore = std::move(pKernel);
- mpKernel = mpKernelStore.get();
+ return mpKernel != nullptr;
}
CLInterpreterResult launchKernel()
@@ -3571,11 +3588,7 @@ public:
CLInterpreterContext createCLInterpreterContext( const ScCalcConfig& rConfig,
const ScFormulaCellGroupRef& xGroup, const ScTokenArray& rCode )
{
- CLInterpreterContext aCxt(xGroup->mnLength);
-
- aCxt.setManagedKernel(DynamicKernel::create(rConfig, rCode, xGroup->mnLength));
-
- return aCxt;
+ return CLInterpreterContext(xGroup->mnLength, DynamicKernel::create(rConfig, rCode, xGroup->mnLength));
}
void genRPNTokens( ScDocument& rDoc, const ScAddress& rTopPos, ScTokenArray& rCode )