Skip to content

Commit 41b7466

Browse files
committed
[hist] Used fixed-width SIMD type for interpreted code in TFormula
In the interpreter, we must match the SIMD width used by compiled ROOT. `ROOT::Double_v` aliases the best available native SIMD type, which may differ between compiled and interpreted contexts (e.g. with `-march=native`). Therefore, we explicitly select the fixed-size SIMD type corresponding to the native SIMD width used in compiled ROOT. This fixes failues in the vectorized TFormula tests for platforms with possible mismatch between the SIMD types between interpretd and compiled context (e.g. vanilla Alma 10 or Alma 9 with `march=native` in the CI). Also, disable some subtests in the vectorized TFormula tests if they'd still fail becaues of missing Vc symbols.
1 parent 25f8bbd commit 41b7466

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

hist/hist/src/TFormula.cxx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ std::string doubleToString(double val)
4949
return ss.str();
5050
}
5151

52+
// In the interpreter, we must match the SIMD width used by compiled ROOT.
53+
// ROOT::Double_v aliases the best available native SIMD type, which may differ
54+
// between compiled and interpreted contexts (e.g. with -march=native).
55+
// Therefore, we explicitly select the fixed-size SIMD type corresponding to
56+
// the native SIMD width used in compiled ROOT.
57+
std::string vectorizedArgType()
58+
{
59+
#ifdef VECCORE_ENABLE_VC
60+
auto n = ROOT::Double_v::size();
61+
return "Vc::fixed_size_simd<double, " + std::to_string(n) + ">";
62+
#else
63+
// For other possible VecCore backends, we assume using the same type is fine.
64+
return "ROOT::Double_v";
65+
#endif
66+
}
67+
5268
} // namespace
5369

5470
/** \class TFormula TFormula.h "inc/TFormula.h"
@@ -815,7 +831,7 @@ prepareMethod(bool HasParameters, bool HasVariables, const char* FuncName,
815831
TString prototypeArguments = "";
816832
if (HasVariables || HasParameters) {
817833
if (IsVectorized)
818-
prototypeArguments.Append("ROOT::Double_v const*");
834+
prototypeArguments.Append(vectorizedArgType() + " const*");
819835
else
820836
prototypeArguments.Append("Double_t const*");
821837
}
@@ -2387,7 +2403,7 @@ void TFormula::ProcessFormula(TString &formula)
23872403
if (fVectorized)
23882404
inputFormulaVecFlag += " (vectorized)";
23892405

2390-
TString argType = fVectorized ? "ROOT::Double_v" : "Double_t";
2406+
TString argType = fVectorized ? vectorizedArgType() : "Double_t";
23912407

23922408
// valid input formula - try to put into Cling (in case of no variables but only parameter we need to add the standard signature)
23932409
TString argumentsPrototype = TString::Format("%s%s%s", ( (hasVariables || hasParameters) ? (argType + " const *x").Data() : ""),

test/TFormulaVecTests.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,40 @@ bool testVecFormula() {
9393

9494
bool ok = true;
9595

96+
// Note that we have to disable several tests when using the Vc backend
97+
// because of linker errors. This is because Vc is always built as a static
98+
// library, and linked in MathCore, but the interpreter cannot lookup
99+
// missing symbols for Vc math functions if the formula requires them and
100+
// they are not already linked into MathCore by chance.
101+
// See also:
102+
// https://its.cern.ch/jira/browse/ROOT-10614
103+
// https://github.com/root-project/root/pull/20769
104+
96105
ok &= testVec1D("3+[0]",constant_function, 3.333);
97106
ok &= testVec1D("3",constant_function, 3.333);
107+
#ifndef R__HAS_VC
98108
ok &= testVec1D("sin(x)",std::sin,1);
99109
ok &= testVec1D("cos(x)",std::cos,1);
110+
#endif
100111
ok &= testVec1D("exp(x)",std::exp,1);
101112
ok &= testVec1D("log(x)",std::log,2);
102113
ok &= testVec1D("log10(x)",TMath::Log10,2);
114+
#ifndef R__HAS_VC
103115
ok &= testVec1D("tan(x)",std::tan,1);
104-
//ok &= testVec1D("sinh(x)",std::sinh,1);
105-
//ok &= testVec1D("cosh(x)",std::cosh,1);
106-
//ok &= testVec1D("tanh(x)",std::tanh,1);
116+
ok &= testVec1D("sinh(x)",std::sinh,1);
117+
ok &= testVec1D("cosh(x)",std::cosh,1);
118+
ok &= testVec1D("tanh(x)",std::tanh,1);
107119
ok &= testVec1D("asin(x)",std::asin,.1);
108120
ok &= testVec1D("acos(x)",std::acos,.1);
121+
#endif
109122
ok &= testVec1D("atan(x)",std::atan,.1);
110123
ok &= testVec1D("sqrt(x)",std::sqrt,2);
111124
ok &= testVec1D("abs(x)",std::abs,-1);
112125
ok &= testVec2D("pow(x,y)",std::pow,2,3);
126+
#ifndef R__HAS_VC
113127
ok &= testVec2D("min(x,y)",TMath::Min,2,3);
114128
ok &= testVec2D("max(x,y)",TMath::Max,2,3);
129+
#endif
115130
ok &= testVec2D("atan2(x,y)",TMath::ATan2,2,3);
116131

117132
return ok;

0 commit comments

Comments
 (0)