Date: prev next · Thread: first prev next last
2015 Archives by date, by thread · List index


Hi Kohei,

        I'd love some input (if you have a minute) on the attached. The
punch-line is, that if we want to do really fast arithmetic, we start to
need to do some odd things; while I suspect that this piece of unrolling
can be done with the iterator - the next step I'm poking at (SSE3
assembler ;-) is not going to like that.

        The win from this on a sum heavy sheet calculation is from 14.4s
seconds to recalculate to 9s (actually testing using the
'puncture_mdds_encap' approach ;-) - a 35%+ speedup.

        I guess, what I'd most like is a:

        'const double *getDoubles(size_t nAtOffset);

        Or somesuch =) or, failing that - a chunked double iterator that would
give a pointer and size (reflecting the underlying chunks but giving
some freedom there).

        Thoughts much appreciated =)

        ATB,

                Michael.

-- 
 michael.meeks@collabora.com  <><, Pseudo Engineer, itinerant idiot
commit 5c3fd002727197d5c4867503b799662193608ce0
Author: Michael Meeks <michael.meeks@collabora.com>
Date:   Sat Oct 24 22:56:39 2015 +0100

    Adapt FuncSum to vectorize better - potentially ...
    
    Change-Id: Ife1523538d4086b0072ca14c768358f4dd3396ab

diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index e02abbc..4caf175 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -203,6 +203,11 @@ double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
 
 namespace {
 
+// this is unpleasant - but ... we want raw access.
+struct puncture_mdds_encap : public sc::numeric_block {
+    const double *getPtr(size_t nOffset) const { return &m_array[nOffset]; }
+};
+
 class NumericCellAccumulator
 {
     double mfSum;
@@ -211,32 +216,63 @@ class NumericCellAccumulator
 public:
     NumericCellAccumulator() : mfSum(0.0), mnError(0) {}
 
-    void operator() (size_t, double fVal)
+    void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
     {
-        mfSum += fVal;
-    }
+        switch (rNode.type)
+        {
+            case sc::element_type_numeric:
+            {
+                sc::numeric_block::const_iterator it = sc::numeric_block::begin(*rNode.data);
+                std::advance(it, nOffset);
+                const double *p = &(*it); // FIXME - this is not ideal at all ...
+#if 0
+                const puncture_mdds_encap *pBlock = static_cast<const puncture_mdds_encap 
*>(rNode.data);
+                const double *p = pBlock->getPtr(nOffset);
+#endif
+                size_t i, nUnrolled = (nDataSize & 0x3) >> 2;
+
+                // Try to encourage the compiler/CPU to do something sensible (?)
+                for (i = 0; i < nUnrolled; i+=4)
+                {
+                    mfSum += p[i];
+                    mfSum += p[i+1];
+                    mfSum += p[i+2];
+                    mfSum += p[i+3];
+                }
+                for (; i < nDataSize; ++i)
+                    mfSum += p[i];
+                break;
+            }
 
-    void operator() (size_t, const ScFormulaCell* pCell)
-    {
-        if (mnError)
-            // Skip all the rest if we have an error.
-            return;
+            case sc::element_type_formula:
+            {
+                sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
+                std::advance(it, nOffset);
+                sc::formula_block::const_iterator itEnd = it;
+                std::advance(itEnd, nDataSize);
+                for (; it != itEnd; ++it)
+                {
+                    double fVal = 0.0;
+                    sal_uInt16 nErr = 0;
+                    ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*(*it));
+                    if (!rCell.GetErrorOrValue(nErr, fVal))
+                        // The cell has neither error nor value.  Perhaps string result.
+                        continue;
 
-        double fVal = 0.0;
-        sal_uInt16 nErr = 0;
-        ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
-        if (!rCell.GetErrorOrValue(nErr, fVal))
-            // The cell has neither error nor value.  Perhaps string result.
-            return;
+                    if (nErr)
+                    {
+                        // Cell has error - skip all the rest
+                        mnError = nErr;
+                        return;
+                    }
 
-        if (nErr)
-        {
-            // Cell has error.
-            mnError = nErr;
-            return;
+                    mfSum += fVal;
+                }
+            }
+            break;
+            default:
+                ;
         }
-
-        mfSum += fVal;
     }
 
     sal_uInt16 getError() const { return mnError; }
@@ -335,7 +371,7 @@ public:
             return;
 
         NumericCellAccumulator aFunc;
-        maPos.miCellPos = sc::ParseFormulaNumeric(maPos.miCellPos, mpCol->GetCellStore(), nRow1, 
nRow2, aFunc);
+        maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, 
nRow2);
         mnError = aFunc.getError();
         if (mnError)
             return;

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.