35 #include <boost/core/ignore_unused.hpp>
36 #include <boost/algorithm/string/predicate.hpp>
50 map<OpImpTimingKey,OperatorImpMap> CollectionOptimisation::m_opImpMap;
52 CollectionOptimisation::CollectionOptimisation(
56 map<ElmtOrder, ImplementationType> defaults, defaultsPhysDeriv;
57 bool verbose = (pSession.get()) &&
58 (pSession->DefinesCmdLineArgument(
"verbose")) &&
59 (pSession->GetComm()->GetRank() == 0);
66 map<string, LibUtilities::ShapeType> elTypes;
76 for (
auto &it2 : elTypes)
78 defaults [
ElmtOrder(it2.second, -1)] = m_defaultType;
79 defaultsPhysDeriv [
ElmtOrder(it2.second, -1)] = m_defaultType;
84 for (
auto &it2 : elTypes)
87 for (
int i = 1; i < 5; ++i)
96 for (
int i = 1; i < 3; ++i)
103 map<string, OperatorType> opTypes;
117 map<string, ImplementationType> impTypes;
125 TiXmlDocument &doc = pSession->GetDocument();
126 TiXmlHandle docHandle(&doc);
127 TiXmlElement *master = docHandle.FirstChildElement(
"NEKTAR").Element();
128 ASSERTL0(master,
"Unable to find NEKTAR tag in file.");
130 TiXmlElement *xmlCol = master->FirstChildElement(
"COLLECTIONS");
136 const char *maxSize = xmlCol->Attribute(
"MAXSIZE");
137 m_maxCollSize = (maxSize ? atoi(maxSize) : 0);
139 const char *defaultImpl = xmlCol->Attribute(
"DEFAULT");
140 m_defaultType = defaultType;
146 const std::string collinfo = string(defaultImpl);
147 m_autotune = boost::iequals(collinfo,
"auto");
151 bool collectionFound{
false};
154 if(boost::iequals(collinfo,
158 collectionFound =
true;
164 "Unknown default collection scheme: "+collinfo);
168 for (
auto &it2 : elTypes)
170 defaults[
ElmtOrder(it2.second, -1)] = m_defaultType;
181 TiXmlElement *elmt = xmlCol->FirstChildElement();
186 string tagname = elmt->ValueStr();
188 ASSERTL0(boost::iequals(tagname,
"OPERATOR"),
189 "Only OPERATOR tags are supported inside the "
192 const char *attr = elmt->Attribute(
"TYPE");
193 ASSERTL0(attr,
"Missing TYPE in OPERATOR tag.");
197 "Unknown OPERATOR type " + opType +
".");
201 TiXmlElement *elmt2 = elmt->FirstChildElement();
205 string tagname = elmt2->ValueStr();
206 ASSERTL0(boost::iequals(tagname,
"ELEMENT"),
207 "Only ELEMENT tags are supported inside the "
210 const char *attr = elmt2->Attribute(
"TYPE");
211 ASSERTL0(attr,
"Missing TYPE in ELEMENT tag.");
214 auto it2 = elTypes.find(elType);
216 "Unknown element type "+elType+
" in ELEMENT "
219 const char *attr2 = elmt2->Attribute(
"IMPTYPE");
220 ASSERTL0(attr2,
"Missing IMPTYPE in ELEMENT tag.");
221 string impType(attr2);
222 ASSERTL0(impTypes.count(impType) > 0,
223 "Unknown IMPTYPE type " + impType +
".");
225 const char *attr3 = elmt2->Attribute(
"ORDER");
226 ASSERTL0(attr3,
"Missing ORDER in ELEMENT tag.");
236 vector<unsigned int> orders;
237 ParseUtils::GenerateSeqVector(order, orders);
239 for (
int i = 0; i < orders.size(); ++i)
241 m_global[ot][
ElmtOrder(it2->second, orders[i])]
246 elmt2 = elmt2->NextSiblingElement();
249 elmt = elmt->NextSiblingElement();
255 if (!m_setByXml && !m_autotune)
257 cout <<
"Setting Collection optimisation using: "
264 for (
auto &mIt : m_global)
269 for (
auto &eIt : mIt.second)
273 <<
" order " << eIt.first.second <<
" -> "
287 ElmtOrder searchKey(pExp->DetShapeType(),
288 pExp->GetBasisNumModes(0));
289 ElmtOrder defSearch(pExp->DetShapeType(), -1);
291 for (
auto &it : m_global)
295 auto it2 = it.second.find(searchKey);
297 if (it2 == it.second.end())
299 it2 = it.second.find(defSearch);
300 if (it2 == it.second.end())
307 impType = it2->second;
312 impType = it2->second;
315 ret[it.first] = impType;
322 vector<StdRegions::StdExpansionSharedPtr> pCollExp,
326 boost::ignore_unused(impTypes);
334 if(m_opImpMap.count(OpKey) != 0)
336 ret = m_opImpMap[OpKey];
340 int maxsize = pCollExp.size()*max(pExp->GetNcoeffs(),pExp->GetTotPoints());
350 cout <<
"Collection Implemenation for "
352 for(
int i = 0; i < pExp->GetNumBases(); ++i)
354 cout << pExp->GetBasis(i)->GetNumModes() <<
" ";
356 cout <<
")" <<
" for ngeoms = " << pCollExp.size() << endl;
371 OperatorKey opKey(pCollExp[0]->DetShapeType(), opType, impType,
372 pCollExp[0]->IsNodalNonTensorialExp());
376 impTypes[opType] = impType;
380 cout <<
"Note: Implementation does not exist: " << opKey << endl;
389 coll.push_back(collLoc);
400 coll[0].ApplyOperator(OpType, inarray,
401 outarray1, outarray2,
407 Ntest[i] = max((
int)(0.25/oneTest),1);
417 for (
int imp = 0; imp < coll.size(); ++imp)
419 if (coll[imp].HasOperator(OpType))
422 for(
int n = 0; n < Ntest[i]; ++n)
424 coll[imp].ApplyOperator(OpType, inarray,
425 outarray1, outarray2,
433 timing[imp] = 1000.0;
444 for(
int j = 0; j < coll.size(); ++j)
446 if (timing[j] > 999.0)
454 if(j != coll.size()-1)
468 m_opImpMap[OpKey] = ret;
#define ASSERTL0(condition, msg)
COLLECTIONS_EXPORT void Initialise(const OperatorType opType, StdRegions::FactorMap factors=StdRegions::NullFactorMap)
std::pair< LibUtilities::ShapeType, int > ElmtOrder
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
std::map< OperatorType, ImplementationType > OperatorImpMap
const char *const ImplementationTypeMap[]
@ SIZE_ImplementationType
const char *const OperatorTypeMap[]
std::tuple< LibUtilities::ShapeType, OperatorType, ImplementationType, ExpansionIsNodal > OperatorKey
Key for describing an Operator.
OperatorFactory & GetOperatorFactory()
Returns the singleton Operator factory object.
std::vector< Collection > CollectionVector
std::shared_ptr< SessionReader > SessionReaderSharedPtr
const char *const ShapeTypeMap[]
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::map< ConstFactorType, NekDouble > ConstFactorMap
The above copyright notice and this permission notice shall be included.
int Imin(int n, const T *x, const int incx)
Return the index of the minimum element in x.