Internal:Argobots and CDT3D: Difference between revisions
| Line 564: | Line 564: | ||
! 35 | ! 35 | ||
! 40 | ! 40 | ||
! colspan="11" | Mesh Refinement | ! colspan="11" | Mesh Refinement | ||
|- | |- | ||
! | ! rowspan="2" MR|Time to insert vertices | ||
| 0.02 (2.38) | | 0.02 | ||
| 0.06 (6.32) | | (2.38) | ||
| 0.01 (1.12) | | 0.06 | ||
| 0.01 (0.58) | | (6.32) | ||
| -0.00 (-0.40) | | 0.01 | ||
| 0.05 (4.28) | | (1.12) | ||
| 0.05 (4.70) | | 0.01 | ||
| -0.01 (-0.88) | | (0.58) | ||
| 0.05 (4.73) | | -0.00 | ||
| 0.06 (5.65) | | (-0.40) | ||
| 0.05 | |||
| (4.28) | |||
| 0.05 | |||
| (4.70) | |||
| -0.01 | |||
| (-0.88) | |||
| 0.05 | |||
| (4.73) | |||
| 0.06 | |||
| (5.65) | |||
|- | |- | ||
! | ! rowspan="2" MR|Time to create vertices | ||
| 0.01 (0.09) | | 0.01 | ||
| 0.94 (17.77) | | (0.09) | ||
| 0.49 (19.57) | | 0.94 | ||
| 0.24 (18.17) | | (17.77) | ||
| 0.20 (20.08) | | 0.49 | ||
| 0.13 (16.39) | | (19.57) | ||
| 0.13 (19.29) | | 0.24 | ||
| 0.13 (20.35) | | (18.17) | ||
| 0.11 (18.69) | | 0.20 | ||
| 0.06 (12.62) | | (20.08) | ||
| 0.13 | |||
| (16.39) | |||
| 0.13 | |||
| (19.29) | |||
| 0.13 | |||
| (20.35) | |||
| 0.11 | |||
| (18.69) | |||
| 0.06 | |||
| (12.62) | |||
|- | |- | ||
! | ! rowspan="2" MR|Total time to optimize connectivity | ||
| 0.31 (0.09) | | 0.31 | ||
| -1.66 (-1.35) | | (0.09) | ||
| -0.57 (-1.11) | | -1.66 | ||
| -0.60 (-2.33) | | (-1.35) | ||
| -0.67 (-3.63) | | -0.57 | ||
| -0.83 (-5.44) | | (-1.11) | ||
| -0.79 (-6.01) | | -0.60 | ||
| -0.58 (-4.94) | | (-2.33) | ||
| -0.59 (-5.64) | | -0.67 | ||
| -0.61 (-6.50) | | (-3.63) | ||
| -0.83 | |||
| (-5.44) | |||
| -0.79 | |||
| (-6.01) | |||
| -0.58 | |||
| (-4.94) | |||
| -0.59 | |||
| (-5.64) | |||
| -0.61 | |||
| (-6.50) | |||
|- | |- | ||
! | ! rowspan="2" MR|Time to remove small edges | ||
| -0.71 (-2.72) | | -0.71 | ||
| 1.05 (8.01) | | (-2.72) | ||
| -2.75 (-41.21) | | 1.05 | ||
| -1.23 (-29.26) | | (8.01) | ||
| -0.39 (-14.11) | | -2.75 | ||
| -0.37 (-16.03) | | (-41.21) | ||
| -0.37 (-21.31) | | -1.23 | ||
| -0.43 (-27.97) | | (-29.26) | ||
| -0.31 (-23.25) | | -0.39 | ||
| -0.19 (-16.41) | | (-14.11) | ||
| -0.37 | |||
| (-16.03) | |||
| -0.37 | |||
| (-21.31) | |||
| -0.43 | |||
| (-27.97) | |||
| -0.31 | |||
| (-23.25) | |||
| -0.19 | |||
| (-16.41) | |||
|- | |- | ||
! | ! rowspan="2" MR|Total time to refine the mesh | ||
| 0.59 (0.15) | | 0.59 | ||
| 1.58 (1.05) | | (0.15) | ||
| -1.56 (-2.36) | | 1.58 | ||
| -0.43 (-1.21) | | (1.05) | ||
| 0.18 (0.71) | | -1.56 | ||
| 0.02 (0.10) | | (-2.36) | ||
| 0.10 (0.51) | | -0.43 | ||
| 0.16 (0.94) | | (-1.21) | ||
| 0.33 (2.09) | | 0.18 | ||
| 0.42 (2.92) | | (0.71) | ||
| 0.02 | |||
| (0.10) | |||
| 0.10 | |||
| (0.51) | |||
| 0.16 | |||
| (0.94) | |||
| 0.33 | |||
| (2.09) | |||
| 0.42 | |||
| (2.92) | |||
|- | |- | ||
! colspan="11" | Mesh Quality Improvement | ! colspan="11" | Mesh Quality Improvement | ||
|- | |- | ||
! | ! rowspan="2" MI|Total time to optimize connectivity | ||
| 0.18 (0.06) | | 0.18 | ||
| 2.66 (2.46) | | (0.06) | ||
| 1.41 (3.05) | | 2.66 | ||
| 0.73 (3.13) | | (2.46) | ||
| 0.15 (0.89) | | 1.41 | ||
| 0.19 (1.39) | | (3.05) | ||
| 0.23 (1.95) | | 0.73 | ||
| 0.30 (2.97) | | (3.13) | ||
| 0.21 (2.34) | | 0.15 | ||
| 0.29 (3.63) | | (0.89) | ||
| 0.19 | |||
| (1.39) | |||
| 0.23 | |||
| (1.95) | |||
| 0.30 | |||
| (2.97) | |||
| 0.21 | |||
| (2.34) | |||
| 0.29 | |||
| (3.63) | |||
|- | |- | ||
! | ! rowspan="2" MI|Time to smooth vertices | ||
| -3.06 (-0.96) | | -3.06 | ||
| 1.40 (0.94) | | (-0.96) | ||
| 5.51 (7.84) | | 1.40 | ||
| 2.65 (7.48) | | (0.94) | ||
| 1.84 (7.70) | | 5.51 | ||
| 1.32 (7.31) | | (7.84) | ||
| 1.21 (7.92) | | 2.65 | ||
| 1.05 (7.96) | | (7.48) | ||
| 1.01 (8.48) | | 1.84 | ||
| 1.77 (15.51) | | (7.70) | ||
| 1.32 | |||
| (7.31) | |||
| 1.21 | |||
| (7.92) | |||
| 1.05 | |||
| (7.96) | |||
| 1.01 | |||
| (8.48) | |||
| 1.77 | |||
| (15.51) | |||
|- | |- | ||
! | ! rowspan="2" MI|Total time to improve the mesh | ||
| -9.70 (-1.56) | | -9.70 | ||
| 0.83 (0.31) | | (-1.56) | ||
| 5.58 (4.59) | | 0.83 | ||
| 2.72 (4.37) | | (0.31) | ||
| 1.47 (3.39) | | 5.58 | ||
| 1.18 (3.44) | | (4.59) | ||
| 1.26 (4.27) | | 2.72 | ||
| 1.16 (4.52) | | (4.37) | ||
| 1.12 (4.87) | | 1.47 | ||
| 1.89 (8.81) | | (3.39) | ||
| 1.18 | |||
| (3.44) | |||
| 1.26 | |||
| (4.27) | |||
| 1.16 | |||
| (4.52) | |||
| 1.12 | |||
| (4.87) | |||
| 1.89 | |||
| (8.81) | |||
|- | |- | ||
! colspan="11" | Summary | ! colspan="11" | Summary | ||
|- | |- | ||
! | ! rowspan="2" Total mesh generation time | ||
| -8.99 (-0.88) | | -8.99 | ||
| 3.21 (0.75) | | (-0.88) | ||
| 4.10 (2.12) | | 3.21 | ||
| 2.42 (2.36) | | (0.75) | ||
| 1.70 (2.29) | | 4.10 | ||
| 1.04 (1.70) | | (2.12) | ||
| 1.44 (2.66) | | 2.42 | ||
| 1.22 (2.51) | | (2.36) | ||
| 1.39 (3.10) | | 1.70 | ||
| 2.29 (5.42) | | (2.29) | ||
| 1.04 | |||
| (1.70) | |||
| 1.44 | |||
| (2.66) | |||
| 1.22 | |||
| (2.51) | |||
| 1.39 | |||
| (3.10) | |||
| 2.29 | |||
| (5.42) | |||
|} | |} | ||
Revision as of 15:08, 30 September 2019
Objective
Replace native/system threads with Argobots tasklets. Goal offload load balancing and thread manipulation to Argobots and ultimately to PREMA
Preliminary Data
Overall
Argobots
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Argobots + avoid repartitioning in mesh refinement
The changes introduced in the code due to argobots inttegration made easier to avoid the costly re-partitioning of active elements at every iteration. In fact for the previous case we had to force merging to keep similar flow of execution.
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Argobots + naive bucket rebalancing in mesh refinement
For this method at evey iteration buckets with size > 2*max_allowed are split in half
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Notes
- Evaluated using (threads_time - argobots_time)/threads_time *100, same for counters
Updated : --Christos Tsolakis 12:27, 30 September 2019 (EDT)
Smoothing
- 5 iterations of smoothing are applied for all cases
- case is delta wing 500k target complexity from scitech paper
| cores | 40 | 20 | 10 | 5 | 1 | |
|---|---|---|---|---|---|---|
| OpenMP static | chunck 1 | 13.07 | 23.02 | 45.42 | 75.93 | 319.32 |
| chunck 10 | 17.38 | 30.62 | 58.37 | 119.682 | 530.316 | |
| OpenMP dynamic | chunck 1 | 5.18 | 9.46 | 20.7 | 46.42 | 318.22 |
| chunck 10 | 8.41 | 14.53 | 30.41 | 62.54 | 318.82 | |
| OpenMP guided | chunck 1 | 15.32 | 28.54 | 56.36 | 111.56 | 526.962 |
| chunck 10 | 10.22 | 17.22 | 33.80 | 67.62 | 318.394 | |
| Argobots | chuck 1 | 10 | 18 | 35 | 71 | 330 |
| chunk 10 | 10.15 | 17.34 | 34.37 | 69.57 | 322 |
| cores | 40 | 20 | 10 | 5 | 1 | |
|---|---|---|---|---|---|---|
| OpenMP static | chunck 1 | 0.26 | 0.12 | 0.05 | 0.03 | 0 |
| chunck 10 | 1.52 | 1.62 | 1.52 | 1.05 | 0 | |
| OpenMP dynamic | chunck 1 | 61.8 | 59.1 | 51.45 | 42.4 | 0 |
| chunck 10 | 21.31 | 22.64 | 17.54 | 12.95 | 0 | |
| OpenMP guided | chunck 1 | 0.30 | 0.14 | 0.07 | 0.03 | 0 |
| chunck 10 | 0.31 | 0.14 | 0.06 | 0.03 | 0 | |
| Argobots | chuck 1 | 1.9 | 1.6 | 1.5 | 1.2 | 0 |
| chunk 10 | 0.50 | 0.30 | 0.15 | 0.09 | 0 |
Edge Collapse
- Collapse is performed in 3 places, afterreconstruction, after surface refinement, after volume refienement
| cores | 40 | 20 | 10 | 5 | 1 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Argobots | 0.1 | 0.15 | 0.95 | 0.13 | 0.2 | 1.58 | 0.24 | 0.25 | 3.98 | 0.48 | 0.48 | 5.73 | 2.06 | 2.08 | 27.09 |
| OpenMP (guided,scheduling) | 0.07 | 0.11 | 1.13 | 0.13 | 0.15 | 2.68 | 0.25 | 0.39 | 4.06 | 0.49 | 0.5 | 6.64 | 1.96 | 2.03 | 26.26 |
Common Interface
Implemented an abstract interface for creating tasks
/**
* @brief launch tasks using the abt_wrapper and wait until they all finish
* For this version of the function the user_function must expect a pointer
* to one of the elemnts of the provided task_vector
*
* @param user_task_args vector of tasks
* @param user_func the user function to be executed, type should be void func(void*),
* where argument is ptr to an item in user_task_args
* @param nthreads number of threads to use
* @param chuck size of the "unit of work"
*/
template<typename FunctionType, typename UserTaskArgs>
inline void task_for(std::vector<UserTaskArgs>& user_task_args, FunctionType user_func,int nthreads, size_t chuck = 10)
// second version that allows for an extra field of common arguments to be shared among tasks
template<typename FunctionType, typename UserTaskArgs, typename UserCommonArgs>
inline void task_for(std::vector<UserTaskArgs>& user_task_args, FunctionType user_func, UserCommonArgs& user_common_args, int nthreads, size_t chuck = 10)
- Two level task creation
- Create 2*nthreads (level-0) tasks that statically divide the iteration space into user tasks. This allows for multithreaded task creation and better initial load balancing.
- Each level0 task will create level-1 tasks that will execute chunck times user_func
- abstracts 138 (with documentation) loc to 1.
- 11 occurences in the current code ( 2019.09.27)
TODO
- remove void typecasting
- Variadic template
Important Findings
- For operations applied on neighboring entities (vertices,tetrahedra) a bigger chunk size in OpenMP plays a very important role in the chance of rollbacks. This is because a small chunk is associated with different cores and thus increases the propability of roolback.
- In Argobots.PREMA because we launch the tasks in two stages, many chuncks are grouped together and thus this chance is lower.
--Christos Tsolakis 18:11, 12 September 2019 (EDT)
Implementation Notes
- Local reconnection and vertex creation (and other tasks directly related to them) operate on a single bucket.
- Edge collapse and vertex smoothing tasks operate of every vertex.
- Important refactoring is that even sequential operations like vertex insertion was modified to operate on buckets ( one at a time) this eases the transition, provides a common approach and prepares for the future parallelization of the operation.
- Future Work
- The speculative approach introduces rollbacks , find a way to resolve them in the middleware level
Pre-Implementation Notes
- There are Blocking and non-blocking tasks.
- Both can wait for their children
- Blocking can wait(yield) on Argobbots specific mutexes, locks etc
- There is a task create and join capability
- Thread id is can be acquired within in the task ( we need it in CDT3D in order to know in which memory pool to allocate ith no syncronization)
- Preferably we would like many tasks created in a tree-like fashion so that task initialization cost can be distributed
- In create_vertices we could use blockable tasks (spinlocks can be replaced with ABT spinlocks) also atomic locks can become atomic "read locks"
- remember to tweak stack size to the size required by predicates.
- Candidates for porting:
- (Vertex-based) smoothing (easy)
- OpenMP based
- Edge collapse (easy)
- OpenMP based
- vertex creation (modetate)
- custom bucket based load balancer
- parallel reconnection (moderate)
- custom bucket based load balancer
- (Vertex-based) smoothing (easy)
--Christos Tsolakis 19:49, 5 September 2019 (EDT)
Previous Discussions
Ideas
Try first at element granularity :
Refactor Local Reconnection loop so that a function of type
for every element t :
attempt_flip(t)
attempt_flip will be a tasklet in the Arbobots nomenclature (ie the lightest work units, that run to executing and offer no blocking)
Bonus present it in a power-aware fashion
Advantages
- Offload load balancing from CDT3D to PREMA.
- Allow take advantage from PREMA's future plans on memory locality awareness on DSM systems.
- Ability to "boost" a CDT3D instance if more than on of them are running on the same PREMA process.
- Reason: If we have more that one CDT3D instance a shared task pool will provide access to more parallelism when one of the CDT3D instances runs a section of the code sequencially or with small number of threads.
- Example: Two CDT3D instances (A &B) with 8 threads sharing a task pool. If A runs a sequential part of the code, B can use up to 17 threads to run its parallel parts. ( Caveat: Starvation may appear see solution below using groups.)
- Indirect contribution to PDR.
Details
- Bucket-level granularity since element-level would to too fine.
- Should be have constant size of buckets or constant number of buckets(current implementation):
- TODO Gather data on time per bucket (Histogram)
- TODO Use histogram distribution to create mini benchmark/test application for PREMA.
- Constant size of bucket will allow for CDT3D to come closer to PODM ie cavity level parallelism.
- Should be have constant size of buckets or constant number of buckets(current implementation):
- As a first attempt we can try to replace
push to thread pooltopush to arbobots poolthis should have no runtime overhead. (Use example code from Polykarpos). - Keep buckets alive.
- Replace Mesh Partitioning with bucket rebalancing in parallel.
- Bucket rebalancing task may launch additional tasks. there is no need of synchonization between rebalancing and mesh operation.
- Task crearion and distribution will be done recursively.
- Update global inactive tertahedra pointer carefully.(CAS, one per bucket)
- Thread-id will be replaced by stream id.
- Thread-id is used (a) to write to a memory pool that no other thread is writing. (b) To tag locked vertices
- Ultimately we would like to recast all parallel parts of CDT3D into parallel executrion modes with a unique interface, having thus only one part of the code, interfacing with Argobots. Moreover, a proper refactoring will allow thread-based implementation to co-exist as a fallback option when CDT3D is compiled without Argobots.
- Thread groups is also a interesting and usefull idea towards building this integration.
- Problem WITHOUT groups : If we have two CDT3D instances ( A & B) running on the same PREMA process, a unique task-pool will be offered by PREMA. This means that tasks (with varying size) from either instance A or B will be pushed into the task-pool. Due to the non-deterministict nature of the task-scheduling there is a possibbility that one CDT3D instance will starve because few of its tasks are waiting into the task-pool while the other one consumes all the available threads.
- Solution: Divide requested number of threads of the two CDT3D instances into two groups. Use hierachical work stealing to give priority first to local tasks and then to remote.