diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2018-10-12 11:34:20 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2018-11-14 16:09:16 +0100 |
commit | 12c95935f265b484c0a2fa13470085710729c903 (patch) | |
tree | a05fe2319f5acf42bee46ad9da7d64c573d5fe20 /sc/source | |
parent | 7fb235b21d43f3afa340dfeb53efffd516ee21fd (diff) |
$SC_FORCE_CALCULATION to force Calc use opencl/threads for everything
So that e.g. unit tests can be easily run with OpenCL forced. This forces
even single cells to be evaluated using the forced method (many correctness
tests are just a single cell which normally would not be used for grouped
calculation).
Change-Id: If5c6e77a6e0d8696d5416d760cf5e47b8acf3d27
Reviewed-on: https://gerrit.libreoffice.org/63188
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 45 | ||||
-rw-r--r-- | sc/source/core/opencl/formulagroupcl.cxx | 3 | ||||
-rw-r--r-- | sc/source/core/tool/calcconfig.cxx | 37 | ||||
-rw-r--r-- | sc/source/core/tool/recursionhelper.cxx | 15 | ||||
-rw-r--r-- | sc/source/ui/unoobj/docuno.cxx | 4 |
5 files changed, 98 insertions, 6 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 7b0f9e47b3fe..8d16fdf0d352 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1483,12 +1483,43 @@ public: } } }; -} + +// Forced calculation: OpenCL and threads require formula groups, so force even single cells to be a "group". +// Remove the group again at the end, since there are some places throughout the code +// that do not handle well groups with just 1 cell. Remove the groups only when the recursion level +// reaches 0 again (groups contain some info such as disabling threading because of cycles, so removing +// a group immediately would remove the info), for this reason affected cells are stored in the recursion +// helper. +struct TemporaryCellGroupMaker +{ + TemporaryCellGroupMaker( ScFormulaCell* cell, bool enable ) + : mCell( cell ) + , mEnabled( enable ) + { + if( mEnabled && mCell->GetCellGroup() == nullptr ) + { + mCell->CreateCellGroup( 1, false ); + mCell->GetDocument()->GetRecursionHelper().AddTemporaryGroupCell( mCell ); + } + } + ~TemporaryCellGroupMaker() + { + if( mEnabled ) + mCell->GetDocument()->GetRecursionHelper().CleanTemporaryGroupCells(); + } + ScFormulaCell* mCell; + const bool mEnabled; +}; + +} // namespace void ScFormulaCell::Interpret() { ScRecursionHelper& rRecursionHelper = pDocument->GetRecursionHelper(); + static ForceCalculationType forceType = ScCalcConfig::getForceCalculationType(); + TemporaryCellGroupMaker cellGroupMaker( this, forceType != ForceCalculationNone && forceType != ForceCalculationCore ); + ScFormulaCell* pTopCell = mxGroup ? mxGroup->mpTopCell : this; if (pTopCell->mbSeenInPath && rRecursionHelper.GetDepComputeLevel()) @@ -4473,9 +4504,12 @@ bool ScFormulaCell::InterpretFormulaGroup() return false; } - // To temporarily use threading for sc unit tests regardless of the size of the formula group, - // add the condition !std::getenv("LO_TESTNAME") below (with &&) - if (GetWeight() < ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize) + // Use SC_TEST_CALCULATION=opencl/threads to force calculation e.g. for unittests + static ForceCalculationType forceType = ScCalcConfig::getForceCalculationType(); + if (forceType == ForceCalculationCore + || ( GetWeight() < ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize + && forceType != ForceCalculationOpenCL + && forceType != ForceCalculationThreads)) { mxGroup->meCalcState = sc::GroupCalcDisabled; aScope.addGroupSizeThresholdMessage(*this); @@ -4802,7 +4836,8 @@ bool ScFormulaCell::InterpretFormulaGroupOpenCL(sc::FormulaLogger::GroupScope& a if (pInterpreter == nullptr || !pInterpreter->interpret(*pDocument, xGroup->mpTopCell->aPos, xGroup, aCode)) { - SAL_INFO("sc.opencl", "interpreting group " << mxGroup << " (state " << static_cast<int>(mxGroup->meCalcState) << ") failed, disabling"); + SAL_INFO("sc.opencl", "interpreting group " << mxGroup->mpTopCell->aPos + << " (state " << static_cast<int>(mxGroup->meCalcState) << ") failed, disabling"); mxGroup->meCalcState = sc::GroupCalcDisabled; // Undo the hack above diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx index a0c7a098c579..7df68fc77fab 100644 --- a/sc/source/core/opencl/formulagroupcl.cxx +++ b/sc/source/core/opencl/formulagroupcl.cxx @@ -3843,6 +3843,9 @@ bool FormulaGroupInterpreterOpenCL::interpret( ScDocument& rDoc, genRPNTokens(rDoc, rTopPos, rCode); + if( rCode.GetCodeLen() == 0 ) + return false; + CLInterpreterContext aCxt = createCLInterpreterContext(maCalcConfig, xGroup, rCode); if (!aCxt.isValid()) return false; diff --git a/sc/source/core/tool/calcconfig.cxx b/sc/source/core/tool/calcconfig.cxx index 4a1f5d3d3c27..784bd4690df0 100644 --- a/sc/source/core/tool/calcconfig.cxx +++ b/sc/source/core/tool/calcconfig.cxx @@ -43,10 +43,44 @@ static rtl::Reference<ConfigurationListener> const & getFormulaCalculationListen return xListener; } +static ForceCalculationType forceCalculationTypeInit() +{ + const char* env = getenv( "SC_FORCE_CALCULATION" ); + if( env != nullptr ) + { + if( strcmp( env, "opencl" ) == 0 ) + { + SAL_INFO("sc.core.formulagroup", "Forcing calculations to use OpenCL"); + return ForceCalculationOpenCL; + } + if( strcmp( env, "threads" ) == 0 ) + { + SAL_INFO("sc.core.formulagroup", "Forcing calculations to use threads"); + return ForceCalculationThreads; + } + if( strcmp( env, "core" ) == 0 ) + { + SAL_INFO("sc.core.formulagroup", "Forcing calculations to use core"); + return ForceCalculationCore; + } + SAL_WARN("sc.core.formulagroup", "Unrecognized value of SC_TEST_CALCULATION"); + } + return ForceCalculationNone; +} + +ForceCalculationType ScCalcConfig::getForceCalculationType() +{ + static const ForceCalculationType type = forceCalculationTypeInit(); + return type; +} + bool ScCalcConfig::isOpenCLEnabled() { if (utl::ConfigManager::IsFuzzing()) return false; + static ForceCalculationType force = getForceCalculationType(); + if( force != ForceCalculationNone ) + return force == ForceCalculationOpenCL; static comphelper::ConfigurationListenerProperty<bool> gOpenCLEnabled(getMiscListener(), "UseOpenCL"); return gOpenCLEnabled.get(); } @@ -55,6 +89,9 @@ bool ScCalcConfig::isThreadingEnabled() { if (utl::ConfigManager::IsFuzzing()) return false; + static ForceCalculationType force = getForceCalculationType(); + if( force != ForceCalculationNone ) + return force == ForceCalculationThreads; static comphelper::ConfigurationListenerProperty<bool> gThreadingEnabled(getFormulaCalculationListener(), "UseThreadedCalculationForFormulaGroups"); return gThreadingEnabled.get(); } diff --git a/sc/source/core/tool/recursionhelper.cxx b/sc/source/core/tool/recursionhelper.cxx index dd5be99c7155..1375048759e8 100644 --- a/sc/source/core/tool/recursionhelper.cxx +++ b/sc/source/core/tool/recursionhelper.cxx @@ -157,6 +157,21 @@ bool ScRecursionHelper::AnyParentFGInCycle() return false; } +void ScRecursionHelper::AddTemporaryGroupCell(ScFormulaCell* cell) +{ + aTemporaryGroupCells.push_back( cell ); +} + +void ScRecursionHelper::CleanTemporaryGroupCells() +{ + if( GetRecursionCount() == 0 ) + { + for( ScFormulaCell* cell : aTemporaryGroupCells ) + cell->SetCellGroup( nullptr ); + aTemporaryGroupCells.clear(); + } +} + ScFormulaGroupCycleCheckGuard::ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCell* pCell) : mrRecHelper(rRecursionHelper) { diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 22d75e24c58c..3c6baec93899 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -3125,13 +3125,15 @@ void ScModelObj::HandleCalculateEvents() sal_Bool ScModelObj::isOpenCLEnabled() { - return officecfg::Office::Common::Misc::UseOpenCL::get(); + return ScCalcConfig::isOpenCLEnabled(); } void ScModelObj::enableOpenCL(sal_Bool bEnable) { if (ScCalcConfig::isOpenCLEnabled() == static_cast<bool>(bEnable)) return; + if (ScCalcConfig::getForceCalculationType() != ForceCalculationNone) + return; std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); officecfg::Office::Common::Misc::UseOpenCL::set(bEnable, batch); |