GemaCoreLib
The GeMA Core library
Loading...
Searching...
No Matches
gmTaskManager.h
Go to the documentation of this file.
1/************************************************************************
2**
3** Copyright (C) 2014 by Carlos Augusto Teixera Mendes
4** All rights reserved.
5**
6** This file is part of the "GeMA" software. It's use should respect
7** the terms in the license agreement that can be found together
8** with this source code.
9** It is provided AS IS, with NO WARRANTY OF ANY KIND,
10** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
11** A PARTICULAR PURPOSE.
12**
13************************************************************************/
14
24#ifndef _GEMA_TASK_MANAGER_H_
25#define _GEMA_TASK_MANAGER_H_
26
27#include "gmCoreConfig.h"
28#include "gmValueInfo.h"
29#include "gmThreadManager.h"
30
31#include "gmTrace.h"
32
33#include <luaEnv.h>
34
35//C++ 20 concepts are used to check template parameters and provide better error messages
36//For now we are on C++17, but looking forward it is a good practice to use concepts when possible.
37#if (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) || (__cplusplus >= 202002L)
38#include <concepts>
39#endif
40
42class GmMesh;
43class GmCellMesh;
44class GmCell;
45class GmCellGroupSet;
46class GmNodeSet;
47
48
51{
52public:
54 virtual ~GmNodeTaskDataSet() {}
55
62 virtual int nextNode() = 0;
63
65 virtual void reset() = 0;
66};
67
70{
71public:
73 virtual ~GmCellTaskDataSet() {}
74
76 virtual GmCell* nextCell() = 0;
77
79 virtual void reset() = 0;
80};
81
84{
85public:
86
89 {
90 NPS_DEFAULT = -1,
91 NPS_SEQUENTIAL_BLOCK = 0,
92 NPS_STRIDE = 1,
93
94 //-----------------------------
95 // No entries should be added after this line
96 // IMPORTANT: When adding entries or CHANGING enum order, please remember
97 // to also change str2NodePartitionStrategy() AND
98 // GmLuaUtils::checkAndLoadTaskOptions()
99 //-----------------------------
100 NPS_NUM_STRATEGIES
101 };
102
105 {
106 CPS_DEFAULT = -1,
107 CPS_SEQUENTIAL_BLOCK = 0,
108 CPS_STRIDE = 1,
109 //-----------------------------
110 // No entries should be added after this line
111 // IMPORTANT: When adding entries or CHANGING enum order, please remember
112 // to also change str2CellPartitionStrategy() AND
113 // GmLuaUtils::checkAndLoadTaskOptions()
114 //-----------------------------
115 CPS_NUM_STRATEGIES
116 };
117
119
120 static NodePartitionStrategy str2NodePartitionStrategy(QString str);
121 static CellPartitionStrategy str2CellPartitionStrategy(QString str);
122
124 GmThreadManager* threadManager() const { return _threadManager; }
125
127 int numTasks() const { return _threadManager->numTasks(); }
128
129 template <class T>
130 GmThreadTaskResult runParallelNodeLoop(const GmMesh* m, GmAffectedNodes affNodes, T& taskObj,
131 int ntasks = 0, NodePartitionStrategy strategy = NPS_DEFAULT,
132 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
133
134 template <class T>
135 GmThreadTaskResult runParallelNodeLoop(const GmNodeSet* ns, T& taskObj,
136 int ntasks = 0, NodePartitionStrategy strategy = NPS_DEFAULT,
137 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
138
139 template <class T>
140 GmThreadTaskResult runParallelCountLoop(int count, T& taskObj,
141 int ntasks = 0, NodePartitionStrategy strategy = NPS_DEFAULT,
142 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
143
144 template <class T>
145 void execParallelNodeLoop(const GmMesh* m, GmAffectedNodes affNodes, T& taskObj,
146 int ntasks = 0, NodePartitionStrategy strategy = NPS_DEFAULT,
147 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
148
149 template <class T>
150 void execParallelNodeLoop(const GmNodeSet* m, T& taskObj,
151 int ntasks = 0, NodePartitionStrategy strategy = NPS_DEFAULT,
152 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
153
154 template <class T>
155 GmThreadTaskResult runParallelCellLoop(GmCellMesh* m, bool activeOnly, T& taskObj,
156 int ntasks = 0, CellPartitionStrategy strategy = CPS_DEFAULT,
157 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
158
159 template <class T>
160 GmThreadTaskResult runParallelCellLoop(GmCellGroupSet* gs, bool activeOnly, T& taskObj,
161 int ntasks = 0, CellPartitionStrategy strategy = CPS_DEFAULT,
162 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
163
164 template <class T>
165 void execParallelCellLoop(GmCellMesh* m, bool activeOnly, T& taskObj,
166 int ntasks = 0, CellPartitionStrategy strategy = CPS_DEFAULT,
167 int nworkers = -1, const QVector<int>& taskAffinity = QVector<int>());
168
169 template <class M, class T> bool addNodeTasks(const M* m, GmAffectedNodes affNodes, T& taskObj,
170 int ntasks, NodePartitionStrategy strategy, int nworkers,
171 const QVector<int>& taskAffinity, bool* ok);
172
173 template <class M, class T> bool addCellTasks(M* m, bool activeOnly, T& taskObj,
174 int ntasks, CellPartitionStrategy strategy, int nworkers,
175 const QVector<int>& taskAffinity, bool* ok);
177// Parallel Accessor reducttion //
179
180//C++ 20 concepts are used to check template parameters and provide better error messages
181//For now we are on C++17, but looking forward it is a good practice to use concepts when possible.
182#if (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) || (__cplusplus >= 202002L)
183#include <concepts>
184#endif
185
186/*
187Traverse single accessor, (aggregation)
188*/
189template<typename Accessor, typename ReduceF, typename JoinF, typename InitV>
190 void traverseAccessor(int nworkers, const Accessor* acc, const GmCellMesh* cmesh, const ReduceF& reduce, const JoinF& join, InitV& val);
191
192template<typename Accessor, typename ReduceF, typename JoinF, typename InitV>
193 void traverseAccessor(int nworkers, const Accessor* acc1, const Accessor* acc2, const GmCellMesh* cmesh, const ReduceF& reduce, const JoinF& join, InitV& val);
194
195private:
196 void adjustExecParameters(int* ntasks, int* nworkers);
197
198 template <class M>
199 QVector<GmNodeTaskDataSet*> buildNodePartition(const M* m, int n, GmAffectedNodes affNodes,
200 NodePartitionStrategy strategy) const;
201
202 template <class M>
203 QVector<GmCellTaskDataSet*> buildCellPartition(M* m, int n, bool activeOnly,
204 CellPartitionStrategy strategy) const;
205
207
211};
212
247template <class T>
249 int ntasks, NodePartitionStrategy strategy,
250 int nworkers, const QVector<int>& taskAffinity)
251{
252 S_TRACE();
253
254 // Add tasks to the manager.
255 bool ok;
256 if(!addNodeTasks<GmMesh, T>(m, affNodes, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
257 return ok ? GM_THREAD_OK : GM_THREAD_ABORTED; // false + ok = no tasks
258
259 // Run tasks!
260 return _threadManager->runTasks(nworkers);
261}
262
263template <class T>
265 int ntasks, NodePartitionStrategy strategy,
266 int nworkers, const QVector<int>& taskAffinity)
267{
268 S_TRACE();
269
270 // Add tasks to the manager.
271 bool ok;
272 if (!addNodeTasks<GmNodeSet, T>(ns, GM_BOTH, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
273 return ok ? GM_THREAD_OK : GM_THREAD_ABORTED; // false + ok = no tasks
274
275 // Run tasks!
276 return _threadManager->runTasks(nworkers);
277}
278
279template <class T>
280GmThreadTaskResult GmTaskManager::runParallelCountLoop(int count, T& taskObj,
281 int ntasks, NodePartitionStrategy strategy,
282 int nworkers, const QVector<int>& taskAffinity)
283{
284 S_TRACE();
285
286 // Add tasks to the manager.
287 bool ok;
288 if(!addNodeTasks<int, T>(&count, GM_BOTH, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
289 return ok ? GM_THREAD_OK : GM_THREAD_ABORTED; // false + ok = no tasks
290
291 // Run tasks!
292 return _threadManager->runTasks(nworkers);
293}
294
296template <class T>
298 int ntasks, NodePartitionStrategy strategy,
299 int nworkers, const QVector<int>& taskAffinity)
300{
301 S_TRACE();
302
303 // Add tasks to the manager.
304 bool ok;
305 if(!addNodeTasks<GmMesh, T>(m, affNodes, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
306 {
307 if(!ok)
308 luaL_error(_threadManager->threadLuaEnv(0)->state(), "%s", luaPrintable(QObject::tr("Task execution aborted.")));
309 return;
310 }
311
312 // Run tasks!
313 _threadManager->execTasks(nworkers);
314}
315
316template <class T>
317void GmTaskManager::execParallelNodeLoop(const GmNodeSet* m, T& taskObj,
318 int ntasks, NodePartitionStrategy strategy,
319 int nworkers, const QVector<int>& taskAffinity)
320{
321 S_TRACE();
322
323 // Add tasks to the manager.
324 bool ok;
325 if (!addNodeTasks<GmNodeSet, T>(m, GM_BOTH, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
326 {
327 if (!ok)
328 luaL_error(_threadManager->threadLuaEnv(0)->state(), "%s", luaPrintable(QObject::tr("Task execution aborted.")));
329 return;
330 }
331
332 // Run tasks!
333 _threadManager->execTasks(nworkers);
334}
335
343template <class M, class T>
344bool GmTaskManager::addNodeTasks(const M* m, GmAffectedNodes affNodes, T& taskObj,
345 int ntasks, NodePartitionStrategy strategy, int nworkers,
346 const QVector<int>& taskAffinity, bool* ok)
347{
348 S_TRACE();
349
350 *ok = true;
351
352 // Adjust execution parameters, converting possible default options to real values
353 adjustExecParameters(&ntasks, &nworkers);
354 if(strategy == NPS_DEFAULT)
355 strategy = _defNodeStrategy;
356 assert(ntasks > 0 && nworkers >= 0 && strategy >= 0 && strategy < NPS_NUM_STRATEGIES);
357
358 // Partition the mesh nodes
359 QVector<GmNodeTaskDataSet*> taskData = buildNodePartition<M>(m, ntasks, affNodes, strategy);
360 if(taskData.isEmpty()) // No tasks
361 return false;
362
363 // Check affinity vector
364 bool useAffinity = !taskAffinity.isEmpty();
365 if(useAffinity && taskData.size() != taskAffinity.size())
366 {
367 qDeleteAll(taskData);
368 gmErrorMsg(_threadManager->logger(), QObject::tr("Error creating node tasks. Affinity vector size (%1) is different from the number of tasks (%2).")
369 .arg(taskAffinity.size()).arg(taskData.size()));
370 *ok = false;
371 return false; // No way to support the affinity request
372 }
373
374 // Add tasks to the manager. The thread manager takes ownership and destroys the tasks
375 class NodeTask: public GmThreadTask
376 {
377 public:
378 NodeTask(T& task, GmNodeTaskDataSet* dataSet) : _task(task), _dataSet(dataSet) {}
379 virtual ~NodeTask() { delete _dataSet; }
380
381 virtual GmThreadTaskResult run(const GmThread* thread) { return _task(_dataSet, thread); }
382
383 private:
384 T& _task;
385 GmNodeTaskDataSet* _dataSet;
386 };
387
388 int i = 0;
389 foreach(GmNodeTaskDataSet* ds, taskData)
390 _threadManager->addTask(new NodeTask(taskObj, ds), useAffinity ? taskAffinity[i++] : 0);
391
392 return true;
393}
394
429template <class T>
431 int ntasks, CellPartitionStrategy strategy,
432 int nworkers, const QVector<int>& taskAffinity)
433{
434 S_TRACE();
435
436 // Add tasks to the manager.
437 bool ok;
438 if(!addCellTasks<GmCellMesh, T>(m, activeOnly, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
439 return ok ? GM_THREAD_OK : GM_THREAD_ABORTED; // false + ok = no tasks
440
441 // Run tasks!
442 return _threadManager->runTasks(nworkers);
443}
444
446template <class T>
448 int ntasks, CellPartitionStrategy strategy,
449 int nworkers, const QVector<int>& taskAffinity)
450{
451 S_TRACE();
452
453 // Add tasks to the manager.
454 bool ok;
455 if(!addCellTasks<GmCellGroupSet, T>(gs, activeOnly, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
456 return ok ? GM_THREAD_OK : GM_THREAD_ABORTED; // false + ok = no tasks
457
458 // Run tasks!
459 return _threadManager->runTasks(nworkers);
460}
461
463template <class T>
464void GmTaskManager::execParallelCellLoop(GmCellMesh* m, bool activeOnly, T& taskObj,
465 int ntasks, CellPartitionStrategy strategy,
466 int nworkers, const QVector<int>& taskAffinity)
467{
468 S_TRACE();
469
470 // Add tasks to the manager.
471 bool ok;
472 if(!addCellTasks<GmCellMesh, T>(m, activeOnly, taskObj, ntasks, strategy, nworkers, taskAffinity, &ok))
473 {
474 if(!ok)
475 luaL_error(_threadManager->threadLuaEnv(0)->state(), "%s", luaPrintable(QObject::tr("Task execution aborted.")));
476 return;
477 }
478
479 // Run tasks!
480 _threadManager->execTasks(nworkers);
481}
482
489template <class M, class T>
490bool GmTaskManager::addCellTasks(M* m, bool activeOnly, T& taskObj,
491 int ntasks, CellPartitionStrategy strategy, int nworkers,
492 const QVector<int>& taskAffinity, bool* ok)
493{
494 S_TRACE();
495
496 *ok = true;
497
498 // Adjust execution parameters, converting possible default options to real values
499 adjustExecParameters(&ntasks, &nworkers);
500 if(strategy == CPS_DEFAULT)
501 strategy = _defCellStrategy;
502 assert(ntasks > 0 && nworkers >= 0 && strategy >= 0 && strategy < CPS_NUM_STRATEGIES);
503
504 // Partition the mesh nodes
505 QVector<GmCellTaskDataSet*> taskData = buildCellPartition(m, ntasks, activeOnly, strategy);
506 if(taskData.isEmpty()) // No tasks
507 return false;
508
509 // Check affinity vector
510 bool useAffinity = !taskAffinity.isEmpty();
511 if(useAffinity && taskData.size() != taskAffinity.size())
512 {
513 qDeleteAll(taskData);
514 gmErrorMsg(_threadManager->logger(), QObject::tr("Error creating cell tasks. Affinity vector size (%1) is different from the number of tasks (%2).")
515 .arg(taskAffinity.size()).arg(taskData.size()));
516 *ok = false;
517 return false; // No way to support the affinity request
518 }
519
520 // Add tasks to the manager. The thread manager takes ownership and destroys the tasks
521 class CellTask: public GmThreadTask
522 {
523 public:
524 CellTask(T& task, GmCellTaskDataSet* dataSet) : _task(task), _dataSet(dataSet) {}
525 virtual ~CellTask() { delete _dataSet; }
526
527 virtual GmThreadTaskResult run(const GmThread* thread) { return _task(_dataSet, thread); }
528
529 private:
530 T& _task;
531 GmCellTaskDataSet* _dataSet;
532 };
533
534 int i = 0;
535 foreach(GmCellTaskDataSet* ds, taskData)
536 _threadManager->addTask(new CellTask(taskObj, ds), useAffinity ? taskAffinity[i++] : 0);
537
538 return true;
539}
540
541//Parallel accessor traversal
542
543/*
544Traverse single accessor, (aggregation)
545*/
546template<typename Accessor, typename ReduceF, typename JoinF, typename InitV>
547#if (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) || (__cplusplus >= 202002L)
548 requires std::invocable<ReduceF, const double*, InitV&>
549&& std::invocable<JoinF, const InitV&, InitV&>
550&& (std::same_as<Accessor, GmValueAccessor> || std::same_as<Accessor, GmCellAccessor> || std::same_as<Accessor, GmGaussAccessor>)
551#endif
552void GmTaskManager::traverseAccessor(int nworkers, const Accessor* acc, const GmCellMesh* cmesh, const ReduceF& reduce, const JoinF& join, InitV& val)
553{
554 S_TRACE();
555 assert(acc);
557 tval.init(val);
558
559 const GmMeshGaussIndex* gi;
560 const GmElementMesh* emesh;
561 if constexpr (std::is_same_v<Accessor, GmGaussAccessor>)
562 {
563 gi = acc->gaussIndex();
564 emesh = gi->mesh();
565 assert(emesh == dynamic_cast<const GmElementMesh*>(cmesh));
566 }
567 else if constexpr (std::is_same_v<Accessor, GmCellAccessor>)
568 {
569 }
570 else if constexpr (std::is_same_v<Accessor, GmValueAccessor>)
571 {
572 }
573 else {
574 assert(0);
575 return;
576 }
577
578 auto task = [&](GmNodeTaskDataSet* dataSet, const GmThread* thread) {
579 int i;
580 InitV& lval = tval.localData();
581
582 while ((i = dataSet->nextNode()) != -1)
583 {
584 if (thread->cancelPending())
585 return GM_THREAD_CANCELED;
586
587 const double* v;
588 if constexpr (std::is_same_v<Accessor, GmGaussAccessor>)
589 {
590 //For non-function accessors it would be better to just traverse
591 //the memory, but to be general we need to follow the (cell,ip)
592 //interface.
593 int ip;
594 int cId = gi->cellIp(i, &ip);
595 v = acc->valueAt(emesh->cell(cId), ip, NULL);
596 }
597 else if constexpr (std::is_same_v<Accessor, GmCellAccessor>)
598 {
599 //To avoid warnings with user functions with no coordinates
600 //we use ip=0. The default would be to evaluate at the cell
601 //center but that requires the cell nodes or knowing the
602 //natural coordinates dimension.
603 //If we traverse a cell accessor that is a function varying
604 //within the cell, any kind of reduction operation is already
605 //defeated, so we go for the cheapest "ip=0"
606 int ip = 0;
607 v = acc->valueAt(cmesh->cell(i), NULL, ip);
608 }
609 else if constexpr (std::is_same_v<Accessor, GmValueAccessor>)
610 {
611 v = acc->value(i);
612 }
613 reduce(v, lval);
614 }
615 return GM_THREAD_OK;
616 };
617
618 runParallelCountLoop(acc->size(), task, nworkers);
619
620 //Join thread results
621 for (int i = 0; i < tval.size(); ++i) {
622 join(tval.localData(i), val);
623 }
624}
625
626/*
627Traverse two accessors,(error calculation, etc).
628*/
629template<typename Accessor, typename ReduceF, typename JoinF, typename InitV>
630#if (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) || (__cplusplus >= 202002L)
631 requires std::invocable<ReduceF, const double*, const double*, InitV&>
632&& std::invocable<JoinF, const InitV&, InitV&>
633&& (std::same_as<Accessor, GmValueAccessor> || std::same_as<Accessor, GmCellAccessor> || std::same_as<Accessor, GmGaussAccessor>)
634#endif
635void GmTaskManager::traverseAccessor(int nworkers, const Accessor* acc1, const Accessor* acc2, const GmCellMesh* cmesh, const ReduceF& reduce, const JoinF& join, InitV& val)
636{
637 S_TRACE();
638 assert(acc1 && acc2);
640 tval.init(val);
641
642 const GmMeshGaussIndex* gi;
643 const GmElementMesh* emesh;
644 if constexpr (std::is_same_v<Accessor, GmGaussAccessor>)
645 {
646 gi = acc1->gaussIndex();
647 emesh = gi->mesh();
648 assert(emesh == cmesh);
649 }
650 else if constexpr (std::is_same_v<Accessor, GmCellAccessor>) {}
651 else if constexpr (std::is_same_v<Accessor, GmValueAccessor>) {}
652 else {
653 assert(0);
654 return;
655 }
656 assert(acc1->size() == acc2->size());
657
658 auto task = [&](GmNodeTaskDataSet* dataSet, const GmThread* thread) {
659 int i;
660 InitV& lval = tval.localData();
661
662 while ((i = dataSet->nextNode()) != -1)
663 {
664 if (thread->cancelPending())
665 return GM_THREAD_CANCELED;
666
667 const double* v1, * v2;
668 if constexpr (std::is_same_v<Accessor, GmGaussAccessor>)
669 {
670 //For non-function accessors it would be better to just traverse
671 //the memory, but to be general we need to follow the (cell,ip)
672 //interface.
673 int ip;
674 int cId = gi->cellIp(i, &ip);
675 const GmCell* cell = emesh->cell(cId);
676 v1 = acc1->valueAt(cell, ip, NULL);
677 v2 = acc2->valueAt(cell, ip, NULL);
678 }
679 else if constexpr (std::is_same_v<Accessor, GmCellAccessor>)
680 {
681 const GmCell* cell = cmesh->cell(i);
682 v1 = acc1->valueAt(cell, NULL);
683 v2 = acc2->valueAt(cell, NULL);
684 }
685 else if constexpr (std::is_same_v<Accessor, GmValueAccessor>)
686 {
687 v1 = acc1->value(i);
688 v2 = acc2->value(i);
689 }
690 reduce(v1, v2, lval);
691 }
692 return GM_THREAD_OK;
693 };
694
695 runParallelCountLoop(acc1->size(), task, nworkers);
696
697 //Join thread results
698 for (int i = 0; i < tval.size(); ++i) {
699 join(tval.localData(i), val);
700 }
701}
702
703#endif
Interface for helping managing mesh cell groups and returning the elements in their union.
Definition gmCellGroupSet.h:35
Base interface for mesh cells.
Definition gmCell.h:88
Base interface class for CellMesh type plugins.
Definition gmCellMesh.h:40
virtual const GmCell * cell(int cellIndex) const =0
Returns a cell of the mesh.
Base class for accessing the set of cells belonging to a mesh partition.
Definition gmTaskManager.h:70
virtual ~GmCellTaskDataSet()
Virtual destructor.
Definition gmTaskManager.h:73
virtual GmCell * nextCell()=0
Returns the next cell in the set. Returns NULL when there are no more cells to treat.
virtual void reset()=0
Resets the data set iterator so that the next call to nextCell will return the first cell in the set.
Base interface for FEM (finite element) meshes.
Definition gmElementMesh.h:42
A Gauss index interface always indexing ALL the elements of a mesh, with support for mesh growing.
Definition gmGaussIndex.h:275
const GmElementMesh * mesh() const
Returns the associated mesh.
Definition gmGaussIndex.h:287
Base interface class for Mesh type plugins.
Definition gmMesh.h:48
This class stores a set of nodes belonging to a mesh. The nodes can belong to the mesh boundary but t...
Definition gmNodeSet.h:34
Base class for accessing the set of nodes belonging to a mesh partition.
Definition gmTaskManager.h:51
virtual ~GmNodeTaskDataSet()
Virtual destructor.
Definition gmTaskManager.h:54
virtual int nextNode()=0
Returns the next node in the set. Returns -1 when there are no more nodes to treat....
virtual void reset()=0
Resets the data set iterator so that the next call to nextNode will return the first node in the set.
Auxiliar class used to store the complete set of simulation data.
Definition gmSimulationData.h:55
A class that works together with GmThreadManager to provide thread local storage.
Definition gmThreadLocalStorage.h:132
T & localData(int tid)
Returns the given thread local data as a modifiable reference.
Definition gmThreadLocalStorage.h:163
int size() const
Returns the number of values stored in the TLS object. Equal to the max number of threads + 1 (for th...
Definition gmThreadLocalStorage.h:160
void init(const T &val)
Initializes the value for ALL threads with the given value.
Definition gmThreadLocalStorage.h:153
Task manager used for handling parallel executions.
Definition gmTaskManager.h:84
GmThreadTaskResult runParallelNodeLoop(const GmMesh *m, GmAffectedNodes affNodes, T &taskObj, int ntasks=0, NodePartitionStrategy strategy=NPS_DEFAULT, int nworkers=-1, const QVector< int > &taskAffinity=QVector< int >())
Parallel executes the given task over mesh nodes.
Definition gmTaskManager.h:248
void adjustExecParameters(int *ntasks, int *nworkers)
Adjusts task execution parameters, converting possible default options to real values.
Definition gmTaskManager.cpp:252
bool addCellTasks(M *m, bool activeOnly, T &taskObj, int ntasks, CellPartitionStrategy strategy, int nworkers, const QVector< int > &taskAffinity, bool *ok)
Worker function for adding cell tasks to the thread manager. See runParallelCellLoop() for parameter ...
Definition gmTaskManager.h:490
GmThreadTaskResult runParallelCellLoop(GmCellMesh *m, bool activeOnly, T &taskObj, int ntasks=0, CellPartitionStrategy strategy=CPS_DEFAULT, int nworkers=-1, const QVector< int > &taskAffinity=QVector< int >())
Parallel executes the given task over mesh cells.
Definition gmTaskManager.h:430
void execParallelNodeLoop(const GmMesh *m, GmAffectedNodes affNodes, T &taskObj, int ntasks=0, NodePartitionStrategy strategy=NPS_DEFAULT, int nworkers=-1, const QVector< int > &taskAffinity=QVector< int >())
Similar to runParallelNodeLoop() but raising a lua error if the execution was either canceled or abor...
Definition gmTaskManager.h:297
QVector< GmCellTaskDataSet * > buildCellPartition(M *m, int n, bool activeOnly, CellPartitionStrategy strategy) const
Creates a list with the 'n' parallel cell tasks to be executed, given the destination mesh,...
Definition gmTaskManager.cpp:356
GmThreadManager * threadManager() const
Returns the associated thread manager.
Definition gmTaskManager.h:124
void execParallelCellLoop(GmCellMesh *m, bool activeOnly, T &taskObj, int ntasks=0, CellPartitionStrategy strategy=CPS_DEFAULT, int nworkers=-1, const QVector< int > &taskAffinity=QVector< int >())
Similar to runParallelCellLoop() but raising a lua error if the execution was either canceled or abor...
Definition gmTaskManager.h:464
QVector< GmNodeTaskDataSet * > buildNodePartition(const M *m, int n, GmAffectedNodes affNodes, NodePartitionStrategy strategy) const
Creates a list with the 'n' parallel node tasks to be executed, given the destination mesh,...
Definition gmTaskManager.cpp:270
bool addNodeTasks(const M *m, GmAffectedNodes affNodes, T &taskObj, int ntasks, NodePartitionStrategy strategy, int nworkers, const QVector< int > &taskAffinity, bool *ok)
Worker function for adding node tasks to the thread manager. See runParallelNodeLoop() for parameter ...
Definition gmTaskManager.h:344
int _defNumTasks
The default number of tasks for a parallel loop. Negative numbers are multiples of the number of work...
Definition gmTaskManager.h:208
NodePartitionStrategy
Partition strategies for a parallel node loop.
Definition gmTaskManager.h:89
@ NPS_DEFAULT
Uses the default strategy given by simulation options or NPS_SEQUENTIAL_BLOCK if missing.
Definition gmTaskManager.h:90
@ NPS_NUM_STRATEGIES
The number of partition strategies.
Definition gmTaskManager.h:100
NodePartitionStrategy _defNodeStrategy
The default strategy for node partitioning.
Definition gmTaskManager.h:209
CellPartitionStrategy
Partition strategies for a parallel cell loop.
Definition gmTaskManager.h:105
@ CPS_NUM_STRATEGIES
The number of partition strategies.
Definition gmTaskManager.h:115
@ CPS_DEFAULT
Uses the default strategy given by simulation options or CPS_SEQUENTIAL_BLOCK if missing.
Definition gmTaskManager.h:106
GmThreadManager * _threadManager
The thread manager used to run tasks in multiple threads.
Definition gmTaskManager.h:206
int numTasks() const
Returns the number of tasks added to the queue by addNodetasks or addCellTasks.
Definition gmTaskManager.h:127
CellPartitionStrategy _defCellStrategy
The default strategy for cell partitioning.
Definition gmTaskManager.h:210
Our thread wrapper, specialized for running tasks from the thread manager queue.
Definition gmThreadManager.h:268
Thread manager used for handling parallel executions.
Definition gmThreadManager.h:100
void execTasks(int nthreads)
Similar to runTasks() but raising a lua error if the execution was either canceled or aborted.
Definition gmThreadManager.cpp:951
void addTask(GmThreadTask *task, int tid=0)
Adds a task to the manager. The manager gets the task ownership and will delete it after execution....
Definition gmThreadManager.cpp:776
LuaEnv * threadLuaEnv(int tid) const
Returns the Lua environment associated with the given thread id.
Definition gmThreadManager.cpp:726
const GmLogCategory & logger()
Returns the thread manager logger.
Definition gmThreadManager.h:152
GmThreadTaskResult runTasks(int nthreads)
Executes the set of tasks in the queue using at most 'nthreads'. Waits for the threads to finish befo...
Definition gmThreadManager.cpp:820
Interface for a task executed by a thread manager thread.
Definition gmThreadManager.h:71
int cellIp(int gpIndex, int *ip) const
Given a Gauss point "linear" index (a value from 0 to numPoints()-1), returns the mesh cell index + i...
Definition gmGaussIndex.h:135
lua_State * state()
Declaration of useful configuration definitions for the Core library.
#define GMC_API_EXPORT
Macro for controlling if the class is being exported (GEMA_CORE_LIB defined) or imported (GEMA_CORE_L...
Definition gmCoreConfig.h:35
Declaration of the GmThreadManager class.
GmThreadTaskResult
Possible results for running a task.
Definition gmThreadManager.h:63
@ GM_THREAD_CANCELED
The thread was externally canceled.
Definition gmThreadManager.h:65
@ GM_THREAD_OK
The thread finished its execution without errors.
Definition gmThreadManager.h:64
@ GM_THREAD_ABORTED
The thread aborted.
Definition gmThreadManager.h:66
Auxiliary configuration file used to enable or disable compiling the GeMA tools with support for usin...
#define S_TRACE()
Macro for run time stack tracking at release build.
Definition gmTrace.h:44
Declaration of the GmValueInfo class.
GmAffectedNodes
Affected node types for node based values (GM_NODE_COORDINATES, GM_NODE_ATTRIBUTE or GM_NODE_STATEVAR...
Definition gmValueInfo.h:97
@ GM_BOTH
Specifies that this value exists over mesh and ghost nodes.
Definition gmValueInfo.h:100
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isEmpty() const const
int size() const const