Nektar++
Public Member Functions | Private Types | Private Attributes | Static Private Attributes | List of all members
Nektar::Collections::CollectionOptimisation Class Reference

#include <CollectionOptimisation.h>

Public Member Functions

COLLECTIONS_EXPORT CollectionOptimisation (LibUtilities::SessionReaderSharedPtr pSession, ImplementationType defaultType=eStdMat)
 
 ~CollectionOptimisation ()
 
ImplementationType GetDefaultImplementationType ()
 
unsigned int GetMaxCollectionSize ()
 
bool IsUsingAutotuning ()
 
COLLECTIONS_EXPORT OperatorImpMap GetOperatorImpMap (StdRegions::StdExpansionSharedPtr pExp)
 Get Operator Implementation Map from XMl or using default;. More...
 
COLLECTIONS_EXPORT OperatorImpMap SetWithTimings (std::vector< StdRegions::StdExpansionSharedPtr > pGeom, OperatorImpMap &impTypes, bool verbose=true)
 
bool SetByXml (void)
 

Private Types

typedef std::pair< LibUtilities::ShapeType, int > ElmtOrder
 

Private Attributes

std::map< OperatorType, std::map< ElmtOrder, ImplementationType > > m_global
 
bool m_setByXml
 
bool m_autotune
 
ImplementationType m_defaultType
 
unsigned int m_maxCollSize
 

Static Private Attributes

static std::map< OpImpTimingKey, OperatorImpMapm_opImpMap
 

Detailed Description

Definition at line 113 of file CollectionOptimisation.h.

Member Typedef Documentation

◆ ElmtOrder

Definition at line 154 of file CollectionOptimisation.h.

Constructor & Destructor Documentation

◆ CollectionOptimisation()

Nektar::Collections::CollectionOptimisation::CollectionOptimisation ( LibUtilities::SessionReaderSharedPtr  pSession,
ImplementationType  defaultType = eStdMat 
)

Definition at line 52 of file CollectionOptimisation.cpp.

55 {
56  map<ElmtOrder, ImplementationType> defaults, defaultsPhysDeriv;
57  bool verbose = (pSession.get()) &&
58  (pSession->DefinesCmdLineArgument("verbose")) &&
59  (pSession->GetComm()->GetRank() == 0);
60 
61  m_setByXml = false;
62  m_autotune = false;
63  m_maxCollSize = 0;
64  m_defaultType = defaultType == eNoImpType ? eIterPerExp : defaultType;
65 
66  map<string, LibUtilities::ShapeType> elTypes;
67  elTypes["S"] = LibUtilities::eSegment;
68  elTypes["T"] = LibUtilities::eTriangle;
69  elTypes["Q"] = LibUtilities::eQuadrilateral;
70  elTypes["A"] = LibUtilities::eTetrahedron;
71  elTypes["P"] = LibUtilities::ePyramid;
72  elTypes["R"] = LibUtilities::ePrism;
73  elTypes["H"] = LibUtilities::eHexahedron;
74 
75  // Set defaults for all element types.
76  for (auto &it2 : elTypes)
77  {
78  defaults [ElmtOrder(it2.second, -1)] = m_defaultType;
79  defaultsPhysDeriv [ElmtOrder(it2.second, -1)] = m_defaultType;
80  }
81 
82  if (defaultType == eNoImpType)
83  {
84  for (auto &it2 : elTypes)
85  {
86  // For 1<=N<=5 use StdMat otherwise IterPerExp or given default type
87  for (int i = 1; i < 5; ++i)
88  {
89  defaults[ElmtOrder(it2.second, i)] = eStdMat;
90  }
91 
92  // For 1<=N<=3 use SumFac otherwise NoCollection. Note that
93  // default is not currently overwritten by given default
94  // type
95  defaultsPhysDeriv [ElmtOrder(it2.second, -1)] = eNoCollection;
96  for (int i = 1; i < 3; ++i)
97  {
98  defaultsPhysDeriv[ElmtOrder(it2.second, i)] = eSumFac;
99  }
100  }
101  }
102 
103  map<string, OperatorType> opTypes;
104  for (int i = 0; i < SIZE_OperatorType; ++i)
105  {
106  opTypes[OperatorTypeMap[i]] = (OperatorType)i;
107  switch ((OperatorType)i)
108  {
109  case ePhysDeriv:
110  m_global[(OperatorType)i] = defaultsPhysDeriv;
111  break;
112  default:
113  m_global[(OperatorType)i] = defaults;
114  }
115  }
116 
117  map<string, ImplementationType> impTypes;
118  for (int i = 0; i < SIZE_ImplementationType; ++i)
119  {
120  impTypes[ImplementationTypeMap[i]] = (ImplementationType)i;
121  }
122 
123  if(pSession.get()) // turn off file reader if dummy pointer is given
124  {
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.");
129 
130  TiXmlElement *xmlCol = master->FirstChildElement("COLLECTIONS");
131 
132  // Check if user has specified some options
133  if (xmlCol)
134  {
135  // Set the maxsize and default implementation type if provided
136  const char *maxSize = xmlCol->Attribute("MAXSIZE");
137  m_maxCollSize = (maxSize ? atoi(maxSize) : 0);
138 
139  const char *defaultImpl = xmlCol->Attribute("DEFAULT");
140  m_defaultType = defaultType;
141 
142  // If user has specified a default impl type, autotuning
143  // and set this default across all operators.
144  if (defaultType == eNoImpType && defaultImpl)
145  {
146  const std::string collinfo = string(defaultImpl);
147  m_autotune = boost::iequals(collinfo, "auto");
148 
149  if (!m_autotune)
150  {
151  bool collectionFound{false};
152  for(int i = 1; i < Collections::SIZE_ImplementationType; ++i)
153  {
154  if(boost::iequals(collinfo,
156  {
158  collectionFound = true;
159  break;
160  }
161  }
162 
163  ASSERTL0(collectionFound,
164  "Unknown default collection scheme: "+collinfo);
165 
166  defaults.clear();
167  // Override default types
168  for (auto &it2 : elTypes)
169  {
170  defaults[ElmtOrder(it2.second, -1)] = m_defaultType;
171  }
172 
173  for (int i = 0; i < SIZE_OperatorType; ++i)
174  {
175  m_global[(OperatorType)i] = defaults;
176  }
177  }
178  }
179 
180  // Now process operator-specific implementation selections
181  TiXmlElement *elmt = xmlCol->FirstChildElement();
182  while (elmt)
183  {
184  m_setByXml = true;
185 
186  string tagname = elmt->ValueStr();
187 
188  ASSERTL0(boost::iequals(tagname, "OPERATOR"),
189  "Only OPERATOR tags are supported inside the "
190  "COLLECTIONS tag.");
191 
192  const char *attr = elmt->Attribute("TYPE");
193  ASSERTL0(attr, "Missing TYPE in OPERATOR tag.");
194  string opType(attr);
195 
196  ASSERTL0(opTypes.count(opType) > 0,
197  "Unknown OPERATOR type " + opType + ".");
198 
199  OperatorType ot = opTypes[opType];
200 
201  TiXmlElement *elmt2 = elmt->FirstChildElement();
202 
203  while (elmt2)
204  {
205  string tagname = elmt2->ValueStr();
206  ASSERTL0(boost::iequals(tagname, "ELEMENT"),
207  "Only ELEMENT tags are supported inside the "
208  "OPERATOR tag.");
209 
210  const char *attr = elmt2->Attribute("TYPE");
211  ASSERTL0(attr, "Missing TYPE in ELEMENT tag.");
212 
213  string elType(attr);
214  auto it2 = elTypes.find(elType);
215  ASSERTL0(it2 != elTypes.end(),
216  "Unknown element type "+elType+" in ELEMENT "
217  "tag");
218 
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 + ".");
224 
225  const char *attr3 = elmt2->Attribute("ORDER");
226  ASSERTL0(attr3, "Missing ORDER in ELEMENT tag.");
227  string order(attr3);
228 
229  if (order == "*")
230  {
231  m_global[ot][ElmtOrder(it2->second, -1)]
232  = impTypes[impType];
233  }
234  else
235  {
236  vector<unsigned int> orders;
237  ParseUtils::GenerateSeqVector(order, orders);
238 
239  for (int i = 0; i < orders.size(); ++i)
240  {
241  m_global[ot][ElmtOrder(it2->second, orders[i])]
242  = impTypes[impType];
243  }
244  }
245 
246  elmt2 = elmt2->NextSiblingElement();
247  }
248 
249  elmt = elmt->NextSiblingElement();
250  }
251 
252  // Print out operator map
253  if (verbose)
254  {
255  if (!m_setByXml && !m_autotune)
256  {
257  cout << "Setting Collection optimisation using: "
259  << endl;
260  }
261 
262  if (m_setByXml)
263  {
264  for (auto &mIt : m_global)
265  {
266  cout << "Operator " << OperatorTypeMap[mIt.first]
267  << ":" << endl;
268 
269  for (auto &eIt : mIt.second)
270  {
271  cout << "- "
272  << LibUtilities::ShapeTypeMap[eIt.first.first]
273  << " order " << eIt.first.second << " -> "
274  << ImplementationTypeMap[eIt.second] << endl;
275  }
276  }
277  }
278  }
279  }
280  }
281 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::map< OperatorType, std::map< ElmtOrder, ImplementationType > > m_global
std::pair< LibUtilities::ShapeType, int > ElmtOrder
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector.
Definition: ParseUtils.cpp:108
const char *const ImplementationTypeMap[]
Definition: Operator.h:96
const char *const OperatorTypeMap[]
Definition: Operator.h:76
const char *const ShapeTypeMap[]
Definition: ShapeType.hpp:67

References ASSERTL0, Nektar::LibUtilities::eHexahedron, Nektar::Collections::eIterPerExp, Nektar::Collections::eNoCollection, Nektar::Collections::eNoImpType, Nektar::Collections::ePhysDeriv, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::Collections::eStdMat, Nektar::Collections::eSumFac, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, Nektar::Collections::ImplementationTypeMap, Nektar::Collections::OperatorTypeMap, Nektar::LibUtilities::ShapeTypeMap, Nektar::Collections::SIZE_ImplementationType, and Nektar::Collections::SIZE_OperatorType.

◆ ~CollectionOptimisation()

Nektar::Collections::CollectionOptimisation::~CollectionOptimisation ( )
inline

Definition at line 121 of file CollectionOptimisation.h.

121 {};

Member Function Documentation

◆ GetDefaultImplementationType()

ImplementationType Nektar::Collections::CollectionOptimisation::GetDefaultImplementationType ( )
inline

Definition at line 123 of file CollectionOptimisation.h.

124  {
125  return m_defaultType;
126  }

References m_defaultType.

Referenced by Nektar::MultiRegions::ExpList::CreateCollections().

◆ GetMaxCollectionSize()

unsigned int Nektar::Collections::CollectionOptimisation::GetMaxCollectionSize ( )
inline

Definition at line 128 of file CollectionOptimisation.h.

129  {
130  return m_maxCollSize;
131  }

References m_maxCollSize.

Referenced by Nektar::MultiRegions::ExpList::CreateCollections().

◆ GetOperatorImpMap()

OperatorImpMap Nektar::Collections::CollectionOptimisation::GetOperatorImpMap ( StdRegions::StdExpansionSharedPtr  pExp)

Get Operator Implementation Map from XMl or using default;.

Definition at line 283 of file CollectionOptimisation.cpp.

285 {
286  OperatorImpMap ret;
287  ElmtOrder searchKey(pExp->DetShapeType(),
288  pExp->GetBasisNumModes(0));
289  ElmtOrder defSearch(pExp->DetShapeType(), -1);
290 
291  for (auto &it : m_global)
292  {
293  ImplementationType impType;
294 
295  auto it2 = it.second.find(searchKey);
296 
297  if (it2 == it.second.end())
298  {
299  it2 = it.second.find(defSearch);
300  if (it2 == it.second.end())
301  {
302  // Shouldn't be able to reach here.
303  impType = eNoCollection;
304  }
305  else
306  {
307  impType = it2->second;
308  }
309  }
310  else
311  {
312  impType = it2->second;
313  }
314 
315  ret[it.first] = impType;
316  }
317 
318  return ret;
319 }
std::map< OperatorType, ImplementationType > OperatorImpMap
Definition: Operator.h:108

References Nektar::Collections::eNoCollection.

Referenced by Nektar::MultiRegions::ExpList::CreateCollections().

◆ IsUsingAutotuning()

bool Nektar::Collections::CollectionOptimisation::IsUsingAutotuning ( )
inline

Definition at line 133 of file CollectionOptimisation.h.

134  {
135  return m_autotune;
136  }

References m_autotune.

Referenced by Nektar::MultiRegions::ExpList::CreateCollections().

◆ SetByXml()

bool Nektar::Collections::CollectionOptimisation::SetByXml ( void  )
inline

Definition at line 148 of file CollectionOptimisation.h.

149  {
150  return m_setByXml;
151  }

References m_setByXml.

◆ SetWithTimings()

OperatorImpMap Nektar::Collections::CollectionOptimisation::SetWithTimings ( std::vector< StdRegions::StdExpansionSharedPtr pGeom,
OperatorImpMap impTypes,
bool  verbose = true 
)

Definition at line 321 of file CollectionOptimisation.cpp.

325 {
326  boost::ignore_unused(impTypes);
327 
328  OperatorImpMap ret;
329 
330  StdRegions::StdExpansionSharedPtr pExp = pCollExp[0];
331 
332  // check to see if already defined for this expansion
333  OpImpTimingKey OpKey(pExp,pCollExp.size(),pExp->GetNumBases());
334  if(m_opImpMap.count(OpKey) != 0)
335  {
336  ret = m_opImpMap[OpKey];
337  return ret;
338  }
339 
340  int maxsize = pCollExp.size()*max(pExp->GetNcoeffs(),pExp->GetTotPoints());
341  Array<OneD, NekDouble> inarray(maxsize,1.0);
342  Array<OneD, NekDouble> outarray1(maxsize);
343  Array<OneD, NekDouble> outarray2(maxsize);
344  Array<OneD, NekDouble> outarray3(maxsize);
345 
346  LibUtilities::Timer t;
347 
348  if(verbose)
349  {
350  cout << "Collection Implemenation for "
351  << LibUtilities::ShapeTypeMap[pExp->DetShapeType()] << " ( ";
352  for(int i = 0; i < pExp->GetNumBases(); ++i)
353  {
354  cout << pExp->GetBasis(i)->GetNumModes() <<" ";
355  }
356  cout << ")" << " for ngeoms = " << pCollExp.size() << endl;
357  }
358  // set up an array of collections
359  CollectionVector coll;
360 
361  StdRegions::ConstFactorMap factors; // required for helmholtz operator
362  factors[StdRegions::eFactorLambda] = 1.5;
363 
364  for(int imp = 1; imp < SIZE_ImplementationType; ++imp)
365  {
366  ImplementationType impType = (ImplementationType)imp;
367  OperatorImpMap impTypes;
368  for (int i = 0; i < SIZE_OperatorType; ++i)
369  {
370  OperatorType opType = (OperatorType)i;
371  OperatorKey opKey(pCollExp[0]->DetShapeType(), opType, impType,
372  pCollExp[0]->IsNodalNonTensorialExp());
373 
374  if (GetOperatorFactory().ModuleExists(opKey))
375  {
376  impTypes[opType] = impType;
377  }
378  else
379  {
380  cout << "Note: Implementation does not exist: " << opKey << endl;
381  }
382  }
383 
384  Collection collLoc(pCollExp,impTypes);
385  for (int i = 0; i < SIZE_OperatorType; ++i)
386  {
387  collLoc.Initialise((OperatorType)i, factors);
388  }
389  coll.push_back(collLoc);
390  }
391 
392  // Determine the number of tests to do in one second
393  Array<OneD, int> Ntest(SIZE_OperatorType);
394  for(int i = 0; i < SIZE_OperatorType; ++i)
395  {
396  OperatorType OpType = (OperatorType)i;
397 
398  t.Start();
399 
400  coll[0].ApplyOperator(OpType, inarray,
401  outarray1, outarray2,
402  outarray3);
403  t.Stop();
404 
405  NekDouble oneTest = t.TimePerTest(1);
406 
407  Ntest[i] = max((int)(0.25/oneTest),1);
408  }
409 
410  Array<OneD, NekDouble> timing(SIZE_ImplementationType);
411  // loop over all operators and determine fastest implementation
412  for(int i = 0; i < SIZE_OperatorType; ++i)
413  {
414  OperatorType OpType = (OperatorType)i;
415 
416  // call collection implementation in thorugh ExpList.
417  for (int imp = 0; imp < coll.size(); ++imp)
418  {
419  if (coll[imp].HasOperator(OpType))
420  {
421  t.Start();
422  for(int n = 0; n < Ntest[i]; ++n)
423  {
424  coll[imp].ApplyOperator(OpType, inarray,
425  outarray1, outarray2,
426  outarray3);
427  }
428  t.Stop();
429  timing[imp] = t.TimePerTest(Ntest[i]);
430  }
431  else
432  {
433  timing[imp] = 1000.0;
434  }
435  }
436  // determine optimal implementation. Note +1 to
437  // remove NoImplementationType flag
438  int minImp = Vmath::Imin(coll.size(),timing,1)+1;
439 
440  if(verbose)
441  {
442  cout << "\t " << OperatorTypeMap[i] << ": "
443  << ImplementationTypeMap[minImp] << "\t (";
444  for(int j = 0; j < coll.size(); ++j)
445  {
446  if (timing[j] > 999.0)
447  {
448  cout << "-";
449  }
450  else
451  {
452  cout << timing[j] ;
453  }
454  if(j != coll.size()-1)
455  {
456  cout <<", ";
457  }
458  }
459  cout << ")" <<endl;
460  }
461  // could reset global map if reusing method?
462  //m_global[OpType][pExp->DetShapeType()] = (ImplementationType)minImp;
463  // set up new map
464  ret[OpType] = (ImplementationType)minImp;
465  }
466 
467  // store map for use by another expansion.
468  m_opImpMap[OpKey] = ret;
469  return ret;
470 }
static std::map< OpImpTimingKey, OperatorImpMap > m_opImpMap
std::tuple< LibUtilities::ShapeType, OperatorType, ImplementationType, ExpansionIsNodal > OperatorKey
Key for describing an Operator.
Definition: Operator.h:181
OperatorFactory & GetOperatorFactory()
Returns the singleton Operator factory object.
Definition: Operator.cpp:121
std::vector< Collection > CollectionVector
Definition: Collection.h:114
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:314
double NekDouble
int Imin(int n, const T *x, const int incx)
Return the index of the minimum element in x.
Definition: Vmath.cpp:966

References Nektar::StdRegions::eFactorLambda, Nektar::Collections::GetOperatorFactory(), Vmath::Imin(), Nektar::Collections::ImplementationTypeMap, Nektar::Collections::Collection::Initialise(), Nektar::Collections::OperatorTypeMap, Nektar::LibUtilities::ShapeTypeMap, Nektar::Collections::SIZE_ImplementationType, Nektar::Collections::SIZE_OperatorType, Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), and Nektar::LibUtilities::Timer::TimePerTest().

Referenced by Nektar::MultiRegions::ExpList::CreateCollections().

Member Data Documentation

◆ m_autotune

bool Nektar::Collections::CollectionOptimisation::m_autotune
private

Definition at line 159 of file CollectionOptimisation.h.

Referenced by IsUsingAutotuning().

◆ m_defaultType

ImplementationType Nektar::Collections::CollectionOptimisation::m_defaultType
private

Definition at line 160 of file CollectionOptimisation.h.

Referenced by GetDefaultImplementationType().

◆ m_global

std::map<OperatorType, std::map<ElmtOrder, ImplementationType> > Nektar::Collections::CollectionOptimisation::m_global
private

Definition at line 157 of file CollectionOptimisation.h.

◆ m_maxCollSize

unsigned int Nektar::Collections::CollectionOptimisation::m_maxCollSize
private

Definition at line 161 of file CollectionOptimisation.h.

Referenced by GetMaxCollectionSize().

◆ m_opImpMap

map< OpImpTimingKey, OperatorImpMap > Nektar::Collections::CollectionOptimisation::m_opImpMap
staticprivate

Definition at line 156 of file CollectionOptimisation.h.

◆ m_setByXml

bool Nektar::Collections::CollectionOptimisation::m_setByXml
private

Definition at line 158 of file CollectionOptimisation.h.

Referenced by SetByXml().