35#ifdef TTK_ENABLE_OPENMP
36 const ParallelGuard pg{parallelParams_.nbThreads};
48 this->
printMsg(std::vector<std::vector<std::string>>{
49 {
"#Threads", std::to_string(parallelParams_.nbThreads)},
50 {
"#Partitions", std::to_string(parallelParams_.nbPartitions)}});
52 if(
params_->simplifyThreshold) {
53 this->
printMsg(std::vector<std::vector<std::string>>{
54 {
"Simplify method", std::to_string(
params_->simplifyMethod)},
55 {
"Simplify thresh.", std::to_string(
params_->simplifyThreshold)}});
66 printDebug(timerSort,
"Sort scalars (+mirror) ");
76 for(
idInterface i = 0; i < parallelParams_.nbInterfaces; i++) {
77 std::cout <<
"interface : " <<
static_cast<unsigned>(i);
78 std::cout <<
" seed : " << parallelData_.interfaces[i].getSeed();
79 std::cout << std::endl;
82 printDebug(timerInitOverlap,
"Interface and overlap init. ");
90 std::vector<std::vector<ExtendedUnionFind *>> vect_baseUF_JT(
91 parallelParams_.nbPartitions),
93 vect_baseUF_ST(parallelParams_.nbPartitions);
95 = (
scalars_->size / parallelParams_.nbPartitions) / 10;
97 parallelData_.trees.clear();
98 parallelData_.trees.reserve(parallelParams_.nbPartitions);
100 for(
idPartition tree = 0; tree < parallelParams_.nbPartitions; ++tree) {
105#ifdef TTK_ENABLE_OPENMP
106#pragma omp parallel for num_threads(parallelParams_.nbPartitions) \
109 for(
idPartition tree = 0; tree < parallelParams_.nbPartitions; ++tree) {
111 parallelData_.trees[tree].flush();
114 vect_baseUF_JT[tree].resize(
scalars_->size);
115 vect_baseUF_ST[tree].resize(
scalars_->size);
118 parallelData_.trees[tree].jt_.treeData_.nodes.reserve(resSize);
119 parallelData_.trees[tree].jt_.treeData_.superArcs.reserve(resSize);
120 parallelData_.trees[tree].st_.treeData_.nodes.reserve(resSize);
121 parallelData_.trees[tree].st_.treeData_.superArcs.reserve(resSize);
123 printDebug(timerAllocPara,
"Parallel allocations ");
134 for(
idPartition i = 0; i < parallelParams_.nbPartitions; i++) {
135 std::cout << i <<
" :" << std::endl;
136 parallelData_.trees[i].printTree2();
137 std::cout <<
"-----" << std::endl;
140 for(
idPartition i = 0; i < parallelParams_.nbPartitions; i++) {
141 std::cout << i <<
" jt:" << std::endl;
142 parallelData_.trees[i].jt_.printTree2();
143 std::cout << i <<
" st:" << std::endl;
144 parallelData_.trees[i].st_.printTree2();
145 std::cout <<
"-----" << std::endl;
157 if(parallelParams_.partitionNum == -1
158 && parallelParams_.nbPartitions > 1) {
160 for(
idPartition p = 0; p < parallelParams_.nbPartitions; ++p) {
162 parallelData_.trees[p].parallelInitNodeValence(
163 parallelParams_.nbThreads);
179 if(parallelParams_.partitionNum >= 0) {
180 if(parallelParams_.partitionNum > parallelParams_.nbInterfaces) {
181 clone(¶llelData_.trees[parallelParams_.nbPartitions - 1]);
183 clone(¶llelData_.trees[parallelParams_.partitionNum]);
185 }
else if(parallelParams_.nbPartitions == 1) {
186 clone(¶llelData_.trees[0]);
193 if(parallelParams_.partitionNum >= 0) {
194 if(parallelParams_.partitionNum > parallelParams_.nbInterfaces) {
195 jt_.clone(¶llelData_.trees[parallelParams_.nbInterfaces].jt_);
196 st_.clone(¶llelData_.trees[parallelParams_.nbInterfaces].st_);
198 jt_.clone(¶llelData_.trees[parallelParams_.partitionNum].jt_);
199 st_.clone(¶llelData_.trees[parallelParams_.partitionNum].st_);
201 }
else if(parallelParams_.nbPartitions == 1) {
202 jt_.clone(¶llelData_.trees[0].jt_);
203 st_.clone(¶llelData_.trees[0].st_);
206 jt_.parallelInitNodeValence(parallelParams_.nbThreads);
207 st_.parallelInitNodeValence(parallelParams_.nbThreads);
211 printDebug(timerUnify,
"Contour tree created ");
218 && parallelParams_.partitionNum == -1 &&
params_->simplifyThreshold) {
223 printDebug(timerGlobalSimplify,
"Simplify Contour tree ");
224 std::cout <<
" ( " << simplified <<
" pairs merged )" << std::endl;
238 std::cout <<
"JT :" << std::endl;
240 std::cout <<
"ST :" << std::endl;
243 }
else if(
params_->debugLevel > 2) {
244 std::stringstream msg;
248 msg <<
"JT max node : " <<
jt_.getNumberOfNodes();
249 msg <<
"ST max node : " <<
st_.getNumberOfNodes();
257 jt_.updateSegmentation();
258 st_.updateSegmentation();
263 for(
idPartition tree = 0; tree < parallelParams_.nbPartitions; ++tree) {
264 parallelData_.trees[tree].jt_.treeData_.nodes.shrink_to_fit();
265 parallelData_.trees[tree].jt_.treeData_.superArcs.shrink_to_fit();
266 parallelData_.trees[tree].st_.treeData_.nodes.shrink_to_fit();
267 parallelData_.trees[tree].st_.treeData_.superArcs.shrink_to_fit();
279 std::vector<std::vector<ExtendedUnionFind *>> &vect_baseUF_JT,
280 std::vector<std::vector<ExtendedUnionFind *>> &vect_baseUF_ST,
281 const triangulationType &mesh) {
283 const std::vector<float> timeSimplify(parallelParams_.nbPartitions, 0);
284 std::vector<float> speedProcess(parallelParams_.nbPartitions * 2, 0);
285#ifdef TTK_ENABLE_CONTOUR_FORESTS_PARALLEL_SIMPLIFY
289#ifdef TTK_ENABLE_OPENMP
290 omp_set_max_active_levels(100);
294#ifdef TTK_ENABLE_OPENMP
295#pragma omp parallel for num_threads(parallelParams_.nbPartitions) \
298 for(
idPartition i = 0; i < parallelParams_.nbPartitions; ++i) {
305 if(parallelParams_.partitionNum != -1
306 && parallelParams_.partitionNum != i)
313 std::tuple<SimplexId, SimplexId> rangeJT =
getJTRange(i);
314 std::tuple<SimplexId, SimplexId> rangeST =
getSTRange(i);
315 std::tuple<SimplexId, SimplexId> seedsPos =
getSeedsPos(i);
316 std::tuple<std::vector<SimplexId>, std::vector<SimplexId>> overlaps
319 = std::abs(std::get<0>(rangeJT) - std::get<1>(rangeJT))
320 + std::get<0>(overlaps).size() + std::get<1>(overlaps).size();
326#ifdef TTK_ENABLE_OPENMP
327#pragma omp parallel sections num_threads(2) if(parallelParams_.lessPartition)
332#ifdef TTK_ENABLE_OPENMP
341 parallelData_.trees[i].getJoinTree()->build(
342 vect_baseUF_JT[i], std::get<0>(overlaps), std::get<1>(overlaps),
343 std::get<0>(rangeJT), std::get<1>(rangeJT),
344 std::get<0>(seedsPos), std::get<1>(seedsPos), mesh);
347#ifdef TTK_ENABLE_CONTOUR_FORESTS_PARALLEL_SIMPLIFY
352 parallelData_.trees[i].getJoinTree()->localSimplify<scalarType>(
353 std::get<0>(seedsPos), std::get<1>(seedsPos));
354#ifdef TTK_ENABLE_OPENMP
355#pragma omp atomic update
358#ifdef TTK_ENABLE_OPENMP
359#pragma omp atomic update
361 nbPairMerged += tmpMerge;
366#ifdef TTK_ENABLE_OPENMP
375 parallelData_.trees[i].getSplitTree()->build(
376 vect_baseUF_ST[i], std::get<1>(overlaps), std::get<0>(overlaps),
377 std::get<0>(rangeST), std::get<1>(rangeST),
378 std::get<0>(seedsPos), std::get<1>(seedsPos), mesh);
379 speedProcess[parallelParams_.nbPartitions + i]
382#ifdef TTK_ENABLE_CONTOUR_FORESTS_PARALLEL_SIMPLIFY
387 parallelData_.trees[i]
389 ->localSimplify<scalarType>(
390 std::get<0>(seedsPos), std::get<1>(seedsPos));
391#ifdef TTK_ENABLE_OPENMP
392#pragma omp atomic update
395#ifdef TTK_ENABLE_OPENMP
396#pragma omp atomic update
398 nbPairMerged += tmpMerge;
404 this->
printMsg(
"Constructed Merge Tree " + std::to_string(i), 1.0,
411 parallelData_.trees[i].getJoinTree()->updateSegmentation();
412 parallelData_.trees[i].getSplitTree()->updateSegmentation();
415 this->
printMsg(
"Local MT updated", 1.0,
417 this->threadNumber_);
429 auto *jt = parallelData_.trees[i].getJoinTree();
430 auto *st = parallelData_.trees[i].getSplitTree();
434 for(
idNode t = 0; t < st->getNumberOfNodes(); ++t) {
435 if(!st->getNode(t)->isHidden()) {
438 jt->insertNode(st->getNode(t),
true);
442 for(
idNode t = 0; t < jt->getNumberOfNodes(); ++t) {
443 if(!jt->getNode(t)->isHidden()) {
446 st->insertNode(jt->getNode(t),
true);
452 std::cout <<
"Local JT :" << std::endl;
453 parallelData_.trees[i].getJoinTree()->printTree2();
454 std::cout <<
"Local ST :" << std::endl;
455 parallelData_.trees[i].getSplitTree()->printTree2();
456 std::cout <<
"combine" << std::endl;
460 parallelData_.trees[i].combine(
461 std::get<0>(seedsPos), std::get<1>(seedsPos), this->storage_);
462 parallelData_.trees[i].updateSegmentation();
465 printDebug(timerCombine,
"Trees combined in ");
470 parallelData_.trees[i].printTree2();
474 std::cout <<
"Local JT :" << std::endl;
475 parallelData_.trees[i].getJoinTree()->printTree2();
476 std::cout <<
"Local ST :" << std::endl;
477 parallelData_.trees[i].getSplitTree()->printTree2();
478 std::cout <<
"combine" << std::endl;
488#ifdef TTK_ENABLE_CONTOUR_FORESTS_PARALLEL_SIMPLIFY
489 if(
params_->simplifyThreshold) {
491 = max_element(timeSimplify.cbegin(), timeSimplify.cend());
492 float maxSimplif = *maxSimplifIt;
493 std::cout <<
"Local simplification maximum time :" << maxSimplif;
494 std::cout <<
" ( " << nbPairMerged <<
" pairs merged )" << std::endl;
498 = max_element(speedProcess.cbegin(), speedProcess.cend());
500 = min_element(speedProcess.cbegin(), speedProcess.cend());
501 std::stringstream msg;
502 msg <<
"process speed : ";
503 msg <<
" min is " << *minProcSpeed <<
" vert/sec";
504 msg <<
" max is " << *maxProcSpeed <<
" vert/sec";
513 const SimplexId nbEdges = mesh->getNumberOfEdges();
523 std::vector<std::vector<std::vector<SimplexId>>> lowers(
524 parallelParams_.nbThreads);
525 std::vector<std::vector<std::vector<SimplexId>>> uppers(
526 parallelParams_.nbThreads);
528 for(
numThread p = 0; p < parallelParams_.nbThreads; p++) {
529 lowers[p].resize(parallelParams_.nbInterfaces);
530 uppers[p].resize(parallelParams_.nbInterfaces);
533#ifdef TTK_ENABLE_OPENMP
534#pragma omp parallel for num_threads(parallelParams_.nbThreads) schedule(static)
538#ifdef TTK_ENABLE_OPENMP
544 std::vector<std::vector<SimplexId>> &localUppers = uppers[part];
545 std::vector<std::vector<SimplexId>> &localLowers = lowers[part];
548 mesh->getEdgeVertex(e, 0, v0);
549 mesh->getEdgeVertex(e, 1, v1);
551 for(
idInterface i = 0; i < parallelParams_.nbInterfaces; i++) {
553 =
isHigher(v0, parallelData_.interfaces[i].getSeed());
555 =
isHigher(v1, parallelData_.interfaces[i].getSeed());
563 localUppers[i].emplace_back(v0);
565 localLowers[i].emplace_back(v1);
568 localUppers[i].emplace_back(v1);
570 localLowers[i].emplace_back(v0);
583 std::vector<SimplexId> sizeReserveUp(parallelParams_.nbInterfaces, 0);
584 std::vector<SimplexId> sizeReserveLo(parallelParams_.nbInterfaces, 0);
585 for(
numThread p = 0; p < parallelParams_.nbThreads; p++) {
586 for(
idInterface i = 0; i < parallelParams_.nbInterfaces; i++) {
587 sizeReserveUp[i] += uppers[p][i].size();
588 sizeReserveLo[i] += lowers[p][i].size();
592 for(
idInterface i = 0; i < parallelParams_.nbInterfaces; i++) {
593 parallelData_.interfaces[i].upReserve(sizeReserveUp[i]);
594 parallelData_.interfaces[i].loReserve(sizeReserveLo[i]);
598 for(
numThread p = 0; p < parallelParams_.nbThreads; p++) {
599 for(
idInterface i = 0; i < parallelParams_.nbInterfaces; i++) {
600 parallelData_.interfaces[i].appendUpper(uppers[p][i]);
601 parallelData_.interfaces[i].appendLower(lowers[p][i]);
614#ifdef TTK_ENABLE_OPENMP
615#pragma omp parallel for num_threads(parallelParams_.nbThreads) schedule(static)
617 for(
idInterface i = 0; i < parallelParams_.nbInterfaces; i++) {
618 std::vector<SimplexId> &upOverlap
619 = parallelData_.interfaces[i].getUpper();
620 std::vector<SimplexId> &loOverlap
621 = parallelData_.interfaces[i].getLower();
640 sort(upOverlap.begin(), upOverlap.end(), vertComp);
641 auto upLast = unique(upOverlap.begin(), upOverlap.end());
642 upOverlap.erase(upLast, upOverlap.end());
644 sort(loOverlap.begin(), loOverlap.end(), vertComp);
645 auto loLast = unique(loOverlap.begin(), loOverlap.end());
646 loOverlap.erase(loLast, loOverlap.end());