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.me...@collabora.com  <><, Pseudo Engineer, itinerant idiot
commit 5c3fd002727197d5c4867503b799662193608ce0
Author: Michael Meeks <michael.me...@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;
_______________________________________________
LibreOffice mailing list
LibreOffice@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice

Reply via email to