From a9f8e63dec62d350edef7a6ca0c950cf1352e030 Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Fri, 9 Sep 2022 09:52:50 +0200 Subject: [PATCH] Deactivating parallelism for 2D/1D + corrections for non parallel run + adding ParallelCompute function in Python --- src/SMESH/SMESH_Gen.cxx | 36 ++++++++++++++++++++++-- src/SMESH/SMESH_Mesh.hxx | 1 + src/SMESH/SMESH_subMesh.cxx | 5 ++-- src/SMESH_SWIG/smeshBuilder.py | 24 ++++++++++++++-- src/StdMeshers/StdMeshers_Regular_1D.cxx | 24 ++++++++-------- 5 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index c48e8d841..eb292e928 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -48,6 +48,7 @@ #include #include "memoire.h" +#include #ifdef WIN32 #include @@ -247,6 +248,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, TopAbs_ShapeEnum previousShapeType = TopAbs_VERTEX; std::vector> pending; + int nbThreads = aMesh.GetNbThreads(); + auto begin = std::chrono::high_resolution_clock::now(); + smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst); while ( smIt->more() ) @@ -258,13 +262,17 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, const TopAbs_ShapeEnum shapeType = shape.ShapeType(); if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX ) continue; - + if(shapeType==TopAbs_FACE||shapeType==TopAbs_EDGE) + aMesh.SetNbThreads(0); + else + aMesh.SetNbThreads(nbThreads); //DEBUG std::cout << "Shape Type" << shapeType << " previous" << previousShapeType << std::endl; - if (aMesh.IsParallel() && shapeType != previousShapeType) { + if ((aMesh.IsParallel()||nbThreads!=0) && shapeType != previousShapeType) { // Waiting for all threads for the previous type to end for(auto &it: pending){ it.wait(); } + std::string file_name; switch(previousShapeType){ case TopAbs_FACE: @@ -276,6 +284,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, case TopAbs_VERTEX: file_name = "Mesh0D.med"; break; + case TopAbs_SOLID: default: file_name = ""; break; @@ -306,10 +315,14 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, shapeSM, aShapeOnly, allowedSubShapes, aShapesId)); } else { + auto begin2 = std::chrono::high_resolution_clock::now(); + compute_function(1 ,smToCompute, computeEvent, shapeSM, aShapeOnly, allowedSubShapes, aShapesId); + + if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE && ( shapeType != TopAbs_EDGE || !SMESH_Algo::isDegenerated( TopoDS::Edge( shape )))) ret = false; @@ -328,6 +341,14 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, } aMesh.GetMeshDS()->Modified(); + auto end = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(end - begin); + std::cout << "Time for All: " << elapsed.count()*1e-9 << std::endl; + + // Pool of thread for computation + if(aMesh.IsParallel()) + aMesh.DeletePoolThreads(); + return ret; } else @@ -338,7 +359,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, // the most complex shapes and collect sub-meshes with algos that // DO support sub-meshes // ================================================================ - + auto begin = std::chrono::high_resolution_clock::now(); list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes[4]; // for each dim // map to sort sm with same dim algos according to dim of @@ -534,7 +555,12 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, continue; sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes )); setCurrentSubMesh( sm ); + auto begin = std::chrono::high_resolution_clock::now(); sm->ComputeStateEngine( computeEvent ); + auto end = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(end - begin); + std::cout << "Time for seq:alldim:compute: " << elapsed.count()*1e-9 << std::endl; + setCurrentSubMesh( NULL ); sm->SetAllowedSubShapes( nullptr ); if ( aShapesId ) @@ -547,6 +573,10 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, // mesh the rest sub-shapes starting from vertices // ----------------------------------------------- ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId, allowedSubShapes ); + auto end = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(end - begin); + std::cout << "Time for All: " << elapsed.count()*1e-9 << std::endl; + } MEMOSTAT; diff --git a/src/SMESH/SMESH_Mesh.hxx b/src/SMESH/SMESH_Mesh.hxx index b3823828d..f6847260b 100644 --- a/src/SMESH/SMESH_Mesh.hxx +++ b/src/SMESH/SMESH_Mesh.hxx @@ -394,6 +394,7 @@ class SMESH_EXPORT SMESH_Mesh void SetNbThreads(int nbThreads){_NbThreads=nbThreads;}; void InitPoolThreads(){_pool = new ctpl::thread_pool(_NbThreads);}; + void DeletePoolThreads(){delete _pool;}; bool IsParallel(){return _NbThreads > 0;} diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 3790ffdde..476cf4d61 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -65,7 +65,7 @@ using namespace std; //#define PRINT_WHO_COMPUTE_WHAT #endif -#define PRINT_WHO_COMPUTE_WHAT +//#define PRINT_WHO_COMPUTE_WHAT //============================================================================= /*! * \brief Allocate some memory at construction and release it at destruction. @@ -1519,7 +1519,8 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event) break; } TopoDS_Shape shape = _subShape; - algo->SubMeshesToCompute().assign( 1, this ); + if(!_father->IsParallel()) + algo->SubMeshesToCompute().assign( 1, this ); // check submeshes needed // In parallel there would be no submesh to check if (_father->HasShapeToMesh() && !_father->IsParallel()) { diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 21a6c5af6..ef57b606c 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -1842,8 +1842,28 @@ class Mesh(metaclass = MeshMeta): geom = self.geom return self.smeshpyD.Evaluate(self.mesh, geom) + def ParallelCompute(self, nbThreads, geom=0, discardModifs=False, refresh=False): + """ + Parallel computation of the mesh and return the status of the computation + The mesh must contains have be constructed using create_parallel_mesh - def Compute(self, geom=0, discardModifs=False, refresh=False, nbThreads=0): + Parameters: + nbThreads: Number of threads to use for a parallel computation + geom: geomtrical shape on which mesh data should be computed + discardModifs: if True and the mesh has been edited since + a last total re-compute and that may prevent successful partial re-compute, + then the mesh is cleaned before Compute() + refresh: if *True*, Object Browser is automatically updated (when running in GUI) + + Returns: + True or False + """ + if (nbThreads <= 1): + raise ValueError("nbThreads must be greater than 1") + self.mesh.SetNbThreads(nbThreads) + return self.Compute(geom=geom, discardModifs=discardModifs, refresh=refresh) + + def Compute(self, geom=0, discardModifs=False, refresh=False): """ Compute the mesh and return the status of the computation @@ -1865,8 +1885,6 @@ class Mesh(metaclass = MeshMeta): try: if discardModifs and self.mesh.HasModificationsToDiscard(): # issue 0020693 self.mesh.Clear() - # Setting parallel parameters - self.mesh.SetNbThreads(nbThreads) ok = self.smeshpyD.Compute(self.mesh, geom) except SALOME.SALOME_Exception as ex: print("Mesh computation failed, exception caught:") diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index 5dd486982..bf0d6ed91 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -133,15 +133,15 @@ bool StdMeshers_Regular_1D::CheckHypothesis( SMESH_Mesh& aMesh, // find non-auxiliary hypothesis const SMESHDS_Hypothesis *theHyp = 0; set< string > propagTypes; - std::cout << "For shape " << aShape.HashCode(1) << " of type "<< aShape.ShapeType() << - "CheckHypothesis" << std::endl; - for(auto hyp:hyps){ - SMESH_Comment hypStr; - hypStr << hyp << " " << hyp->GetName() << " "; - ((SMESHDS_Hypothesis*)hyp)->SaveTo( hypStr.Stream() ); - hypStr << " "; - std::cout << hypStr << std::endl; - } + //std::cout << "For shape " << aShape.HashCode(1) << " of type "<< aShape.ShapeType() << + // "CheckHypothesis" << std::endl; + // for(auto hyp:hyps){ + // SMESH_Comment hypStr; + // hypStr << hyp << " " << hyp->GetName() << " "; + // ((SMESHDS_Hypothesis*)hyp)->SaveTo( hypStr.Stream() ); + // hypStr << " "; + // std::cout << hypStr << std::endl; + // } list ::const_iterator h = hyps.begin(); for ( ; h != hyps.end(); ++h ) { if ( static_cast(*h)->IsAuxiliary() ) { @@ -1218,7 +1218,7 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t const SMDS_MeshNode * nLast = SMESH_Algo::VertexNode( VLast, meshDS ); if ( !nFirst || !nLast ){ theMesh.Unlock(); - std::cout << "exit no node" << std::endl; + //std::cout << "exit no node" << std::endl; return error( COMPERR_BAD_INPUT_MESH, "No node on vertex"); } // remove elements created by e.g. pattern mapping (PAL21999) @@ -1265,7 +1265,7 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t BRepAdaptor_Curve C3d( E ); if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, reversed, true )) { theMesh.Unlock(); - std::cout << "exit Compute internal failed" << std::endl; + //std::cout << "exit Compute internal failed" << std::endl; return false; } @@ -1358,7 +1358,7 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t } } theMesh.Unlock(); - std::cout << "exit normal" << std::endl; + //std::cout << "exit normal" << std::endl; return true; }