From d18c6cc5f1ad80eb29b72811fb85a909a584c748 Mon Sep 17 00:00:00 2001 From: ika Date: Fri, 8 Mar 2024 15:12:34 +0000 Subject: [PATCH] 0033634: Data Exchange, Step Import - Multithreading Step processing - add parallel execution on the level of STEPControl_ActorRead. Sendingsimple shapes for healing in parallel; - add parameter to turn ON/OFF this behavior read.step.parallel.healing, ON by default; - add jemalloc allocator; - add CMake option to chose the allocator, jemalloc by default. --- CMakeLists.txt | 12 + adm/cmake/jemalloc.cmake | 143 +++++++++ adm/cmake/occt_defs_flags.cmake | 3 + adm/templates/custom.build.bat.in | 3 +- adm/templates/custom.build.sh.in | 3 +- adm/templates/custom.install.bat.in | 1 + adm/templates/custom.install.sh.in | 1 + adm/templates/env.bat.in | 21 +- adm/templates/env.build.sh.in | 6 +- adm/templates/env.install.sh.in | 6 +- src/STEPControl/STEPControl_ActorRead.cxx | 93 +++++- src/STEPControl/STEPControl_ActorRead.hxx | 12 +- src/STEPControl/STEPControl_Controller.cxx | 6 + src/Standard/Standard.cxx | 345 +++++++-------------- src/TKernel/CMakeLists.txt | 9 + src/TKernel/EXTERNLIB | 1 + 16 files changed, 406 insertions(+), 259 deletions(-) create mode 100644 adm/cmake/jemalloc.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 100d61339d..4637c02b4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,10 @@ macro (OCCT_INCLUDE_CMAKE_FILE BEING_INCLUDED_FILE) endif() endmacro() +# set using memory manager option for TKernel +set (USE_MMGR_TYPE "JEMALLOC" CACHE STRING "Select using memory manager tool.") +set_property(CACHE USE_MMGR_TYPE PROPERTY STRINGS "NATIVE" "TBB" "JEMALLOC") + # include variable description OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/vardescr") @@ -728,6 +732,14 @@ else() OCCT_CHECK_AND_UNSET ("3RDPARTY_FLEX_EXECUTABLE") endif() +# Jemalloc +if ("${USE_MMGR_TYPE}" STREQUAL "JEMALLOC") + OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/jemalloc") +else() + OCCT_CHECK_AND_UNSET_GROUP ("3RDPARTY_JEMALLOC") + OCCT_CHECK_AND_UNSET ("INSTALL_JEMALLOC") +endif() + # qt for inspector and samples if (BUILD_Inspector OR BUILD_SAMPLES_QT) # check qt 3rdparty path diff --git a/adm/cmake/jemalloc.cmake b/adm/cmake/jemalloc.cmake new file mode 100644 index 0000000000..892aed75f8 --- /dev/null +++ b/adm/cmake/jemalloc.cmake @@ -0,0 +1,143 @@ +# JeMalloc + +if (NOT DEFINED INSTALL_JEMALLOC) + set (INSTALL_JEMALLOC OFF CACHE BOOL "${INSTALL_INSTALL_JEMALLOC_DESCR}") +endif() + +# include occt macros. compiler_bitness, os_with_bit, compiler +OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_macros") + +# specify JEMALLOC folder in connection with 3RDPARTY_DIR +if (3RDPARTY_DIR AND EXISTS "${3RDPARTY_DIR}") + if (NOT 3RDPARTY_JEMALLOC_DIR OR NOT EXISTS "${3RDPARTY_JEMALLOC_DIR}") + FIND_PRODUCT_DIR ("${3RDPARTY_DIR}" jemalloc JEMALLOC_DIR_NAME) + if (JEMALLOC_DIR_NAME) + set (3RDPARTY_JEMALLOC_DIR "${3RDPARTY_DIR}/${JEMALLOC_DIR_NAME}" CACHE PATH "The directory containing JEMALLOC" FORCE) + set (3RDPARTY_JEMALLOC_DIR "${3RDPARTY_DIR}/${JEMALLOC_DIR_NAME}") + message(STATUS "Info: JEMALLOC detected in ${3RDPARTY_JEMALLOC_DIR}") + endif() + endif() + else() +endif() + +# define required JEMALLOC variables +if (NOT DEFINED 3RDPARTY_JEMALLOC_INCLUDE_DIR) + set (3RDPARTY_JEMALLOC_INCLUDE_DIR "" CACHE PATH "the path of headers directory") +endif() + +# check 3RDPARTY_${PRODUCT_NAME}_ paths for consistency with specified 3RDPARTY_${PRODUCT_NAME}_DIR +if (3RDPARTY_JEMALLOC_DIR AND EXISTS "${3RDPARTY_JEMALLOC_DIR}") + CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_JEMALLOC_DIR 3RDPARTY_JEMALLOC_INCLUDE_DIR PATH "the path to JEMALLOC") + CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_JEMALLOC_DIR 3RDPARTY_JEMALLOC_LIBRARY_DIR FILEPATH "The directory containing JEMALLOC libraries") +endif() + +# header +if (NOT 3RDPARTY_JEMALLOC_INCLUDE_DIR OR NOT EXISTS "${3RDPARTY_JEMALLOC_INCLUDE_DIR}") + set (HEADER_NAMES jemalloc.h) + + # set 3RDPARTY_JEMALLOC_INCLUDE_DIR as notfound, otherwise find_library can't assign a new value to 3RDPARTY_JEMALLOC_INCLUDE_DIR + set (3RDPARTY_JEMALLOC_INCLUDE_DIR "3RDPARTY_JEMALLOC_INCLUDE_DIR-NOTFOUND" CACHE FILEPATH "the path to header directory" FORCE) + + if (3RDPARTY_JEMALLOC_DIR AND EXISTS "${3RDPARTY_JEMALLOC_DIR}") + find_path (3RDPARTY_JEMALLOC_INCLUDE_DIR NAMES ${HEADER_NAMES} + PATHS ${3RDPARTY_JEMALLOC_DIR} + PATH_SUFFIXES include/jemalloc + CMAKE_FIND_ROOT_PATH_BOTH + NO_DEFAULT_PATH) + endif() +endif() + +if (3RDPARTY_JEMALLOC_INCLUDE_DIR AND EXISTS "${3RDPARTY_JEMALLOC_INCLUDE_DIR}") + list (APPEND 3RDPARTY_INCLUDE_DIRS "${3RDPARTY_JEMALLOC_INCLUDE_DIR}") +else() + list (APPEND 3RDPARTY_NOT_INCLUDED 3RDPARTY_JEMALLOC_INCLUDE_DIR) + set (3RDPARTY_JEMALLOC_INCLUDE_DIR "" CACHE FILEPATH "the path to jemalloc.h" FORCE) +endif() + +# Installing destination path +if (WIN32) + set (JEMALLOC_INSTALL_DESTINATION "${INSTALL_DIR}/${INSTALL_DIR_BIN}") +else() + set (JEMALLOC_INSTALL_DESTINATION "${INSTALL_DIR}/${INSTALL_DIR_LIB}") +endif() + +macro (JEMALLOC_LIB_SEARCH MMGR_LIB PREFIX) +if (NOT 3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}) + set (JEMALLOC_PATH_SUFFIXES "lib" "bin") + set (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} "3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}-NOTFOUND") + if (3RDPARTY_JEMALLOC_DIR AND EXISTS "${3RDPARTY_JEMALLOC_DIR}") + find_library (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} NAMES ${MMGR_LIB} + PATHS "${3RDPARTY_JEMALLOC_LIBRARY_DIR}" "${3RDPARTY_JEMALLOC_DIR}" + PATH_SUFFIXES ${JEMALLOC_PATH_SUFFIXES} + CMAKE_FIND_ROOT_PATH_BOTH + NO_DEFAULT_PATH) + else() + find_library (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} NAMES ${MMGR_LIB} + PATH_SUFFIXES ${JEMALLOC_PATH_SUFFIXES} + CMAKE_FIND_ROOT_PATH_BOTH) + endif() + if (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}) + get_filename_component (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} "${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}}" PATH) + set (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} "${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}") + else() + set (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} "") + endif() +endif() +if (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}) + list (APPEND 3RDPARTY_LIBRARY_DIRS "${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}") + set (3RDPARTY_JEMALLOC_LIBRARY_DIR "${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}" CACHE PATH "The directory containing JEMALLOC libraries" FORCE) +else() + message("Cannot find ${MMGR_LIB} library in jemalloc 3rdparty") + list (APPEND 3RDPARTY_NO_LIBS 3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}) + set (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} "") +endif() +set (JEMALLOC_IS_STATIC_LIB FALSE) +if (((${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}} MATCHES "lib$")) OR ((${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}} MATCHES "a$"))) + get_filename_component(STATIC_LIB_NAME ${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}} NAME) + list(APPEND CSF_MMGR "${STATIC_LIB_NAME}") + set (JEMALLOC_IS_STATIC_LIB TRUE) +endif() +# install instructions +if (INSTALL_JEMALLOC AND NOT JEMALLOC_IS_STATIC_LIB) + OCCT_MAKE_OS_WITH_BITNESS() + OCCT_MAKE_COMPILER_SHORT_NAME() + get_filename_component(3RDPARTY_JEMALLOC_LIBRARY ${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}} REALPATH) + if (SINGLE_GENERATOR) + install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}" + DESTINATION "${INSTALL_DIR}/${INSTALL_DIR_LIB}") + else() + install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}" + CONFIGURATIONS Debug + DESTINATION "${JEMALLOC_INSTALL_DESTINATION}d") + install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}" + CONFIGURATIONS Release + DESTINATION "${JEMALLOC_INSTALL_DESTINATION}") + install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}" + CONFIGURATIONS RelWithDebInfo + DESTINATION "${JEMALLOC_INSTALL_DESTINATION}i") + endif() + set (USED_3RDPARTY_JEMALLOC_DIR "") +elseif(NOT JEMALLOC_IS_STATIC_LIB) + # the library directory for using by the executable + set (USED_3RDPARTY_JEMALLOC_DIR ${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}) +endif() +unset(3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} CACHE) +unset(3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} CACHE) +endmacro() + +# Reset CSF variable +set (CSF_MMGR "") + +# find static jemalloc lib +SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a") +if (WIN32) + JEMALLOC_LIB_SEARCH ("jemalloc" "STATIC") +elseif(NOT WIN32) + JEMALLOC_LIB_SEARCH ("jemalloc_pic" "STATIC") + SET(CMAKE_FIND_LIBRARY_SUFFIXES "" "so") + JEMALLOC_LIB_SEARCH ("jemalloc.so.2" "SHARED") +endif() + +# find shared jemalloc lib +SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll" ".so") +JEMALLOC_LIB_SEARCH ("jemalloc" "SHARED") diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake index 1b6613515e..98e8504672 100644 --- a/adm/cmake/occt_defs_flags.cmake +++ b/adm/cmake/occt_defs_flags.cmake @@ -11,9 +11,12 @@ set(FLAGS_ALREADY_INCLUDED 1) # project can be switched later to use Intel Compiler (ICC). # Enforcing -fp:precise ensures that in such case ICC will use correct # option instead of its default -fp:fast which is harmful for OCCT. +# Enforcing OMP only for internal test env if (MSVC) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:precise") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fp:precise") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp") endif() # add SSE2 option for old MSVC compilers (VS 2005 - 2010, 32 bit only) diff --git a/adm/templates/custom.build.bat.in b/adm/templates/custom.build.bat.in index c03a7fc0d4..b968dc854a 100644 --- a/adm/templates/custom.build.bat.in +++ b/adm/templates/custom.build.bat.in @@ -14,6 +14,7 @@ if /I "%VCVER%" == "@COMPILER@" ( set "TBB_DIR=@3RDPARTY_TBB_DLL_DIR@" set "VTK_DIR=@3RDPARTY_VTK_DLL_DIR@" set "FFMPEG_DIR=@3RDPARTY_FFMPEG_DLL_DIR@" + set "JEMALLOC_DIR=@3RDPARTY_JEMALLOC_LIBRARY_DIR@" set "OPENVR_DIR=@3RDPARTY_OPENVR_DLL_DIRS@" if not "@3RDPARTY_QT_DIR@" == "" ( @@ -40,7 +41,7 @@ if /I "%VCVER%" == "@COMPILER@" ( set "CSF_OCCTTestsPath=@CMAKE_SOURCE_DIR@/tests" set "CSF_OCCTDocPath=@CMAKE_SOURCE_DIR@/doc" - rem for compatability with external application using CASROOT + rem for compatibility with external application using CASROOT set "CASROOT=@CMAKE_SOURCE_DIR@" ) ) diff --git a/adm/templates/custom.build.sh.in b/adm/templates/custom.build.sh.in index 002a854951..bcf340164e 100644 --- a/adm/templates/custom.build.sh.in +++ b/adm/templates/custom.build.sh.in @@ -12,6 +12,7 @@ if [ "$1" == "@BIN_LETTER@" ]; then export TBB_DIR="@3RDPARTY_TBB_LIBRARY_DIR@" export VTK_DIR="@3RDPARTY_VTK_LIBRARY_DIR@" export FFMPEG_DIR="@3RDPARTY_FFMPEG_LIBRARY_DIR@" + export JEMALLOC_DIR="@3RDPARTY_JEMALLOC_LIBRARY_DIR@" if [ "x@3RDPARTY_QT_DIR" != "x" ]; then export QTDIR="@3RDPARTY_QT_DIR@" @@ -29,7 +30,7 @@ if [ "$1" == "@BIN_LETTER@" ]; then export CSF_OCCTTestsPath="@CMAKE_SOURCE_DIR@/tests" export CSF_OCCTDocPath="@CMAKE_SOURCE_DIR@/doc" - # for compatability with external application using CASROOT + # for compatibility with external application using CASROOT export CASROOT="@CMAKE_SOURCE_DIR@" fi fi diff --git a/adm/templates/custom.install.bat.in b/adm/templates/custom.install.bat.in index 041152bdda..2f2af3a5ac 100644 --- a/adm/templates/custom.install.bat.in +++ b/adm/templates/custom.install.bat.in @@ -16,6 +16,7 @@ if /I "%VCVER%" == "@COMPILER@" ( set "TBB_DIR=@USED_3RDPARTY_TBB_DIR@" set "VTK_DIR=@USED_3RDPARTY_VTK_DIR@" set "FFMPEG_DIR=@USED_3RDPARTY_FFMPEG_DIR@" + set "JEMALLOC_DIR=@USED_3RDPARTY_JEMALLOC_DIR@" set "OPENVR_DIR=@USED_3RDPARTY_OPENVR_DIR@" if not "@USED_3RDPARTY_QT_DIR@" == "" ( diff --git a/adm/templates/custom.install.sh.in b/adm/templates/custom.install.sh.in index 79a4fa3a70..dc6552b342 100644 --- a/adm/templates/custom.install.sh.in +++ b/adm/templates/custom.install.sh.in @@ -12,6 +12,7 @@ if [ "$1" == "@BIN_LETTER@" ]; then export TBB_DIR="@USED_3RDPARTY_TBB_DIR@" export VTK_DIR="@USED_3RDPARTY_VTK_DIR@" export FFMPEG_DIR="@USED_3RDPARTY_FFMPEG_DIR@" + export JEMALLOC_DIR="@USED_3RDPARTY_JEMALLOC_DIR@" if [ "x@USED_3RDPARTY_QT_DIR@" != "x" ]; then export QTDIR="@USED_3RDPARTY_QT_DIR@" diff --git a/adm/templates/env.bat.in b/adm/templates/env.bat.in index ab85ae16f8..24df954e68 100644 --- a/adm/templates/env.bat.in +++ b/adm/templates/env.bat.in @@ -74,6 +74,10 @@ if not "%DevEnvDir%" == "" ( for /f "usebackq delims=" %%i in (`vswhere.exe -version "[16.0,16.99]" -latest -requires Microsoft.VisualStudio.Workload.%VCPROP% -property installationPath`) do ( set "DevEnvDir=%%i\Common7\IDE\" ) +) else if /I "%VCFMT%" == "vc143" ( + for /f "usebackq delims=" %%i in (`vswhere.exe -version "[17.0,17.99]" -latest -requires Microsoft.VisualStudio.Workload.%VCPROP% -property installationPath`) do ( + set "DevEnvDir=%%i\Common7\IDE\" + ) ) else if /I "%VCFMT%" == "gcc" ( rem MinGW ) else ( @@ -107,6 +111,11 @@ if /I "%VCFMT%" == "vc9" ( set "VCVARS=%%i\VC\Auxiliary\Build\vcvarsall.bat" ) set "VCPlatformToolSet=v142" +) else if /I "%VCFMT%" == "vc143" ( + for /f "usebackq delims=" %%i in (`vswhere.exe -version "[17.0,17.99]" -latest -requires Microsoft.VisualStudio.Workload.%VCPROP% -property installationPath`) do ( + set "VCVARS=%%i\VC\Auxiliary\Build\vcvarsall.bat" + ) + set "VCPlatformToolSet=v142" ) else if /I "%VCFMT%" == "gcc" ( rem MinGW ) else ( @@ -115,7 +124,7 @@ if /I "%VCFMT%" == "vc9" ( exit ) -rem ----- For compatability with external application using CASROOT ----- +rem ----- For compatibility with external application using CASROOT ----- if ["%CASROOT%"] == [""] set "CASROOT=%SCRIPTROOT%" rem ----- Define path to 3rdparty products ----- @@ -126,11 +135,16 @@ if ["%ARCH%"] == ["64"] set VCARCH=amd64 if /I ["%1"] == ["vc141"] set "VCVER=vc14" if /I ["%1"] == ["vc142"] set "VCVER=vc14" +if /I ["%1"] == ["vc143"] set "VCVER=vc14" if exist "%CASROOT%\custom.bat" ( call "%CASROOT%\custom.bat" %VCVER% %ARCH% %CASDEB% ) +if not ["%QTDIR%"] == [""] ( + set "PATH=%QTDIR%/bin;%PATH%" + set "QT_PLUGIN_PATH=%QTDIR%/plugins" +) if not ["%TCL_DIR%"] == [""] set "PATH=%TCL_DIR%;%PATH%" if not ["%TK_DIR%"] == [""] set "PATH=%TK_DIR%;%PATH%" if not ["%FREETYPE_DIR%"] == [""] set "PATH=%FREETYPE_DIR%;%PATH%" @@ -140,11 +154,8 @@ if not ["%GLES2_DIR%"] == [""] set "PATH=%GLES2_DIR%;%PATH%" if not ["%TBB_DIR%"] == [""] set "PATH=%TBB_DIR%;%PATH%" if not ["%VTK_DIR%"] == [""] set "PATH=%VTK_DIR%;%PATH%" if not ["%FFMPEG_DIR%"] == [""] set "PATH=%FFMPEG_DIR%;%PATH%" +if not ["%JEMALLOC_DIR%"] == [""] set "PATH=%JEMALLOC_DIR%;%PATH%" if not ["%OPENVR_DIR%"] == [""] set "PATH=%OPENVR_DIR%;%PATH%" -if not ["%QTDIR%"] == [""] ( - set "PATH=%QTDIR%/bin;%PATH%" - set "QT_PLUGIN_PATH=%QTDIR%/plugins" -) rem ----- Set path to 3rd party and OCCT libraries ----- if not "%CSF_OCCTBinPath%" == "" ( diff --git a/adm/templates/env.build.sh.in b/adm/templates/env.build.sh.in index 4e6f2f26d2..3026d4c1f1 100644 --- a/adm/templates/env.build.sh.in +++ b/adm/templates/env.build.sh.in @@ -2,7 +2,7 @@ aScriptPath=${BASH_SOURCE%/*}; if [ -d "${aScriptPath}" ]; then cd "$aScriptPath"; fi; aScriptPath="$PWD"; -# ----- For compatability with external application using CASROOT ----- +# ----- For compatibility with external application using CASROOT ----- if [ "${CASROOT}" == "" ]; then export CASROOT="${aScriptPath}" fi @@ -69,6 +69,10 @@ if [ "$FFMPEG_DIR" != "" ]; then THRDPARTY_PATH="${FFMPEG_DIR}:${THRDPARTY_PATH}" fi +if [ "$JEMALLOC_DIR" != "" ]; then + THRDPARTY_PATH="${JEMALLOC_DIR}:${THRDPARTY_PATH}" +fi + if [ "$QTDIR" != "" ]; then THRDPARTY_PATH="${QTDIR}/lib:${THRDPARTY_PATH}" fi diff --git a/adm/templates/env.install.sh.in b/adm/templates/env.install.sh.in index 07f203b4eb..36254ff8cb 100644 --- a/adm/templates/env.install.sh.in +++ b/adm/templates/env.install.sh.in @@ -2,7 +2,7 @@ aScriptPath=${BASH_SOURCE%/*}; if [ -d "${aScriptPath}" ]; then cd "$aScriptPath"; fi; aScriptPath="$PWD"; -# ----- For compatability with external application using CASROOT ----- +# ----- For compatibility with external application using CASROOT ----- if [ "${CASROOT}" == "" ]; then export CASROOT="@INSTALL_DIR@" fi @@ -71,6 +71,10 @@ if [ "$FFMPEG_DIR" != "" ]; then THRDPARTY_PATH="${FFMPEG_DIR}:${THRDPARTY_PATH}" fi +if [ "$JEMALLOC_DIR" != "" ]; then + THRDPARTY_PATH="${JEMALLOC_DIR}:${THRDPARTY_PATH}" +fi + if [ "$QTDIR" != "" ]; then THRDPARTY_PATH="${QTDIR}/lib:${THRDPARTY_PATH}" fi diff --git a/src/STEPControl/STEPControl_ActorRead.cxx b/src/STEPControl/STEPControl_ActorRead.cxx index 6e15eea916..32f598f763 100644 --- a/src/STEPControl/STEPControl_ActorRead.cxx +++ b/src/STEPControl/STEPControl_ActorRead.cxx @@ -17,6 +17,7 @@ //gka,abv 14.04.99 S4136: maintain unit context, precision and maxtolerance values #include +#include #include #include #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -317,7 +319,10 @@ Handle(Transfer_Binder) STEPControl_ActorRead::Transfer } // [END] Get version of preprocessor (to detect I-Deas case) (ssv; 23.11.2010) Standard_Boolean aTrsfUse = (Interface_Static::IVal("read.step.root.transformation") == 0); - return TransferShape(start, TP, Standard_True, aTrsfUse, theProgress); + auto aResult = TransferShape(start, TP, Standard_True, aTrsfUse, theProgress); + if (Interface_Static::IVal("read.step.parallel.healing") == 0) + PostHealing(TP); + return aResult; } @@ -1480,15 +1485,20 @@ Handle(TransferBRep_ShapeBinder) STEPControl_ActorRead::TransferEntity if (found && myShapeBuilder.IsDone()) { mappedShape = myShapeBuilder.Value(); // Apply ShapeFix (on manifold shapes only. Non-manifold topology is processed separately: ssv; 13.11.2010) - if (isManifold && aHasGeom) + if (isManifold&& aHasGeom) { - Handle(Standard_Transient) info; - mappedShape = - XSAlgo::AlgoContainer()->ProcessShape( mappedShape, myPrecision, myMaxTol, - "read.step.resource.name", - "read.step.sequence", info, - aPS.Next()); - XSAlgo::AlgoContainer()->MergeTransferInfo(TP, info, nbTPitems); + if (Interface_Static::IVal("read.step.parallel.healing") != 0) + { + Handle(Standard_Transient) info; + mappedShape = + XSAlgo::AlgoContainer()->ProcessShape(mappedShape, myPrecision, myMaxTol, + "read.step.resource.name", + "read.step.sequence", info, + aPS.Next()); + XSAlgo::AlgoContainer()->MergeTransferInfo(TP, info, nbTPitems); + } + else + myShapesToHeal.Add(mappedShape); } } found = !mappedShape.IsNull(); @@ -2039,3 +2049,68 @@ void STEPControl_ActorRead::computeIDEASClosings(const TopoDS_Compound& comp, shellClosingsMap.Add(shellA, closingShells); } } + +//======================================================================= +// Method : PostHealing +// Purpose : postprocess shape healing +//======================================================================= +Standard_EXPORT void STEPControl_ActorRead::PostHealing(const Handle(Transfer_TransientProcess)& TP) +{ + NCollection_Array1 aInfos(1, myShapesToHeal.Size()); + NCollection_Array1 aOrigToCopyMapArr(1, myShapesToHeal.Size()); + NCollection_Array1 aCopyToOrigMapArr(1, myShapesToHeal.Size()); + +#pragma omp parallel for + for (int i = 1; i <= myShapesToHeal.Size(); i++) + { + TopoDS_Shape anOrig = myShapesToHeal.FindKey(i); + BRepBuilderAPI_Copy aCurCopy(anOrig, true, true); + TopoDS_Shape aCopy = aCurCopy.Shape(); + // Collect all the modified shapes in Copy() for futher update of binders not to lost attached attributes + for (int aTypeIt = anOrig.ShapeType() + 1; aTypeIt <= TopAbs_VERTEX; aTypeIt++) + { + for (TopExp_Explorer anExp(anOrig, (TopAbs_ShapeEnum)aTypeIt); anExp.More(); anExp.Next()) + { + const TopoDS_Shape& aSx = anExp.Current(); + const TopoDS_Shape& aModifShape = aCurCopy.ModifiedShape(aSx); + aOrigToCopyMapArr.ChangeValue(i).Bind(aSx, aModifShape); + aCopyToOrigMapArr.ChangeValue(i).Bind(aModifShape, aSx); + } + } + Handle(Standard_Transient) anInfo; + aCopy = XSAlgo::AlgoContainer()->ProcessShape(aCopy, myPrecision, myMaxTol, + "read.step.resource.name", + "read.step.sequence", aInfos[i], + Message_ProgressRange()); + *(Handle(TopoDS_TShape)&)anOrig.TShape() = *aCopy.TShape(); + } + + // Update Shape context for correct attributes attaching + Handle(ShapeProcess_ShapeContext) aFullContext = new ShapeProcess_ShapeContext(TopoDS_Shape(), "", ""); + TopTools_DataMapOfShapeShape& aHealedMap = (TopTools_DataMapOfShapeShape&)aFullContext->Map(); + + // Copy maps to the common binders map + for (int i = 1; i <= aOrigToCopyMapArr.Size(); i++) + { + const auto& aForwMap = aOrigToCopyMapArr.Value(i); + const auto& aRevMap = aCopyToOrigMapArr.Value(i); + Handle(ShapeProcess_ShapeContext) aContext = aInfos.Value(i); + + for (TopTools_DataMapOfShapeShape::Iterator aMapIt(aForwMap); aMapIt.More(); aMapIt.Next()) + { + aHealedMap.Bind(aMapIt.Key(), aMapIt.Value()); + } + for (TopTools_DataMapOfShapeShape::Iterator anIter(aContext->Map()); anIter.More(); anIter.Next()) + { + TopoDS_Shape aShape; + if (aRevMap.Find(anIter.Key(), aShape)) + { + aHealedMap.Bind(aShape, anIter.Value()); + } + } + } + + XSAlgo::AlgoContainer()->MergeTransferInfo(TP, aFullContext); + + CleanShapesToHeal(); +} diff --git a/src/STEPControl/STEPControl_ActorRead.hxx b/src/STEPControl/STEPControl_ActorRead.hxx index 22cae5b63b..c2bce114a9 100644 --- a/src/STEPControl/STEPControl_ActorRead.hxx +++ b/src/STEPControl/STEPControl_ActorRead.hxx @@ -28,6 +28,7 @@ #include #include #include +#include class StepRepr_Representation; class Standard_Transient; @@ -98,8 +99,14 @@ public: //! REPRESENTATION_RELATIONSHIP_WITH_TRANSFORMATION Standard_EXPORT Standard_Boolean ComputeSRRWT (const Handle(StepRepr_RepresentationRelationship)& SRR, const Handle(Transfer_TransientProcess)& TP, gp_Trsf& Trsf); + //! Heals the collected during transferring shapes + Standard_EXPORT void PostHealing(const Handle(Transfer_TransientProcess)& TP); - + //! Cleans collected for post healing shapes. + inline void CleanShapesToHeal() + { + myShapesToHeal.Clear(); + } DEFINE_STANDARD_RTTIEXT(STEPControl_ActorRead,Transfer_ActorOfTransientProcess) @@ -185,8 +192,7 @@ private: Standard_Real myPrecision; Standard_Real myMaxTol; Handle(StepRepr_Representation) mySRContext; - - + NCollection_IndexedMap myShapesToHeal; }; diff --git a/src/STEPControl/STEPControl_Controller.cxx b/src/STEPControl/STEPControl_Controller.cxx index 1dd44f6aef..1c64a18358 100644 --- a/src/STEPControl/STEPControl_Controller.cxx +++ b/src/STEPControl/STEPControl_Controller.cxx @@ -217,6 +217,12 @@ STEPControl_Controller::STEPControl_Controller () Interface_Static::Init("step", "read.step.root.transformation", '&', "eval OFF"); Interface_Static::SetCVal("read.step.root.transformation", "ON"); + Interface_Static::Init("step", "read.step.parallel.healing", 'e', ""); + Interface_Static::Init("step", "read.step.parallel.healing", '&', "enum 0"); + Interface_Static::Init("step", "read.step.parallel.healing", '&', "eval ON"); + Interface_Static::Init("step", "read.step.parallel.healing", '&', "eval OFF"); + Interface_Static::SetCVal("read.step.parallel.healing", "ON"); + // STEP file encoding for names translation // Note: the numbers should be consistent with Resource_FormatType enumeration Interface_Static::Init("step", "read.step.codepage", 'e', ""); diff --git a/src/Standard/Standard.cxx b/src/Standard/Standard.cxx index 78b25e1cb7..6146e96ba1 100644 --- a/src/Standard/Standard.cxx +++ b/src/Standard/Standard.cxx @@ -1,7 +1,4 @@ -// Created on: 2005-03-15 -// Created by: Peter KURNEV -// Copyright (c) 1998-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS +// Copyright (c) 1999-2023 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -14,301 +11,173 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - #include -#include -#include -#include -#include + +#include #include + #if(defined(_WIN32) || defined(__WIN32__)) - #include - #include - #include +#include +#include +#include #endif #if defined(_MSC_VER) || defined(__ANDROID__) || defined(__QNX__) - #include +#include #elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && (defined(__i386) || defined(__x86_64))) - #include +#include #else - extern "C" int posix_memalign (void** thePtr, size_t theAlign, size_t theSize); +extern "C" int posix_memalign(void** thePtr, size_t theAlign, size_t theSize); #endif -// There is no support for environment variables in UWP -// OSD_Environment could not be used here because of cyclic dependency -#ifdef OCCT_UWP -#define getenv(x) NULL +#ifdef OCCT_MMGT_OPT_JEMALLOC +#define JEMALLOC_NO_DEMANGLE +#include +#endif // OCCT_MMGT_OPT_JEMALLOC + +// paralleling with Intel TBB +#ifdef HAVE_TBB +#include +#else +#ifdef OCCT_MMGT_OPT_TBB +#undef OCCT_MMGT_OPT_TBB +#endif +#define scalable_malloc malloc +#define scalable_calloc calloc +#define scalable_realloc realloc +#define scalable_free free #endif -#ifndef OCCT_MMGT_OPT_DEFAULT -#define OCCT_MMGT_OPT_DEFAULT 0 -#endif - -//======================================================================= -//class : Standard_MMgrFactory -//purpose : Container for pointer to memory manager; -// used to construct appropriate memory manager according -// to environment settings, and to ensure destruction upon exit -//======================================================================= -class Standard_MMgrFactory -{ -public: - static Standard_MMgrRoot* GetMMgr(); - ~Standard_MMgrFactory(); - -private: - Standard_MMgrFactory(); - Standard_MMgrFactory (const Standard_MMgrFactory&); - Standard_MMgrFactory& operator= (const Standard_MMgrFactory&); - -private: - Standard_MMgrRoot* myFMMgr; -}; - -//======================================================================= -//function : Standard_MMgrFactory -//purpose : Check environment variables and create appropriate memory manager -//======================================================================= - -Standard_MMgrFactory::Standard_MMgrFactory() -: myFMMgr (NULL) -{ -/*#if defined(_MSC_VER) && (_MSC_VER > 1400) - // Turn ON thread-safe C locale globally to avoid side effects by setlocale() calls between threads. - // After this call all following _configthreadlocale() will be ignored assuming - // Notice that this is MSVCRT feature - on POSIX systems xlocale API (uselocale instead of setlocale) - // should be used explicitly to ensure thread-safety! - - // This is not well documented call because _ENABLE_PER_THREAD_LOCALE_GLOBAL flag is defined but not implemented for some reason. - // -1 will set global locale flag to force _ENABLE_PER_THREAD_LOCALE_GLOBAL + _ENABLE_PER_THREAD_LOCALE_NEW behaviour - // although there NO way to turn it off again and following calls will have no effect (locale will be changed only for current thread). - _configthreadlocale (-1); -#endif*/ - - // Check basic assumption. - // If assertion happens, then OCCT should be corrected for compatibility with such CPU architecture. - Standard_STATIC_ASSERT(sizeof(Standard_Utf8Char) == 1); - Standard_STATIC_ASSERT(sizeof(short) == 2); - Standard_STATIC_ASSERT(sizeof(Standard_Utf16Char) == 2); - Standard_STATIC_ASSERT(sizeof(Standard_Utf32Char) == 4); -#ifdef _WIN32 - Standard_STATIC_ASSERT(sizeof(Standard_WideChar) == sizeof(Standard_Utf16Char)); -#endif - - char* aVar; - aVar = getenv ("MMGT_OPT"); - Standard_Integer anAllocId = (aVar ? atoi (aVar): OCCT_MMGT_OPT_DEFAULT); - -#if defined(HAVE_TBB) && defined(_M_IX86) - if (anAllocId == 2) - { - // CR25396: Check if SSE2 instructions are supported on 32-bit x86 processor on Windows platform, - // if not then use MMgrRaw instead of MMgrTBBalloc. - // It is to avoid runtime crash when running on a CPU - // that supports SSE but does not support SSE2 (some modifications of AMD Sempron). - static const DWORD _SSE2_FEATURE_BIT(0x04000000); - DWORD volatile dwFeature; - _asm - { - push eax - push ebx - push ecx - push edx - - // get the CPU feature bits - mov eax, 1 - cpuid - mov dwFeature, edx - - pop edx - pop ecx - pop ebx - pop eax - } - if ((dwFeature & _SSE2_FEATURE_BIT) == 0) - anAllocId = 0; - } -#endif - - aVar = getenv ("MMGT_CLEAR"); - Standard_Boolean toClear = (aVar ? (atoi (aVar) != 0) : Standard_True); - - // on Windows (actual for XP and 2000) activate low fragmentation heap - // for CRT heap in order to get best performance. - // Environment variable MMGT_LFH can be used to switch off this action (if set to 0) -#if defined(_MSC_VER) - aVar = getenv ("MMGT_LFH"); - if ( aVar == NULL || atoi (aVar) != 0 ) - { - ULONG aHeapInfo = 2; - HANDLE aCRTHeap = (HANDLE)_get_heap_handle(); - HeapSetInformation (aCRTHeap, HeapCompatibilityInformation, &aHeapInfo, sizeof(aHeapInfo)); - } -#endif - - switch (anAllocId) - { - case 1: // OCCT optimized memory allocator - { - aVar = getenv ("MMGT_MMAP"); - Standard_Boolean bMMap = (aVar ? (atoi (aVar) != 0) : Standard_True); - aVar = getenv ("MMGT_CELLSIZE"); - Standard_Integer aCellSize = (aVar ? atoi (aVar) : 200); - aVar = getenv ("MMGT_NBPAGES"); - Standard_Integer aNbPages = (aVar ? atoi (aVar) : 1000); - aVar = getenv ("MMGT_THRESHOLD"); - Standard_Integer aThreshold = (aVar ? atoi (aVar) : 40000); - myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold); - break; - } - case 2: // TBB memory allocator - myFMMgr = new Standard_MMgrTBBalloc (toClear); - break; - case 0: - default: // system default memory allocator - myFMMgr = new Standard_MMgrRaw (toClear); - } -} - -//======================================================================= -//function : ~Standard_MMgrFactory -//purpose : -//======================================================================= - -Standard_MMgrFactory::~Standard_MMgrFactory() -{ - if ( myFMMgr ) - myFMMgr->Purge(Standard_True); -} - -//======================================================================= -// function: GetMMgr -// -// This static function has a purpose to wrap static holder for memory -// manager instance. -// -// Wrapping holder inside a function is needed to ensure that it will -// be initialized not later than the first call to memory manager (that -// would be impossible to guarantee if holder was static variable on -// global or file scope, because memory manager may be called from -// constructors of other static objects). -// -// Note that at the same time we could not guarantee that the holder -// object is destroyed after last call to memory manager, since that -// last call may be from static Handle() object which has been initialized -// dynamically during program execution rather than in its constructor. -// -// Therefore holder currently does not call destructor of the memory manager -// but only its method Purge() with Standard_True. -// -// To free the memory completely, we probably could use compiler-specific -// pragmas (such as '#pragma fini' on SUN Solaris and '#pragma init_seg' on -// WNT MSVC++) to put destructing function in code segment that is called -// after destructors of other (even static) objects. However, this is not -// done by the moment since it is compiler-dependent and there is no guarantee -// thatsome other object calling memory manager is not placed also in that segment... -// -// Note that C runtime function atexit() could not help in this problem -// since its behaviour is the same as for destructors of static objects -// (see ISO 14882:1998 "Programming languages -- C++" 3.6.3) -// -// The correct approach to deal with the problem would be to have memory manager -// to properly control its memory allocation and caching free blocks so -// as to release all memory as soon as it is returned to it, and probably -// even delete itself if all memory it manages has been released and -// last call to method Purge() was with True. -// -// Note that one possible method to control memory allocations could -// be counting calls to Allocate() and Free()... -// -//======================================================================= -Standard_MMgrRoot* Standard_MMgrFactory::GetMMgr() -{ - static Standard_MMgrFactory aFactory; - return aFactory.myFMMgr; -} +// Available macros definition +// - OCCT_MMGT_OPT_TBB, using tbb::scalable_allocator +// - OCCT_MMGT_OPT_NATIVE, using native calloc, free +// - OCCT_MMGT_OPT_JEMALLOC, using external jecalloc, jefree //======================================================================= //function : Allocate -//purpose : +//purpose : //======================================================================= - -Standard_Address Standard::Allocate(const Standard_Size size) +Standard_Address Standard::Allocate(const Standard_Size theSize) { - return Standard_MMgrFactory::GetMMgr()->Allocate(size); +#if defined OCCT_MMGT_OPT_JEMALLOC + Standard_Address aPtr = je_calloc(theSize, sizeof(char)); + if (!aPtr) + throw Standard_OutOfMemory("Standard_MMgrRaw::Allocate(): malloc failed"); + return aPtr; +#elif defined OCCT_MMGT_OPT_TBB + Standard_Address aPtr = scalable_calloc(theSize, sizeof(char)); + if (!aPtr) + throw Standard_OutOfMemory("Standard_MMgrRaw::Allocate(): malloc failed"); + return aPtr; +#else + Standard_Address aPtr = calloc(theSize, sizeof(char)); + if (!aPtr) + throw Standard_OutOfMemory("Standard_MMgrRaw::Allocate(): malloc failed"); + return aPtr; +#endif } //======================================================================= //function : Free -//purpose : +//purpose : //======================================================================= - -void Standard::Free (Standard_Address theStorage) +void Standard::Free(Standard_Address theStorage) { - Standard_MMgrFactory::GetMMgr()->Free(theStorage); +#if defined OCCT_MMGT_OPT_JEMALLOC + je_free(theStorage); +#elif defined OCCT_MMGT_OPT_TBB + scalable_free(theStorage); +#else + free(theStorage); +#endif } //======================================================================= //function : Reallocate -//purpose : +//purpose : //======================================================================= - -Standard_Address Standard::Reallocate (Standard_Address theStorage, - const Standard_Size theSize) +Standard_Address Standard::Reallocate(Standard_Address theStorage, + const Standard_Size theSize) { - return Standard_MMgrFactory::GetMMgr()->Reallocate (theStorage, theSize); + // Note that it is not possible to ensure that additional memory + // allocated by realloc will be cleared (so as to satisfy myClear mode); + // in order to do that we would need using memset.. +#if defined OCCT_MMGT_OPT_JEMALLOC + Standard_Address aNewStorage = (Standard_Address)je_realloc(theStorage, theSize); + if (!aNewStorage) + throw Standard_OutOfMemory("Standard_MMgrRaw::Reallocate(): realloc failed"); + return aNewStorage; +#elif defined OCCT_MMGT_OPT_TBB + Standard_Address aNewStorage = (Standard_Address)scalable_realloc(theStorage, theSize); + if (!aNewStorage) + throw Standard_OutOfMemory("Standard_MMgrRaw::Reallocate(): realloc failed"); + return aNewStorage; +#else + Standard_Address aNewStorage = (Standard_Address)realloc(theStorage, theSize); + if (!aNewStorage) + throw Standard_OutOfMemory("Standard_MMgrRaw::Reallocate(): realloc failed"); + return aNewStorage; +#endif } //======================================================================= //function : Purge -//purpose : +//purpose : //======================================================================= - Standard_Integer Standard::Purge() { - return Standard_MMgrFactory::GetMMgr()->Purge(); + return true; } //======================================================================= //function : AllocateAligned //purpose : //======================================================================= - -Standard_Address Standard::AllocateAligned (const Standard_Size theSize, - const Standard_Size theAlign) +Standard_Address Standard::AllocateAligned(const Standard_Size theSize, + const Standard_Size theAlign) { +#ifdef OCCT_MMGT_OPT_JEMALLOC + return je_aligned_alloc(theAlign, theSize); +#elif defined OCCT_MMGT_OPT_TBB + return scalable_aligned_malloc(theSize, theAlign); +#else #if defined(_MSC_VER) - return _aligned_malloc (theSize, theAlign); + return _aligned_malloc(theSize, theAlign); #elif defined(__ANDROID__) || defined(__QNX__) - return memalign (theAlign, theSize); + return memalign(theAlign, theSize); #elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && (defined(__i386) || defined(__x86_64))) - return _mm_malloc (theSize, theAlign); + return _mm_malloc(theSize, theAlign); #else void* aPtr; - if (posix_memalign (&aPtr, theAlign, theSize)) + if (posix_memalign(&aPtr, theAlign, theSize)) { return NULL; } return aPtr; #endif +#endif } //======================================================================= //function : FreeAligned //purpose : //======================================================================= - -void Standard::FreeAligned (Standard_Address thePtrAligned) +void Standard::FreeAligned(Standard_Address thePtrAligned) { -#if defined(_MSC_VER) - _aligned_free (thePtrAligned); -#elif defined(__ANDROID__) || defined(__QNX__) - free (thePtrAligned); -#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && (defined(__i386) || defined(__x86_64))) - _mm_free (thePtrAligned); +#ifdef OCCT_MMGT_OPT_JEMALLOC +return je_free(thePtrAligned); +#elif defined OCCT_MMGT_OPT_TBB + return scalable_aligned_free(thePtrAligned); #else - free (thePtrAligned); +#if defined(_MSC_VER) + _aligned_free(thePtrAligned); +#elif defined(__ANDROID__) || defined(__QNX__) + free(thePtrAligned); +#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && (defined(__i386) || defined(__x86_64))) + _mm_free(thePtrAligned); +#else + free(thePtrAligned); +#endif #endif } diff --git a/src/TKernel/CMakeLists.txt b/src/TKernel/CMakeLists.txt index aa2ddb052d..6a85c03352 100644 --- a/src/TKernel/CMakeLists.txt +++ b/src/TKernel/CMakeLists.txt @@ -1,3 +1,12 @@ project(TKernel) OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) + +# Set desired Memory Manager +if ("${USE_MMGR_TYPE}" STREQUAL "TBB") + target_compile_definitions("TKernel" PRIVATE "OCCT_MMGT_OPT_TBB") +elseif ("${USE_MMGR_TYPE}" STREQUAL "JEMALLOC") + target_compile_definitions("TKernel" PRIVATE "OCCT_MMGT_OPT_JEMALLOC") +else () + message (STATUS "Info: Used native memory manager") +endif() diff --git a/src/TKernel/EXTERNLIB b/src/TKernel/EXTERNLIB index 8911ab53c5..1c9d77f47f 100755 --- a/src/TKernel/EXTERNLIB +++ b/src/TKernel/EXTERNLIB @@ -7,3 +7,4 @@ CSF_dl CSF_wsock32 CSF_psapi CSF_androidlog +CSF_MMGR