From fd3474f5cb5632f219e4f70b79792c9a804ec19e Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 28 Dec 2018 13:43:15 +0100 Subject: [PATCH 01/28] logging in ngcore --- .gitlab-ci.yml | 7 ++ CMakeLists.txt | 8 ++ cmake/SuperBuild.cmake | 2 + cmake/external_projects/spdlog.cmake | 18 ++++ libsrc/core/CMakeLists.txt | 31 +++++- libsrc/core/archive.hpp | 140 +++++++++++++++++++++------ libsrc/core/logging.cpp | 109 +++++++++++++++++++++ libsrc/core/logging.hpp | 87 +++++++++++++++++ libsrc/core/ngcore.hpp | 1 + libsrc/core/ngcore_api.hpp | 4 +- libsrc/core/python_ngcore.cpp | 30 ++++++ libsrc/general/CMakeLists.txt | 4 + libsrc/gprim/CMakeLists.txt | 3 + libsrc/linalg/CMakeLists.txt | 4 + libsrc/meshing/python_mesh.cpp | 1 - libsrc/occ/CMakeLists.txt | 2 +- libsrc/stlgeom/CMakeLists.txt | 3 +- libsrc/visualization/CMakeLists.txt | 2 +- tests/build_nospdlog.sh | 8 ++ tests/catch/CMakeLists.txt | 9 +- 20 files changed, 428 insertions(+), 45 deletions(-) create mode 100644 cmake/external_projects/spdlog.cmake create mode 100644 libsrc/core/logging.cpp create mode 100644 libsrc/core/logging.hpp create mode 100644 libsrc/core/python_ngcore.cpp create mode 100644 tests/build_nospdlog.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86105bfb..d493bdab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -101,6 +101,13 @@ test_guidelines: - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh when: always +# check if it compiles without spdlog +test_noSpdlog: + <<: *ubuntu + stage: test + script: + - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_nospdlog.sh + cleanup_ubuntu: stage: cleanup tags: diff --git a/CMakeLists.txt b/CMakeLists.txt index 14931c4d..5d2e6a9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,8 @@ option( USE_CCACHE "use ccache") option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON) option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) +option( USE_SPDLOG "Enable spd log logging" ON) +option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF) option( USE_SUPERBUILD "use ccache" ON) @@ -258,6 +260,7 @@ endif (USE_GUI) ####################################################################### if (USE_PYTHON) + add_subdirectory(external_dependencies/pybind11) add_definitions(-DNG_PYTHON) find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR}) if( PYBIND_INCLUDE_DIR ) @@ -350,6 +353,11 @@ endif(ENABLE_UNIT_TESTS) ####################################################################### +if(USE_SPDLOG) + include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/external_projects/spdlog.cmake) + include_directories(${SPDLOG_INCLUDE_DIR}) +endif(USE_SPDLOG) + if(ENABLE_CPP_CORE_GUIDELINES_CHECK) find_program( CLANG_TIDY_EXE diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 36ea3fcb..6e7fabd7 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -142,6 +142,8 @@ set_vars( NETGEN_CMAKE_ARGS CMAKE_INSTALL_PREFIX ENABLE_UNIT_TESTS ENABLE_CPP_CORE_GUIDELINES_CHECK + USE_SPDLOG + DEBUG_LOG ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/cmake/external_projects/spdlog.cmake b/cmake/external_projects/spdlog.cmake new file mode 100644 index 00000000..d932ebef --- /dev/null +++ b/cmake/external_projects/spdlog.cmake @@ -0,0 +1,18 @@ +include(ExternalProject) +find_program(GIT_EXECUTABLE git) + +ExternalProject_Add( + project_spdlog + PREFIX ${CMAKE_BINARY_DIR}/spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG v1.2.1 + TIMEOUT 01 + UPDATE_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + +ExternalProject_Get_Property(project_spdlog source_dir) +set(SPDLOG_INCLUDE_DIR ${source_dir}/include) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 92f2e8b7..16cec927 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,16 +1,41 @@ -add_library(ngcore SHARED archive.cpp) -target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) +add_library(ngcore SHARED archive.cpp logging.cpp) + +target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) +if(NOT WIN32) + target_compile_options(ngcore PRIVATE -fvisibility=hidden) +endif(NOT WIN32) + +if(USE_SPDLOG) + include_directories(${SPDLOG_INCLUDE_DIR}) + install(DIRECTORY ${SPDLOG_INCLUDE_DIR} + DESTINATION ${NG_INSTALL_DIR_INCLUDE} + ) + add_dependencies(ngcore project_spdlog) + target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG) + if(DEBUG_LOG) + target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG) + endif(DEBUG_LOG) +endif(USE_SPDLOG) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) if(USE_PYTHON) + target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON) target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS}) endif(USE_PYTHON) -install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp +install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) + +if(USE_PYTHON) + pybind11_add_module(pyngcore SHARED python_ngcore.cpp) + target_link_libraries(pyngcore PUBLIC ngcore) + set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}") + install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen) +endif(USE_PYTHON) + diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index fd2ee275..aa6537d2 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -3,24 +3,25 @@ #include // for complex #include // for size_t, strlen -#include // for operator<<, ifstream, ofstream, basic... +#include // for ifstream, ofstream #include // for function -#include // for map, _Rb_tree_iterator -#include // for __shared_ptr_access, __shared_ptr_acc... +#include // for map +#include // for shared_ptr #include // for runtime_error -#include // for string, operator+ +#include // for string #include // for declval, enable_if, false_type, is_co... #include // for type_info #include // for move, swap, pair #include // for vector +#include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API, unlikely #include "type_traits.hpp" // for all_of_tmpl #include "version.hpp" // for VersionInfo -#ifdef NG_PYTHON +#ifdef NETGEN_PYTHON #include -#endif // NG_PYTHON +#endif // NETGEN_PYTHON namespace ngcore { @@ -104,20 +105,28 @@ namespace ngcore std::vector nr2ptr; protected: bool shallow_to_python = false; + // version map is only used in InArchives + std::map version_map; + std::shared_ptr logger; public: Archive() = delete; Archive(const Archive&) = delete; Archive(Archive&&) = delete; - Archive (bool ais_output) : - is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } + Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), + ptr_count(0), logger(GetLogger("Archive")) { ; } virtual ~Archive() { ; } + // If the object is pickled, all shallow archived objects will be pickled as a list, + // instead of written as a binary archive. This allows pickle to serialize every object only + // once and put them together correctly afterwards. Therefore all objects that may live in + // Python should be archived using this Shallow function. If Shallow is called from C++ code + // it archives the object normally. template Archive& Shallow(T& val) { static_assert(detail::is_any_pointer, "ShallowArchive must be given pointer type!"); -#ifdef NG_PYTHON +#ifdef NETGEN_PYTHON if(shallow_to_python) { if(is_output) @@ -126,17 +135,17 @@ namespace ngcore val = pybind11::cast(ShallowInPython()); } else -#endif // NG_PYTHON +#endif // NETGEN_PYTHON *this & val; return *this; } -#ifdef NG_PYTHON - virtual void ShallowOutPython(pybind11::object /*unused*/) // NOLINT (copy by val is ok for this virt func) +#ifdef NETGEN_PYTHON + virtual void ShallowOutPython(const pybind11::object& /*unused*/) { throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); } virtual pybind11::object ShallowInPython() { throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } -#endif // NG_PYTHON +#endif // NETGEN_PYTHON Archive& operator=(const Archive&) = delete; Archive& operator=(Archive&&) = delete; @@ -261,28 +270,39 @@ namespace ngcore { if(Output()) { + NETGEN_DEBUG_LOG(logger, "Store shared ptr of type " + Demangle(typeid(T).name())); // save -2 for nullptr if(!ptr) - return (*this) << -2; + { + NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + return (*this) << -2; + } void* reg_ptr = ptr.get(); bool neededDowncast = false; // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { + NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*ptr).name()) + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information - if(reg_ptr != static_cast(ptr.get()) ) + if(reg_ptr != static_cast(ptr.get())) + { + NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); neededDowncast = true; + } } auto pos = shared_ptr2nr.find(reg_ptr); // if not found store -1 and the pointer if(pos == shared_ptr2nr.end()) { + NETGEN_DEBUG_LOG(logger, "Didn't find the shared_ptr, create new registry entry at " + + std::to_string(shared_ptr_count)); auto p = ptr.get(); (*this) << -1; (*this) & neededDowncast & p; @@ -293,23 +313,27 @@ namespace ngcore return *this; } // if found store the position and if it has to be downcasted and how + NETGEN_DEBUG_LOG(logger, "Found shared_ptr at position " + std::to_string(pos->second)); (*this) << pos->second << neededDowncast; if(neededDowncast) (*this) << Demangle(typeid(*ptr).name()); } else // Input { + NETGEN_DEBUG_LOG(logger, "Reading shared_ptr of type " + Demangle(typeid(T).name())); int nr; (*this) & nr; // -2 restores a nullptr if(nr == -2) { + NETGEN_DEBUG_LOG(logger, "Reading a nullptr"); ptr = nullptr; return *this; } // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it if (nr == -1) { + NETGEN_DEBUG_LOG(logger, "Createing new shared_ptr"); T* p = nullptr; bool neededDowncast; (*this) & neededDowncast & p; @@ -317,6 +341,7 @@ namespace ngcore // if we did downcast we need to store a shared_ptr to the true object if(neededDowncast) { + NETGEN_DEBUG_LOG(logger, "Shared pointer needed downcasting"); std::string name; (*this) & name; auto info = GetArchiveRegister(name); @@ -327,15 +352,20 @@ namespace ngcore ptr.get()))); } else - nr2shared_ptr.push_back(ptr); + { + NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need downcasting"); + nr2shared_ptr.push_back(ptr); + } } else { + NETGEN_DEBUG_LOG(logger, "Reading already existing pointer at entry " + std::to_string(nr)); auto other = nr2shared_ptr[nr]; bool neededDowncast; (*this) & neededDowncast; if(neededDowncast) { + NETGEN_DEBUG_LOG(logger, "Shared pointer needed pointer downcast"); // if there was a downcast we can expect the class to be registered (since archiving // wouldn't have worked else) std::string name; @@ -348,7 +378,10 @@ namespace ngcore other.get()))); } else - ptr = std::static_pointer_cast(other); + { + NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need pointer casts"); + ptr = std::static_pointer_cast(other); + } } } return *this; @@ -360,26 +393,39 @@ namespace ngcore { if (Output()) { + NETGEN_DEBUG_LOG(logger, "Store pointer of type " + Demangle(typeid(T).name())); // if the pointer is null store -2 if (!p) - return (*this) << -2; + { + NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + return (*this) << -2; + } auto reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { + NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + + Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); + if(reg_ptr != static_cast(p)) + { + NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); + } } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { + NETGEN_DEBUG_LOG(logger, "Didn't find pointer, create new registry entry at " + + std::to_string(ptr_count)); ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if (std::is_constructible::value) { + NETGEN_DEBUG_LOG(logger, "Store standard class pointer (no virt. inh,...)"); return (*this) << -1 & (*p); } else @@ -395,6 +441,7 @@ namespace ngcore throw std::runtime_error(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); + NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } } @@ -402,27 +449,39 @@ namespace ngcore { (*this) & pos->second; bool downcasted = !(reg_ptr == static_cast(p) ); + NETGEN_DEBUG_LOG(logger, "Store a the existing position in registry at " + + std::to_string(pos->second)); + NETGEN_DEBUG_LOG(logger, std::string("Pointer ") + (downcasted ? "needs " : "doesn't need ") + + "downcasting"); // store if the class has been downcasted and the name (*this) << downcasted << Demangle(typeid(*p).name()); } } else { + NETGEN_DEBUG_LOG(logger, "Reading pointer of type " + Demangle(typeid(T).name())); int nr; (*this) & nr; if (nr == -2) // restore a nullptr + { + NETGEN_DEBUG_LOG(logger, "Loading a nullptr"); p = nullptr; + } else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { + NETGEN_DEBUG_LOG(logger, "Load a new pointer to a simple class"); p = detail::constructIfPossible(); nr2ptr.push_back(p); (*this) & *p; } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { + NETGEN_DEBUG_LOG(logger, "Load a new pointer to a potentially more complicated class " + "(allows for multiple/virtual inheritance,...)"); // As stated above, we want this special behaviour only for our classes that implement DoArchive std::string name; (*this) & name; + NETGEN_DEBUG_LOG(logger, "Name = " + name); auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) @@ -434,9 +493,13 @@ namespace ngcore } else { + NETGEN_DEBUG_LOG(logger, "Restoring pointer to already existing object at registry position " + + std::to_string(nr)); bool downcasted; std::string name; (*this) & downcasted & name; + NETGEN_DEBUG_LOG(logger, std::string(downcasted ? "Downcasted" : "Not downcasted") + + " object of type " + name); if(downcasted) { // if the class has been downcasted we can assume it is in the register @@ -536,7 +599,7 @@ namespace ngcore { static_assert(detail::all_of_tmpl::value...>, "Variadic template arguments must be base classes of T"); - detail::ClassArchiveInfo info; + detail::ClassArchiveInfo info {}; info.creator = [this,&info](const std::type_info& ti) -> void* { return typeid(T) == ti ? detail::constructIfPossible() : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; @@ -643,6 +706,9 @@ namespace ngcore BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } + const VersionInfo& GetVersion(const std::string& library) override + { return version_map[library]; } + using Archive::operator&; Archive & operator & (double & d) override { Read(d); return *this; } @@ -758,6 +824,9 @@ namespace ngcore TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} + const VersionInfo& GetVersion(const std::string& library) override + { return version_map[library]; } + using Archive::operator&; Archive & operator & (double & d) override { *stream >> d; return *this; } @@ -805,7 +874,7 @@ namespace ngcore } }; -#ifdef NG_PYTHON +#ifdef NETGEN_PYTHON template class PyArchive : public ARCHIVE @@ -813,7 +882,11 @@ namespace ngcore private: pybind11::list lst; size_t index = 0; + protected: using ARCHIVE::stream; + using ARCHIVE::version_map; + using ARCHIVE::logger; + using ARCHIVE::GetLibraryVersions; public: PyArchive(const pybind11::object& alst = pybind11::none()) : ARCHIVE(std::make_shared()), @@ -821,8 +894,13 @@ namespace ngcore { ARCHIVE::shallow_to_python = true; if(Input()) - stream = std::make_shared - (pybind11::cast(lst[pybind11::len(lst)-1])); + { + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-1])); + *this & version_map; + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-2])); + } } using ARCHIVE::Output; @@ -831,39 +909,45 @@ namespace ngcore using ARCHIVE::operator&; using ARCHIVE::operator<<; using ARCHIVE::GetVersion; - void ShallowOutPython(pybind11::object val) override { lst.append(val); } + void ShallowOutPython(const pybind11::object& val) override { lst.append(val); } pybind11::object ShallowInPython() override { return lst[index++]; } pybind11::list WriteOut() { FlushBuffer(); lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); + stream = std::make_shared(); + *this & GetLibraryVersions(); return lst; } }; template - auto NGSPickle(bool printoutput=false) + auto NGSPickle() { - return pybind11::pickle([printoutput](T* self) + return pybind11::pickle([](T* self) { PyArchive ar; ar & self; auto output = pybind11::make_tuple(ar.WriteOut()); - if(printoutput) - pybind11::print("pickle output of", Demangle(typeid(T).name()),"=", output); + NETGEN_DEBUG_LOG(GetLogger("Archive"), "pickling output for object of type " + + Demangle(typeid(T).name()) + " = " + + std::string(pybind11::str(output))); return output; }, [](pybind11::tuple state) { T* val = nullptr; + NETGEN_DEBUG_LOG(GetLogger("Archive"), "State for unpickling of object of type " + + Demangle(typeid(T).name()) + " = " + + std::string(pybind11::str(state[0]))); PyArchive ar(state[0]); ar & val; return val; }); } -#endif // NG_PYTHON +#endif // NETGEN_PYTHON } // namespace ngcore #endif // NETGEN_CORE_ARCHIVE_HPP diff --git a/libsrc/core/logging.cpp b/libsrc/core/logging.cpp new file mode 100644 index 00000000..467255cd --- /dev/null +++ b/libsrc/core/logging.cpp @@ -0,0 +1,109 @@ + +#include "logging.hpp" + +#ifdef NETGEN_USE_SPDLOG + +#include +#include + +#endif // NETGEN_USE_SPDLOG + +namespace ngcore +{ +#ifdef NETGEN_USE_SPDLOG + namespace detail + { + std::vector>& GetDefaultSinks() + { + static std::vector> sinks = + { std::make_shared() }; + return sinks; + } + std::shared_ptr CreateDefaultLogger(const std::string& name) + { + auto& default_sinks = GetDefaultSinks(); + auto logger = std::make_shared(name, default_sinks.begin(), default_sinks.end()); + spdlog::details::registry::instance().register_and_init(logger); + return logger; + } + } // namespace detail + + std::shared_ptr GetLogger(const std::string& name) + { + auto logger = spdlog::get(name); + if(!logger) + logger = detail::CreateDefaultLogger(name); + return logger; + } + + void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name) + { + if(!name.empty()) + spdlog::get(name)->set_level(level); + else + spdlog::set_level(level); + } + + void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger) + { + auto sink = std::make_shared(filename); + sink->set_level(level); + if(!logger.empty()) + GetLogger(logger)->sinks().push_back(sink); + else + { + detail::GetDefaultSinks().push_back(sink); + spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); + } + } + + void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger) + { + auto sink = std::make_shared(); + sink->set_level(level); + if(!logger.empty()) + GetLogger(logger)->sinks().push_back(sink); + else + { + detail::GetDefaultSinks().push_back(sink); + spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); + } + } + + void ClearLoggingSinks(const std::string& logger) + { + if(!logger.empty()) + GetLogger(logger)->sinks().clear(); + else + { + detail::GetDefaultSinks().clear(); + spdlog::details::registry::instance().apply_all([](auto logger) { logger->sinks().clear(); }); + } + } + + void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger) + { + if(!logger.empty()) + GetLogger(logger)->flush_on(level); + else + spdlog::flush_on(level); + } + +#else // NETGEN_USE_SPDLOG + + // Dummy functions if no spdlog is available + + std::shared_ptr GetLogger(const std::string& /*unused*/) + { + return std::make_shared(); + } + void SetLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + void AddFileSink(const std::string& /*unused*/, spdlog::level::level_enum /*unused*/, + const std::string& /*unused*/) + {} + void AddConsoleSink(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + void ClearLoggingSinks(const std::string& /*unused*/) {} + void FlushOnLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + +#endif // NETGEN_USE_SPDLOG +} //namespace ngcore diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp new file mode 100644 index 00000000..8952a5f6 --- /dev/null +++ b/libsrc/core/logging.hpp @@ -0,0 +1,87 @@ +#ifndef NETGEN_CORE_LOGGING_HPP +#define NETGEN_CORE_LOGGING_HPP + +#include +#include +#include + +#include "ngcore_api.hpp" + +#ifdef NETGEN_USE_SPDLOG + +#ifdef NETGEN_LOG_DEBUG +#define SPDLOG_DEBUG_ON +#endif // NETGEN_LOG_DEBUG + +#include +#include +#include + +#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) + +#else // NETGEN_USE_SPDLOG + +#include + +namespace spdlog +{ + // Dummys if Netgen is compiled with USE_SPDLOG=OFF. + class logger + { + public: + template + void trace(const T& /*unused*/) {} + template + void debug(const T& /*unused*/) {} + template + void info(const T& text) { std::cout << text << std::endl; } + template + void warn(const T& text) { std::cout << text << std::endl; } + template + void error(const T& text) { std::cout << text << std::endl; } + template + void critical(const T& text) { std::cout << text << std::endl; } + }; + + namespace level + { + enum level_enum + { + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 + }; + } // namespace level + + namespace sinks + { + class sink {}; + } // namespace sinks + +} //namespace spdlog + +#define NETGEN_DEBUG_LOG(logger, ...) + +#endif // NETGEN_USE_SPDLOG + +namespace ngcore +{ + namespace detail + { + std::vector>& GetDefaultSinks(); + inline std::shared_ptr CreateDefaultLogger(const std::string& name); + } //namespace detail + + NGCORE_API std::shared_ptr GetLogger(const std::string& name); + NGCORE_API void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name); + NGCORE_API void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger); + NGCORE_API void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger); + NGCORE_API void ClearLoggingSinks(const std::string& logger); + NGCORE_API void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger); +} // namespace ngcore + +#endif // NETGEN_CORE_LOGGING_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 1c8fa591..ea7f8eab 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -2,6 +2,7 @@ #define NETGEN_CORE_NGCORE_HPP #include "archive.hpp" +#include "logging.hpp" #include "version.hpp" #endif // NETGEN_CORE_NGCORE_HPP diff --git a/libsrc/core/ngcore_api.hpp b/libsrc/core/ngcore_api.hpp index c08d0ac9..5c65cf3a 100644 --- a/libsrc/core/ngcore_api.hpp +++ b/libsrc/core/ngcore_api.hpp @@ -5,8 +5,8 @@ #define NGCORE_API_EXPORT __declspec(dllexport) #define NGCORE_API_IMPORT __declspec(dllimport) #else - #define NGCORE_API_EXPORT - #define NGCORE_API_IMPORT + #define NGCORE_API_EXPORT __attribute__((visibility("default"))) + #define NGCORE_API_IMPORT __attribute__((visibility("default"))) #endif #ifdef NGCORE_EXPORTS diff --git a/libsrc/core/python_ngcore.cpp b/libsrc/core/python_ngcore.cpp new file mode 100644 index 00000000..b7624e43 --- /dev/null +++ b/libsrc/core/python_ngcore.cpp @@ -0,0 +1,30 @@ + +#include + +#include "logging.hpp" + +namespace py = pybind11; +using namespace ngcore; + +PYBIND11_MODULE(pyngcore, m) // NOLINT +{ + py::enum_(m, "LOG_LEVEL", "Logging level") + .value("Trace", spdlog::level::trace) + .value("Debug", spdlog::level::debug) + .value("Info", spdlog::level::info) + .value("Warn", spdlog::level::warn) + .value("Error", spdlog::level::err) + .value("Critical", spdlog::level::critical) + .value("Off", spdlog::level::off); + + m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="", + "Set logging level, if name is given only to the specific logger, else set the global logging level"); + m.def("AddFileSink", &AddFileSink, py::arg("filename"), py::arg("level"), py::arg("logger")="", + "Add File sink, either only to logger specified or globally to all loggers"); + m.def("AddConsoleSink", &AddConsoleSink, py::arg("level"), py::arg("logger")="", + "Add console output for specific logger or all if none given"); + m.def("ClearLoggingSinks", &ClearLoggingSinks, py::arg("logger")="", + "Clear sinks of specific logger, or all if none given"); + m.def("FlushOnLoggingLevel", &FlushOnLoggingLevel, py::arg("level"), py::arg("logger")="", + "Flush every message with level at least `level` for specific logger or all loggers if none given."); +} diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index 00c59ea2..39b63d4c 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -6,6 +6,10 @@ add_library(gen OBJECT mpi_interface.cpp gzstream.cpp ) +if(NOT WIN32) + target_link_libraries(gen ngcore) +endif(NOT WIN32) + set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) diff --git a/libsrc/gprim/CMakeLists.txt b/libsrc/gprim/CMakeLists.txt index 3957476a..ac4b8f11 100644 --- a/libsrc/gprim/CMakeLists.txt +++ b/libsrc/gprim/CMakeLists.txt @@ -3,6 +3,9 @@ add_library(gprim OBJECT adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp ) +if(NOT WIN32) + target_link_libraries(gprim ngcore) +endif(NOT WIN32) set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) diff --git a/libsrc/linalg/CMakeLists.txt b/libsrc/linalg/CMakeLists.txt index a5a5a4f2..9f35d751 100644 --- a/libsrc/linalg/CMakeLists.txt +++ b/libsrc/linalg/CMakeLists.txt @@ -4,6 +4,10 @@ add_library( la OBJECT set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) +if(NOT WIN32) + target_link_libraries(la ngcore) +endif(NOT WIN32) + install(FILES densemat.hpp linalg.hpp opti.hpp polynomial.hpp vector.hpp diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 6360174a..d349dfcf 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -506,7 +506,6 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) ) */ - .def("__str__", &ToString) .def_property_readonly("_timestamp", &Mesh::GetTimeStamp) .def("Load", FunctionPointer ([](Mesh & self, const string & filename) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index 831a3875..a244e85b 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -9,7 +9,7 @@ if(USE_GUI) endif(USE_GUI) if(NOT WIN32) - target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) + target_link_libraries( occ ngcore ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) install( TARGETS occ ${NG_INSTALL_DIR}) if (USE_GUI) target_link_libraries( occvis occ ) diff --git a/libsrc/stlgeom/CMakeLists.txt b/libsrc/stlgeom/CMakeLists.txt index 3620c496..7b87a649 100644 --- a/libsrc/stlgeom/CMakeLists.txt +++ b/libsrc/stlgeom/CMakeLists.txt @@ -4,8 +4,7 @@ add_library(stl ${NG_LIB_TYPE} ) if(NOT WIN32) - target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) - target_link_libraries( stl ${PYTHON_LIBRARIES}) + target_link_libraries( stl ngcore mesh ${PYTHON_LIBRARIES}) install( TARGETS stl ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/libsrc/visualization/CMakeLists.txt b/libsrc/visualization/CMakeLists.txt index 8f803d92..f1c82976 100644 --- a/libsrc/visualization/CMakeLists.txt +++ b/libsrc/visualization/CMakeLists.txt @@ -10,7 +10,7 @@ endif(USE_GUI) add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES}) if(NOT WIN32) - target_link_libraries( visual ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) + target_link_libraries( visual ngcore ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) install( TARGETS visual ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/tests/build_nospdlog.sh b/tests/build_nospdlog.sh new file mode 100644 index 00000000..2fedbef2 --- /dev/null +++ b/tests/build_nospdlog.sh @@ -0,0 +1,8 @@ +cd +mkdir -p build/netgen +cd build/netgen +cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_SPDLOG=OFF -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang +make -j12 +make install + diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index fc0ebe41..58386884 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -3,8 +3,7 @@ if(ENABLE_UNIT_TESTS) add_custom_target(unit_tests) # Build catch_main test object -message("netgen include dir = ${NETGEN_INCLUDE_DIR_ABSOLUTE} --------------------------------------") -include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include}) +include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR}) add_library(catch_main STATIC main.cpp) set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) add_dependencies(unit_tests catch_main) @@ -15,11 +14,7 @@ add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_ macro(add_unit_test name sources) add_executable(test_${name} ${sources} ) - if (WIN32) - target_link_libraries(test_${name} ngcore catch_main) - else(WIN32) - target_link_libraries(test_${name} ngcore catch_main) - endif(WIN32) + target_link_libraries(test_${name} ngcore catch_main) add_dependencies(unit_tests test_${name}) add_test(NAME unit_${name} COMMAND test_${name}) From 8e53eb46bb945fe46a060cdc7c23a2729c0b387d Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 28 Dec 2018 15:52:51 +0100 Subject: [PATCH 02/28] fix archive version for pickling --- libsrc/core/archive.hpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index aa6537d2..05766a14 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -97,23 +97,21 @@ namespace ngcore { const bool is_output; // how many different shared_ptr/pointer have been (un)archived - int shared_ptr_count, ptr_count; + int shared_ptr_count{0}, ptr_count{0}; // maps for archived shared pointers and pointers - std::map shared_ptr2nr, ptr2nr; + std::map shared_ptr2nr{}, ptr2nr{}; // vectors for storing the unarchived (shared) pointers - std::vector> nr2shared_ptr; - std::vector nr2ptr; + std::vector> nr2shared_ptr{}; + std::vector nr2ptr{}; protected: bool shallow_to_python = false; - // version map is only used in InArchives - std::map version_map; - std::shared_ptr logger; + std::map version_map = GetLibraryVersions(); + std::shared_ptr logger = GetLogger("Archive"); public: Archive() = delete; Archive(const Archive&) = delete; Archive(Archive&&) = delete; - Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), - ptr_count(0), logger(GetLogger("Archive")) { ; } + Archive (bool ais_output) : is_output(ais_output) { ; } virtual ~Archive() { ; } @@ -152,8 +150,8 @@ namespace ngcore bool Output () const { return is_output; } bool Input () const { return !is_output; } - virtual const VersionInfo& GetVersion(const std::string& library) - { return GetLibraryVersions()[library]; } + const VersionInfo& GetVersion(const std::string& library) + { return version_map[library]; } // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; @@ -166,7 +164,7 @@ namespace ngcore virtual Archive & operator & (std::string & str) = 0; virtual Archive & operator & (char *& str) = 0; - virtual Archive & operator & (VersionInfo & version) + Archive & operator & (VersionInfo & version) { if(Output()) (*this) << version.to_string(); @@ -706,9 +704,6 @@ namespace ngcore BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } - const VersionInfo& GetVersion(const std::string& library) override - { return version_map[library]; } - using Archive::operator&; Archive & operator & (double & d) override { Read(d); return *this; } @@ -824,9 +819,6 @@ namespace ngcore TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} - const VersionInfo& GetVersion(const std::string& library) override - { return version_map[library]; } - using Archive::operator&; Archive & operator & (double & d) override { *stream >> d; return *this; } @@ -918,6 +910,7 @@ namespace ngcore lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); stream = std::make_shared(); *this & GetLibraryVersions(); + lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); return lst; } }; From c000160f9227aa75186d83c8d94a6b7b39e9508e Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 28 Dec 2018 15:54:04 +0100 Subject: [PATCH 03/28] exceptions in ngcore --- libsrc/core/.clang-tidy | 2 +- libsrc/core/CMakeLists.txt | 1 + libsrc/core/archive.hpp | 38 ++++++++++----------- libsrc/core/exception.hpp | 68 ++++++++++++++++++++++++++++++++++++++ libsrc/core/ngcore.hpp | 1 + 5 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 libsrc/core/exception.hpp diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 290188fb..806e0616 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 16cec927..8f6cb5ad 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -26,6 +26,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp + exception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 05766a14..30c1023c 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -7,13 +7,13 @@ #include // for function #include // for map #include // for shared_ptr -#include // for runtime_error #include // for string #include // for declval, enable_if, false_type, is_co... #include // for type_info #include // for move, swap, pair #include // for vector +#include "exception.hpp" // for UnreachableCodeException, Exception #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API, unlikely #include "type_traits.hpp" // for all_of_tmpl @@ -37,7 +37,7 @@ namespace ngcore // create new pointer of type T if it is default constructible, else throw template T* constructIfPossible_impl(Rest... /*unused*/) - { throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } + { throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } template::value>::type> T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT @@ -140,9 +140,9 @@ namespace ngcore #ifdef NETGEN_PYTHON virtual void ShallowOutPython(const pybind11::object& /*unused*/) - { throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); } + { throw UnreachableCodeException{}; } virtual pybind11::object ShallowInPython() - { throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } + { throw UnreachableCodeException{}; } #endif // NETGEN_PYTHON Archive& operator=(const Archive&) = delete; @@ -284,9 +284,9 @@ namespace ngcore NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*ptr).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*ptr).name()) + + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get())) @@ -404,9 +404,9 @@ namespace ngcore NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*p).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); if(reg_ptr != static_cast(p)) { @@ -427,8 +427,8 @@ namespace ngcore return (*this) << -1 & (*p); } else - throw std::runtime_error(std::string("Archive error: Class ") + - Demangle(typeid(*p).name()) + " does not provide a default constructor!"); + throw Exception(std::string("Archive error: Class ") + + Demangle(typeid(*p).name()) + " does not provide a default constructor!"); else { // if a pointer to a base class is archived, the class hierarchy must be registered @@ -436,9 +436,9 @@ namespace ngcore // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it if(!IsRegistered(Demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*p).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } @@ -552,11 +552,11 @@ namespace ngcore { static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/) { - throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); + throw Exception("Upcast not successful, some classes are not registered properly for archiving!"); } static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) { - throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); + throw Exception("Downcast not successful, some classes are not registered properly for archiving!"); } }; @@ -568,7 +568,7 @@ namespace ngcore try { return GetArchiveRegister(Demangle(typeid(B1).name())). upcaster(ti, static_cast(dynamic_cast(p))); } - catch(std::exception&) + catch(const Exception&) { return Caster::tryUpcast(ti, p); } } @@ -581,7 +581,7 @@ namespace ngcore return dynamic_cast(static_cast(GetArchiveRegister(Demangle(typeid(B1).name())). downcaster(ti, p))); } - catch(std::exception&) + catch(const Exception&) { return Caster::tryDowncast(ti, p); } diff --git a/libsrc/core/exception.hpp b/libsrc/core/exception.hpp new file mode 100644 index 00000000..248a180f --- /dev/null +++ b/libsrc/core/exception.hpp @@ -0,0 +1,68 @@ +#ifndef NETGEN_CORE_EXCEPTION_HPP +#define NETGEN_CORE_EXCEPTION_HPP + +#include // for stringstream +#include // for exception +#include // for string + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + // Exception for code that shouldn't be executed + class NGCORE_API UnreachableCodeException : public std::exception + { + const char* what() const noexcept override + { + return "Shouldn't get here, something went wrong!"; + } + }; + + // Default exception class + class NGCORE_API Exception : public std::exception + { + /// a verbal description of the exception + std::string m_what; + public: + Exception() = default; + Exception(const Exception&) = default; + Exception(Exception&&) = default; + Exception(const std::string& s) : m_what(s) {} + Exception(const char* s) : m_what(s) {} + ~Exception() override = default; + + Exception& operator =(const Exception&) = default; + Exception& operator =(Exception&&) noexcept = default; + + /// append string to description + Exception & Append (const std::string & s) { m_what += s; return *this; } + /// append string to description + Exception & Append (const char * s) { m_what += s; return *this; } + + /// verbal description of exception + const std::string & What() const { return m_what; } + + /// implement virtual function of std::exception + const char* what() const noexcept override { return m_what.c_str(); } + }; + + // Out of Range exception + class NGCORE_API RangeException : public Exception + { + public: + /// where it occurs, index, minimal and maximal indices + RangeException (const std::string & where, + int ind, int imin, int imax) : Exception("") + { + std::stringstream str; + str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; + Append (str.str()); + } + }; + + // Exception used if no simd implementation is available to fall back to standard evaluation + class NGCORE_API ExceptionNOSIMD : public Exception + { public: using Exception::Exception; }; +} // namespace ngcore + +#endif // NETGEN_CORE_EXCEPTION_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index ea7f8eab..b345a114 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -2,6 +2,7 @@ #define NETGEN_CORE_NGCORE_HPP #include "archive.hpp" +#include "exception.hpp" #include "logging.hpp" #include "version.hpp" From 5602322e9449e3f03f0f907e3da72a2cbee9a92c Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 2 Jan 2019 16:30:55 +0100 Subject: [PATCH 04/28] add RangeException, NETGEN_CHECK_RANGE macro --- CMakeLists.txt | 1 + cmake/SuperBuild.cmake | 1 + libsrc/core/CMakeLists.txt | 8 +++++++- libsrc/core/exception.hpp | 24 +++++++++++++++++++++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d2e6a9f..29a73670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) option( USE_SPDLOG "Enable spd log logging" ON) option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF) +option( CHECK_RANGE "Check array range access, automatically enabled if built in debug mode" OFF) option( USE_SUPERBUILD "use ccache" ON) diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 6e7fabd7..646de088 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -144,6 +144,7 @@ set_vars( NETGEN_CMAKE_ARGS ENABLE_CPP_CORE_GUIDELINES_CHECK USE_SPDLOG DEBUG_LOG + CHECK_RANGE ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 8f6cb5ad..805808d5 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,11 +1,17 @@ -add_library(ngcore SHARED archive.cpp logging.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp flags.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) target_compile_options(ngcore PRIVATE -fvisibility=hidden) endif(NOT WIN32) +target_compile_definitions(ngcore PUBLIC $<$:NETGEN_ENABLE_CHECK_RANGE>) + +if(CHECK_RANGE) + target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE) +endif(CHECK_RANGE) + if(USE_SPDLOG) include_directories(${SPDLOG_INCLUDE_DIR}) install(DIRECTORY ${SPDLOG_INCLUDE_DIR} diff --git a/libsrc/core/exception.hpp b/libsrc/core/exception.hpp index 248a180f..35359e65 100644 --- a/libsrc/core/exception.hpp +++ b/libsrc/core/exception.hpp @@ -51,13 +51,21 @@ namespace ngcore { public: /// where it occurs, index, minimal and maximal indices - RangeException (const std::string & where, + RangeException (const std::string & where, int ind, int imin, int imax) : Exception("") { std::stringstream str; str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; Append (str.str()); } + + template + RangeException(const std::string& where, const T& value) + { + std::stringstream str; + str << where << " called with wrong value " << value << "\n"; + Append(str.str()); + } }; // Exception used if no simd implementation is available to fall back to standard evaluation @@ -65,4 +73,18 @@ namespace ngcore { public: using Exception::Exception; }; } // namespace ngcore +#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x +#define NETGEN_CORE_NGEXEPTION_STR(x) NETGEN_CORE_NGEXEPTION_STR_HELPER(x) + +// Convenience macro to append file name and line of exception origin to the string +#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s)) + +#ifdef NETGEN_ENABLE_CHECK_RANGE +#define NETGEN_CHECK_RANGE(value, min, max) \ + { if ((value)<(min) || (value)>=(max)) \ + throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", (value), (min), (max)); } +#else // NETGEN_ENABLE_CHECK_RANGE +#define NETGEN_CHECK_RANGE(value, min, max) +#endif // NETGEN_ENABLE_CHECK_RANGE + #endif // NETGEN_CORE_EXCEPTION_HPP From a4f4b6c1be95ea11d580098b0f447fc0b9976785 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 2 Jan 2019 16:32:09 +0100 Subject: [PATCH 05/28] fix cmake file for ngcore --- libsrc/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 805808d5..01479a61 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ngcore SHARED archive.cpp logging.cpp flags.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) From f88cc77cfea66f651475f795993566c73c3210cf Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 2 Jan 2019 18:21:52 +0100 Subject: [PATCH 06/28] move SymbolTable to ngcore --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 28 ++++++ libsrc/core/ngcore.hpp | 1 + libsrc/core/symboltable.hpp | 144 ++++++++++++++++++++++++++++++ libsrc/csg/csgeom.cpp | 20 ++--- libsrc/csg/csgeom.hpp | 10 +-- libsrc/csg/solid.cpp | 16 ++-- libsrc/csg/solid.hpp | 2 +- libsrc/general/CMakeLists.txt | 4 +- libsrc/general/flags.cpp | 20 ++--- libsrc/general/flags.hpp | 10 +-- libsrc/general/myadt.hpp | 1 - libsrc/general/symbolta.cpp | 52 ----------- libsrc/general/symbolta.hpp | 163 ---------------------------------- libsrc/meshing/meshclass.cpp | 20 ++--- libsrc/meshing/meshclass.hpp | 4 +- ng/ngpkg.cpp | 6 +- tests/catch/CMakeLists.txt | 10 +-- tests/catch/symboltable.cpp | 64 +++++++++++++ 19 files changed, 299 insertions(+), 278 deletions(-) create mode 100644 libsrc/core/symboltable.hpp delete mode 100644 libsrc/general/symbolta.cpp delete mode 100644 libsrc/general/symbolta.hpp create mode 100644 tests/catch/symboltable.cpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 01479a61..b75e7582 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -32,7 +32,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp - exception.hpp + exception.hpp symboltable.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 30c1023c..11d4ae71 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -205,6 +205,34 @@ namespace ngcore Do(&v[0], size); return (*this); } + + // vector has special implementation (like a bitarray) therefore + // it needs a special overload (this could probably be more efficient, but we + // don't use it that often anyway) + template<> + Archive& operator& (std::vector& v) + { + size_t size; + if(Output()) + size = v.size(); + (*this) & size; + if(Input()) + { + v.resize(size); + bool b; + for(size_t i=0; i Archive& operator& (std::map& map) { diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index b345a114..153a0e6c 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -4,6 +4,7 @@ #include "archive.hpp" #include "exception.hpp" #include "logging.hpp" +#include "symboltable.hpp" #include "version.hpp" #endif // NETGEN_CORE_NGCORE_HPP diff --git a/libsrc/core/symboltable.hpp b/libsrc/core/symboltable.hpp new file mode 100644 index 00000000..53c07dd4 --- /dev/null +++ b/libsrc/core/symboltable.hpp @@ -0,0 +1,144 @@ +#ifndef NETGEN_CORE_SYMBOLTABLE_HPP +#define NETGEN_CORE_SYMBOLTABLE_HPP + +#include +#include +#include + +#include "archive.hpp" +#include "exception.hpp" +#include "ngcore_api.hpp" + +namespace ngcore +{ + /** + A symbol table. + + The symboltable provides a mapping from string identifiers + to the generic type T. The strings are copied. + Complexity by name access is linear, by index is constant. + */ + template + class NGCORE_API SymbolTable + { + std::vector names; + std::vector data; + public: + using value_type = T; + using reference = typename std::vector::reference; + using const_reference = typename std::vector::const_reference; + + /// Creates a symboltable + SymbolTable () = default; + SymbolTable (const SymbolTable &) = default; + SymbolTable (SymbolTable &&) noexcept = default; + + ~SymbolTable() = default; + + SymbolTable& operator=(const SymbolTable&) = default; + SymbolTable& operator=(SymbolTable&&) = default; + + template + auto DoArchive(Archive& ar) -> typename std::enable_if, void>::type + { + ar & names & data; + } + + /// INDEX of symbol name, throws exception if unused + NGCORE_API size_t Index (const std::string & name) const + { + for (size_t i = 0; i < names.size(); i++) + if (names[i] == name) return i; + throw RangeException("SymbolTable", name); + } + + /// Index of symbol name, returns -1 if unused + NGCORE_API int CheckIndex (const std::string & name) const + { + for (int i = 0; i < names.size(); i++) + if (names[i] == name) return i; + return -1; + } + + /// number of identifiers + size_t Size() const + { + return data.size(); + } + + /// Returns reference to element. exception for unused identifier + reference operator[] (const std::string & name) + { + return data[Index (name)]; + } + + const_reference operator[] (const std::string & name) const + { + return data[Index (name)]; + } + + /// Returns reference to i-th element, range check only in debug build + reference operator[] (size_t i) + { + NETGEN_CHECK_RANGE(i, 0, data.size()); + return data[i]; + } + + /// Returns const reference to i-th element, range check only in debug build + const_reference operator[] (size_t i) const + { + NETGEN_CHECK_RANGE(i, 0, data.size()); + return data[i]; + } + + /// Returns name of i-th element, range check only in debug build + const std::string & GetName (size_t i) const + { + NETGEN_CHECK_RANGE(i, 0, names.size()); + return names[i]; + } + + /// Associates el to the string name, overrides if name is used + void Set (const std::string & name, const T & el) + { + int i = CheckIndex (name); + if (i >= 0) + data[i] = el; + else + { + data.push_back(el); + names.push_back(name); + } + } + + bool Used (const std::string & name) const + { + return CheckIndex(name) >= 0; + } + + /// Deletes symboltable + inline void DeleteAll () + { + names.clear(); + data.clear(); + } + + // Adds all elements from other symboltable + SymbolTable& Update(const SymbolTable& tbl2) + { + for (size_t i = 0; i < tbl2.Size(); i++) + Set (tbl2.GetName(i), tbl2[i]); + return *this; + } + }; + + template + std::ostream & operator<< (std::ostream & ost, const SymbolTable & st) + { + for (int i = 0; i < st.Size(); i++) + ost << st.GetName(i) << " : " << st[i] << std::endl; + return ost; + } +} // namespace ngcore + +#endif // NETGEN_CORE_SYMBOLTABLE_HPP diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 87cae1b4..4aebe271 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -562,7 +562,7 @@ namespace netgen const Surface * CSGeometry :: GetSurface (const char * name) const { if (surfaces.Used(name)) - return surfaces.Get(name); + return surfaces[name]; else return NULL; } @@ -585,7 +585,7 @@ namespace netgen Solid * oldsol = NULL; if (solids.Used (name)) - oldsol = solids.Get(name); + oldsol = solids[name]; solids.Set (name, sol); sol->SetName (name); @@ -605,7 +605,7 @@ namespace netgen const Solid * CSGeometry :: GetSolid (const char * name) const { if (solids.Used(name)) - return solids.Get(name); + return solids[name]; else return NULL; } @@ -616,8 +616,8 @@ namespace netgen const Solid * CSGeometry :: GetSolid (const string & name) const { - if (solids.Used(name.c_str())) - return solids.Get(name.c_str()); + if (solids.Used(name)) + return solids[name]; else return NULL; } @@ -637,15 +637,15 @@ namespace netgen const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const { - if (splinecurves2d.Used(name.c_str())) - return splinecurves2d.Get(name.c_str()); + if (splinecurves2d.Used(name)) + return splinecurves2d[name]; else return NULL; } const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const { - if (splinecurves3d.Used(name.c_str())) - return splinecurves3d.Get(name.c_str()); + if (splinecurves3d.Used(name)) + return splinecurves3d[name]; else return NULL; } @@ -721,7 +721,7 @@ namespace netgen void CSGeometry :: SetFlags (const char * solidname, const Flags & flags) { - Solid * solid = solids.Elem(solidname); + Solid * solid = solids[solidname]; Array surfind; int i; diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index f82407b4..40d90d51 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -102,7 +102,7 @@ namespace netgen { private: /// all surfaces - SYMBOLTABLE surfaces; + SymbolTable surfaces; public: /// primitive of surface @@ -112,12 +112,12 @@ namespace netgen Array delete_them; /// all named solids - SYMBOLTABLE solids; + SymbolTable solids; /// all 2d splinecurves - SYMBOLTABLE< SplineGeometry<2>* > splinecurves2d; + SymbolTable< SplineGeometry<2>* > splinecurves2d; /// all 3d splinecurves - SYMBOLTABLE< SplineGeometry<3>* > splinecurves3d; + SymbolTable< SplineGeometry<3>* > splinecurves3d; /// all top level objects: solids and surfaces Array toplevelobjects; @@ -203,7 +203,7 @@ namespace netgen const Solid * GetSolid (const string & name) const; int GetNSolids () const { return solids.Size(); } const Solid * GetSolid (int i) const { return solids[i]; } - const SYMBOLTABLE & GetSolids () const { return solids; } + const SymbolTable & GetSolids () const { return solids; } void SetSplineCurve (const char * name, SplineGeometry<2> * spl); diff --git a/libsrc/csg/solid.cpp b/libsrc/csg/solid.cpp index a7e5fff5..c61f4e39 100644 --- a/libsrc/csg/solid.cpp +++ b/libsrc/csg/solid.cpp @@ -419,9 +419,9 @@ namespace netgen - static Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE & solids); - static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE & solids); - static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE & solids); + static Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids); + static Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids); + static Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids); static void ReadString (istream & ist, char * str) { @@ -461,7 +461,7 @@ namespace netgen } - Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids) { // cout << "create expr" << endl; @@ -484,7 +484,7 @@ namespace netgen return s1; } - Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids) { // cout << "create term" << endl; @@ -508,7 +508,7 @@ namespace netgen return s1; } - Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids) { Solid * s1; char ch; @@ -533,7 +533,7 @@ namespace netgen } (*testout) << "get terminal " << str << endl; - s1 = solids.Get(str); + s1 = solids[str]; if (s1) { // cout << "primitive: " << str << endl; @@ -545,7 +545,7 @@ namespace netgen } - Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE & solids) + Solid * Solid :: CreateSolid (istream & ist, const SymbolTable & solids) { Solid * nsol = CreateSolidExpr (ist, solids); nsol = new Solid (ROOT, nsol); diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 4d620c04..193cb363 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -158,7 +158,7 @@ namespace netgen { return maxh; } void GetSolidData (ostream & ost, int first = 1) const; - static Solid * CreateSolid (istream & ist, const SYMBOLTABLE & solids); + static Solid * CreateSolid (istream & ist, const SymbolTable & solids); static BlockAllocator ball; diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index 39b63d4c..b65fee96 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -2,7 +2,7 @@ add_definitions(-DNGINTERFACE_EXPORTS) add_library(gen OBJECT array.cpp bitarray.cpp dynamicmem.cpp flags.cpp hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp - profiler.cpp seti.cpp sort.cpp spbita2d.cpp symbolta.cpp table.cpp + profiler.cpp seti.cpp sort.cpp spbita2d.cpp table.cpp mpi_interface.cpp gzstream.cpp ) @@ -19,7 +19,7 @@ install(FILES dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp - spbita2d.hpp stack.hpp symbolta.hpp table.hpp template.hpp + spbita2d.hpp stack.hpp table.hpp template.hpp gzstream.h DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel ) diff --git a/libsrc/general/flags.cpp b/libsrc/general/flags.cpp index e5916f87..993413ed 100644 --- a/libsrc/general/flags.cpp +++ b/libsrc/general/flags.cpp @@ -83,7 +83,7 @@ namespace netgen Flags :: GetStringFlag (const char * name, const char * def) const { if (strflags.Used (name)) - return strflags.Get(name); + return strflags[name]; else return def; } @@ -91,7 +91,7 @@ namespace netgen double Flags :: GetNumFlag (const char * name, double def) const { if (numflags.Used (name)) - return numflags.Get(name); + return numflags[name]; else return def; } @@ -99,7 +99,7 @@ namespace netgen const double * Flags :: GetNumFlagPtr (const char * name) const { if (numflags.Used (name)) - return & ((SYMBOLTABLE&)numflags).Elem(name); + return & ((SymbolTable&)numflags)[name]; else return NULL; } @@ -107,7 +107,7 @@ namespace netgen double * Flags :: GetNumFlagPtr (const char * name) { if (numflags.Used (name)) - return & ((SYMBOLTABLE&)numflags).Elem(name); + return & ((SymbolTable&)numflags)[name]; else return NULL; } @@ -122,7 +122,7 @@ namespace netgen Flags :: GetStringListFlag (const char * name) const { if (strlistflags.Used (name)) - return *strlistflags.Get(name); + return *strlistflags[name]; else { static Array dummy_array(0); @@ -134,7 +134,7 @@ namespace netgen Flags ::GetNumListFlag (const char * name) const { if (numlistflags.Used (name)) - return *numlistflags.Get(name); + return *numlistflags[name]; else { static Array dummy_array(0); @@ -170,9 +170,9 @@ namespace netgen ofstream outfile (filename); for (i = 1; i <= strflags.Size(); i++) - outfile << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + outfile << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) - outfile << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + outfile << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) outfile << defflags.GetName(i) << endl; } @@ -184,9 +184,9 @@ namespace netgen int i; for (i = 1; i <= strflags.Size(); i++) - ost << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + ost << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) - ost << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + ost << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) ost << defflags.GetName(i) << endl; } diff --git a/libsrc/general/flags.hpp b/libsrc/general/flags.hpp index e156d328..e7ba0382 100644 --- a/libsrc/general/flags.hpp +++ b/libsrc/general/flags.hpp @@ -19,15 +19,15 @@ namespace netgen class Flags { /// - SYMBOLTABLE strflags; + SymbolTable strflags; /// - SYMBOLTABLE numflags; + SymbolTable numflags; /// - SYMBOLTABLE defflags; + SymbolTable defflags; /// - SYMBOLTABLE*> strlistflags; + SymbolTable*> strlistflags; /// - SYMBOLTABLE*> numlistflags; + SymbolTable*> numlistflags; public: /// DLL_HEADER Flags (); diff --git a/libsrc/general/myadt.hpp b/libsrc/general/myadt.hpp index 601a3da0..7263d088 100644 --- a/libsrc/general/myadt.hpp +++ b/libsrc/general/myadt.hpp @@ -33,7 +33,6 @@ namespace netgen #include "hashtabl.hpp" -#include "symbolta.hpp" #include "bitarray.hpp" #include "flags.hpp" #include "spbita2d.hpp" diff --git a/libsrc/general/symbolta.cpp b/libsrc/general/symbolta.cpp deleted file mode 100644 index bd35ac7c..00000000 --- a/libsrc/general/symbolta.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************/ -/* File: symbolta.cc */ -/* Author: Joachim Schoeberl */ -/* Date: 01. Jun. 95 */ -/**************************************************************************/ - -/* - Abstract data type Symbol Table -*/ - -#include -#include - - -#ifndef FILE_SYMBOLTABLECC -#define FILE_SYMBOLTABLECC -// necessary for SGI ???? - - -namespace netgen -{ - //using namespace netgen; - - BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE () - { - ; - } - - - BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE() - { - DelNames(); - } - - - void BASE_SYMBOLTABLE :: DelNames() - { - for (int i = 0; i < names.Size(); i++) - delete [] names[i]; - names.SetSize (0); - } - - int BASE_SYMBOLTABLE :: Index (const char * name) const - { - if (!name) return 0; - for (int i = 0; i < names.Size(); i++) - if (strcmp (names[i], name) == 0) return i+1; - return 0; - } -} - -#endif diff --git a/libsrc/general/symbolta.hpp b/libsrc/general/symbolta.hpp deleted file mode 100644 index b599ea42..00000000 --- a/libsrc/general/symbolta.hpp +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef FILE_SYMBOLTA -#define FILE_SYMBOLTA - - -/**************************************************************************/ -/* File: symbolta.hh */ -/* Author: Joachim Schoeberl */ -/* Date: 01. Jun. 95 */ -/**************************************************************************/ - -namespace netgen -{ - -/** - Base class for the generic SYMBOLTABLE. - An array of identifiers is maintained. -*/ -class DLL_HEADER BASE_SYMBOLTABLE -{ -protected: - /// identifiers - Array names; - -public: - /// Constructor - BASE_SYMBOLTABLE (); - /// - ~BASE_SYMBOLTABLE (); - /// - void DelNames (); - /// Index of symbol name, returns 0 if not used. - int Index (const char * name) const; -}; - - -/** - Abstract data type Symbol Table. - - To a string an value of the generic type T is associated. - The string is not copied into the symbol table class! -*/ -template -class SYMBOLTABLE : public BASE_SYMBOLTABLE -{ -private: - /// Associated data - Array data; - -public: - /// Creates a symboltable - inline SYMBOLTABLE (); - /// Returns size of symboltable - inline INDEX Size() const; - /// Returns reference to element, error if not used - inline T & Elem (const char * name); - /// Returns reference to i-th element - inline T & Elem (int i) - { return data.Elem(i); } - /// Returns element, error if not used - inline const T & Get (const char * name) const; - /// Returns i-th element - inline const T & Get (int i) const; - /// Returns name of i-th element - inline const char* GetName (int i) const; - /// Associates el to the string name, overrides if name is used - inline void Set (const char * name, const T & el); - /// Checks whether name is used - inline bool Used (const char * name) const; - /// Deletes symboltable - inline void DeleteAll (); - - void DoArchive(Archive& archive) { archive & names & data;} - - inline T & operator[] (int i) - { return data[i]; } - inline const T & operator[] (int i) const - { return data[i]; } - -private: - /// Prevents from copying symboltable by pointer assignment - SYMBOLTABLE & operator= (SYMBOLTABLE &); -}; - - - - -template -inline SYMBOLTABLE :: SYMBOLTABLE () -{ - ; -} - - -template -inline INDEX SYMBOLTABLE :: Size() const -{ - return data.Size(); -} - -template -inline T & SYMBOLTABLE :: Elem (const char * name) -{ - int i = Index (name); - if (i) - return data.Elem (i); - else - return data.Elem(1); -} - -template -inline const T & SYMBOLTABLE :: Get (const char * name) const -{ - int i; - i = Index (name); - if (i) - return data.Get(i); - else - return data.Get(1); -} - -template -inline const T & SYMBOLTABLE :: Get (int i) const -{ - return data.Get(i); -} - -template -inline const char* SYMBOLTABLE :: GetName (int i) const -{ - return names.Get(i); -} - -template -inline void SYMBOLTABLE :: Set (const char * name, const T & el) -{ - int i; - i = Index (name); - if (i) - data.Set(i, el); - else - { - data.Append (el); - char * hname = new char [strlen (name) + 1]; - strcpy (hname, name); - names.Append (hname); - } -} - -template -inline bool SYMBOLTABLE :: Used (const char * name) const -{ - return (Index(name)) ? true : false; -} - -template -inline void SYMBOLTABLE :: DeleteAll () -{ - DelNames(); - data.DeleteAll(); -} - -} -#endif diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index ebf75ff4..9e96a055 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -6016,7 +6016,7 @@ namespace netgen void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_int.Used(id)) - delete userdata_int.Get(id); + delete userdata_int[id]; Array * newdata = new Array(data); @@ -6026,10 +6026,10 @@ namespace netgen { if(userdata_int.Used(id)) { - if(data.Size() < (*userdata_int.Get(id)).Size()+shift) - data.SetSize((*userdata_int.Get(id)).Size()+shift); - for(int i=0; i<(*userdata_int.Get(id)).Size(); i++) - data[i+shift] = (*userdata_int.Get(id))[i]; + if(data.Size() < (*userdata_int[id]).Size()+shift) + data.SetSize((*userdata_int[id]).Size()+shift); + for(int i=0; i<(*userdata_int[id]).Size(); i++) + data[i+shift] = (*userdata_int[id])[i]; return true; } else @@ -6041,7 +6041,7 @@ namespace netgen void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_double.Used(id)) - delete userdata_double.Get(id); + delete userdata_double[id]; Array * newdata = new Array(data); @@ -6051,10 +6051,10 @@ namespace netgen { if(userdata_double.Used(id)) { - if(data.Size() < (*userdata_double.Get(id)).Size()+shift) - data.SetSize((*userdata_double.Get(id)).Size()+shift); - for(int i=0; i<(*userdata_double.Get(id)).Size(); i++) - data[i+shift] = (*userdata_double.Get(id))[i]; + if(data.Size() < (*userdata_double[id]).Size()+shift) + data.SetSize((*userdata_double[id]).Size()+shift); + for(int i=0; i<(*userdata_double[id]).Size(); i++) + data[i+shift] = (*userdata_double[id])[i]; return true; } else diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index fe72de2a..956946ce 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -132,8 +132,8 @@ namespace netgen /// mesh access semaphors. NgMutex majormutex; - SYMBOLTABLE< Array* > userdata_int; - SYMBOLTABLE< Array* > userdata_double; + SymbolTable< Array* > userdata_int; + SymbolTable< Array* > userdata_double; mutable Array< Point3d > pointcurves; diff --git a/ng/ngpkg.cpp b/ng/ngpkg.cpp index a80b0ea6..5b67637a 100644 --- a/ng/ngpkg.cpp +++ b/ng/ngpkg.cpp @@ -1840,9 +1840,9 @@ namespace netgen - SYMBOLTABLE & GetVisualizationScenes () + SymbolTable & GetVisualizationScenes () { - static SYMBOLTABLE vss; + static SymbolTable vss; return vss; } @@ -1860,7 +1860,7 @@ namespace netgen vs = &vscross; if (GetVisualizationScenes().Used(vismode)) { - vs = GetVisualizationScenes().Get(vismode); + vs = GetVisualizationScenes()[vismode]; } else if (vismode) { diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index 58386884..f0a25744 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -19,14 +19,14 @@ macro(add_unit_test name sources) add_dependencies(unit_tests test_${name}) add_test(NAME unit_${name} COMMAND test_${name}) set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built) + + if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") + endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) endmacro() add_unit_test(archive archive.cpp) +add_unit_test(symboltable symboltable.cpp) add_unit_test(version version.cpp) -if(ENABLE_CPP_CORE_GUIDELINES_CHECK) - set_target_properties(test_archive PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") - set_target_properties(test_version PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") -endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) - endif(ENABLE_UNIT_TESTS) diff --git a/tests/catch/symboltable.cpp b/tests/catch/symboltable.cpp new file mode 100644 index 00000000..5e6ecd2c --- /dev/null +++ b/tests/catch/symboltable.cpp @@ -0,0 +1,64 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + +TEST_CASE("Symboltable") +{ + SymbolTable table; + CHECK_THROWS_AS(table["test"], RangeException); + table.Set("first", 1); + CHECK(table["first"] == 1); + table["first"] = 2; + CHECK(table["first"] == 2); + auto index = table.Index("first"); + CHECK(index == 0); + CHECK(table[index] == 2); + table[index] = 3; + CHECK(table["first"] == 3); +#ifndef NDEBUG + int a; + CHECK_THROWS_AS(a = table[5], RangeException); + CHECK_THROWS_AS(table.GetName(5), RangeException); +#endif + CHECK(table.Used("first")); + CHECK(!table.Used("second")); + SymbolTable another; + another.Set("first", 1); + another.Set("second", 2); + table.Update(another); + CHECK(table["first"] == 1); + CHECK(table["second"] == 2); + std::stringstream s; + s << table; + CHECK(s.str() == "first : 1\nsecond : 2\n"); + auto ss = std::make_shared(); + BinaryOutArchive ao(ss); + ao & table; + ao.FlushBuffer(); + BinaryInArchive ai(ss); + SymbolTable read; + ai & read; + for(size_t i = 0; i is special because of vector is special... + SymbolTable btable; + btable.Set("true", true); + btable.Set("false", false); + CHECK(btable[0]); + CHECK(!btable[1]); + CHECK(btable["true"]); + CHECK(!btable["false"]); + ao & btable; + ao.FlushBuffer(); + SymbolTable bread; + ai & bread; + CHECK(bread["true"]); + CHECK(!bread["false"]); +} From 678b4497c2bc230de4e00e43e89fc6d2b0055c53 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 2 Jan 2019 18:38:03 +0100 Subject: [PATCH 07/28] Paje tracing --- libsrc/core/CMakeLists.txt | 4 +- libsrc/core/archive.cpp | 10 - libsrc/core/archive.hpp | 4 +- libsrc/core/logging.hpp | 53 ++- libsrc/core/ngcore_api.hpp | 24 +- libsrc/core/paje_trace.cpp | 659 +++++++++++++++++++++++++++++++++++++ libsrc/core/paje_trace.hpp | 215 ++++++++++++ libsrc/core/utils.cpp | 20 ++ libsrc/core/utils.hpp | 23 ++ 9 files changed, 973 insertions(+), 39 deletions(-) create mode 100644 libsrc/core/paje_trace.cpp create mode 100644 libsrc/core/paje_trace.hpp create mode 100644 libsrc/core/utils.cpp create mode 100644 libsrc/core/utils.hpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index b75e7582..3e10f58d 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ngcore SHARED archive.cpp logging.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) @@ -32,7 +32,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp - exception.hpp symboltable.hpp + exception.hpp symboltable.hpp paje_trace.hpp utils.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 64789904..9d7f2cd5 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -19,16 +19,6 @@ namespace ngcore void SetLibraryVersion(const std::string& library, const VersionInfo& version) { library_versions[library] = version; } -#ifdef WIN32 - // windows does demangling in typeid(T).name() - std::string Demangle(const char* typeinfo) { return typeinfo; } -#else - std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, - nullptr, - nullptr, - &status); } -#endif - // clang-tidy should ignore this static object static std::unique_ptr> type_register; // NOLINT const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 11d4ae71..04915cbc 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -15,8 +15,9 @@ #include "exception.hpp" // for UnreachableCodeException, Exception #include "logging.hpp" // for logger -#include "ngcore_api.hpp" // for NGCORE_API, unlikely +#include "ngcore_api.hpp" // for NGCORE_API #include "type_traits.hpp" // for all_of_tmpl +#include "utils.hpp" // for Demangle, unlikely #include "version.hpp" // for VersionInfo #ifdef NETGEN_PYTHON @@ -28,7 +29,6 @@ namespace ngcore // Libraries using this archive can store their version here to implement backwards compatibility NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library); NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version); - NGCORE_API std::string Demangle(const char* typeinfo); class NGCORE_API Archive; diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index 8952a5f6..e0e3efd6 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -26,23 +26,6 @@ namespace spdlog { // Dummys if Netgen is compiled with USE_SPDLOG=OFF. - class logger - { - public: - template - void trace(const T& /*unused*/) {} - template - void debug(const T& /*unused*/) {} - template - void info(const T& text) { std::cout << text << std::endl; } - template - void warn(const T& text) { std::cout << text << std::endl; } - template - void error(const T& text) { std::cout << text << std::endl; } - template - void critical(const T& text) { std::cout << text << std::endl; } - }; - namespace level { enum level_enum @@ -57,6 +40,42 @@ namespace spdlog }; } // namespace level + class logger + { + public: + template + void log_helper( T t) { std::clog << t; } + + template + void log_helper( T t, Args ... args) + { + std::clog << t; + log_helper(args...); + std::clog << ", "; + } + + template + void log( level::level_enum level, const char* fmt, Args ... args) + { + std::clog << level << ": " << fmt << "\t Arguments: "; + log_helper(args...); + std::clog << "\n"; + } + + template + void trace( const char* fmt, Args ... args) { log(level::level_enum::trace, fmt, args...); } + template + void debug( const char* fmt, Args ... args) { log(level::level_enum::debug, fmt, args...); } + template + void info( const char* fmt, Args ... args) { log(level::level_enum::info, fmt, args...); } + template + void warn( const char* fmt, Args ... args) { log(level::level_enum::warn, fmt, args...); } + template + void error( const char* fmt, Args ... args) { log(level::level_enum::err, fmt, args...); } + template + void critical( const char* fmt, Args ... args) { log(level::level_enum::critical, fmt, args...); } + }; + namespace sinks { class sink {}; diff --git a/libsrc/core/ngcore_api.hpp b/libsrc/core/ngcore_api.hpp index 5c65cf3a..a84a1381 100644 --- a/libsrc/core/ngcore_api.hpp +++ b/libsrc/core/ngcore_api.hpp @@ -15,15 +15,23 @@ #define NGCORE_API NGCORE_API_IMPORT #endif -namespace ngcore -{ -#if defined(__GNUC__) - inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } - inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } +#ifdef __INTEL_COMPILER + #ifdef WIN32 + #define NETGEN_INLINE __forceinline inline + #define NETGEN_LAMBDA_INLINE + #else + #define NETGEN_INLINE __forceinline inline + #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) + #endif #else - inline bool likely (bool x) { return x; } - inline bool unlikely (bool x) { return x; } + #ifdef __GNUC__ + #define NETGEN_INLINE __attribute__ ((__always_inline__)) inline + #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) + #define NETGEN_VLA + #else + #define NETGEN_INLINE inline + #define NETGEN_LAMBDA_INLINE + #endif #endif -} // namespace ngcore #endif // NETGEN_CORE_NGCORE_API_HPP diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp new file mode 100644 index 00000000..2742d25e --- /dev/null +++ b/libsrc/core/paje_trace.cpp @@ -0,0 +1,659 @@ +#include +#include +#include +#include +#include +#include + +#include "archive.hpp" // for Demangle +#include "paje_trace.hpp" + +static constexpr int MAX_TRACE_LINE_SIZE = 50; +extern const char *header; + +namespace ngcore +{ + // Produce no traces by default + size_t PajeTrace::max_tracefile_size = 11110000; + + // If true, produce variable counting active threads + // increases trace by a factor of two + bool PajeTrace::trace_thread_counter = true; + bool PajeTrace::trace_threads = true; + + PajeTrace :: PajeTrace(int anthreads, std::string aname) + { + start_time = GetTime(); + + nthreads = anthreads; + tracefile_name = aname; + + int bytes_per_event=33; + max_num_events_per_thread = std::min( (size_t)std::numeric_limits::max, max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); + if(max_num_events_per_thread>0) + { + logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024); + logger->info( "Tracing {} events per thread", max_num_events_per_thread , " events per thread"); + } + + tasks.resize(nthreads); + int reserve_size = std::min(1000000U, max_num_events_per_thread); + for(auto & t : tasks) + t.reserve(reserve_size); + + links.resize(nthreads); + for(auto & l : links) + l.reserve(reserve_size); + + jobs.reserve(reserve_size); + timer_events.reserve(reserve_size); + + tracing_enabled = true; + } + + PajeTrace :: ~PajeTrace() + { + if(tracefile_name.size()>0) + Write(tracefile_name); + } + + + void PajeTrace::StopTracing() + { + if(tracing_enabled && max_num_events_per_thread>0) + { + logger->warn("Maximum number of traces reached, tracing is stopped now."); + } + tracing_enabled = false; + } + + using std::string; + class PajeFile + { + public: + typedef PajeTrace::TTimePoint TTimePoint; + static void Hue2RGB ( double x, double &r, double &g, double &b ) + { + double d = 1.0/6.0; + if(x logger = GetLogger("PajeTrace"); + + + double ConvertTime(TTimePoint t) { + // return time in milliseconds as double + // return std::chrono::duration(t-start_time).count()*1000.0; + // return std::chrono::duration(t-start_time).count() / 2.7e3; + return (t-start_time) / 2.7e6; + } + + enum PType + { + SET_VARIABLE=1, + ADD_VARIABLE, + SUB_VARIABLE, + PUSH_STATE, + POP_STATE, + START_LINK, + STOP_LINK + }; + + struct PajeEvent + { + PajeEvent( int aevent_type, double atime, int atype, int acontainer, double avar_value ) + : time(atime), var_value(avar_value), event_type(aevent_type), type(atype), container(acontainer) + { } + + PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue = 0, int aid = 0, bool avalue_is_alias = true ) + : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), id(aid), value_is_alias(avalue_is_alias) + { } + + PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey ) + : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), start_container(astart_container), id(akey) + { } + + double time; + double var_value = 0.0; + int event_type; + int type; + int container; + int value = 0; + int start_container = 0; + int id = 0; + bool value_is_alias = true; + + bool operator < (const PajeEvent & other) const { + // Same times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState) + if(time == other.time) + return event_type < other.event_type; + else + return (time < other.time); + } + + int write(char *buf) + { + const int &key = id; + const int &end_container = start_container; + switch(event_type) + { + case PajeSetVariable: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); + case PajeAddVariable: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); + case PajeSubVariable: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); + case PajePushState: + if(value_is_alias) + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); + else + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); + case PajePopState: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); + case PajeStartLink: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); + case PajeEndLink: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); + } + return 0; + } + }; + + std::vector events; + + public: + PajeFile( string filename, TTimePoint astart_time ) + { + start_time = astart_time; + ctrace_stream = fopen (filename.c_str(),"w"); + fprintf(ctrace_stream, "%s", header ); + alias_counter = 0; + } + int DefineContainerType ( int parent_type, string name ) + { + int alias = ++alias_counter; + if(parent_type!=0) + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); + else + fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); + return alias; + } + + int DefineVariableType ( int container_type, string name ) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"1.0 1.0 1.0\"\n", PajeDefineVariableType, alias, container_type, name.c_str() ); + return alias; + } + + int DefineStateType ( int type, string name ) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); + return alias; + } + + // int DefineEventType () + // { + // Write("event not implemented"); + // } + + int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, string name) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\ta%d\ta%d\t\"%s\"\n", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); + return alias; + } + + int DefineEntityValue (int type, string name, double hue = -1) + { + if(hue==-1) + { + std::hash shash; + size_t h = shash(name); + h ^= h>>32; + h = (uint32_t)h; + hue = h*1.0/std::numeric_limits::max(); + } + + int alias = ++alias_counter; + double r,g,b; + Hue2RGB( hue, r, g, b ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"%.15g %.15g %.15g\"\n", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); + return alias; + } + + int CreateContainer ( int type, int parent, string name ) + { + int alias = ++alias_counter; + if(parent!=0) + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\ta%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); + else + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); + return alias; + } + void DestroyContainer () + {} + + void SetVariable (TTimePoint time, int type, int container, double value ) + { + events.push_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); + } + + void AddVariable (TTimePoint time, int type, int container, double value ) + { + events.push_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); + } + + void SubVariable (TTimePoint time, int type, int container, double value ) + { + events.push_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); + } + + void SetState () + {} + + void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true ) + { + events.push_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id) ); + } + + void PopState ( TTimePoint time, int type, int container ) + { + events.push_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); + } + + void ResetState () + {} + + void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key ) + { + events.push_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) ); + } + + void EndLink ( TTimePoint time, int type, int container, int value, int end_container, int key ) + { + events.push_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); + } + + void NewEvent () + {} + + void WriteEvents() + { + logger->info("Sorting traces..."); + std::sort (events.begin(), events.end()); + + char buf[2*MAX_TRACE_LINE_SIZE]; + logger->info("Writing traces... "); + for (int i = 0; i < events.size(); i++) + { + events[i].write( buf ); + fprintf( ctrace_stream, "%s", buf ); + } + logger->info("Done"); + } + + private: + enum + { + PajeDefineContainerType = 0, + PajeDefineVariableType = 1, + PajeDefineStateType = 2, + PajeDefineEventType = 3, + PajeDefineLinkType = 4, + PajeDefineEntityValue = 5, + PajeCreateContainer = 6, + PajeDestroyContainer = 7, + PajeSetVariable = 8, + PajeAddVariable = 9, + PajeSubVariable = 10, + PajeSetState = 11, + PajePushState = 12, + PajePopState = 13, + PajeResetState = 14, + PajeStartLink = 15, + PajeEndLink = 16, + PajeNewEvent = 17 + }; + + }; + + NGCORE_API PajeTrace *trace; + + void PajeTrace::Write( string filename ) + { + int n_events = jobs.size() + timer_events.size(); + for(auto & vtasks : tasks) + n_events += vtasks.size(); + + logger->info("{} events traced", n_events); + + if(n_events==0) + { + logger->info("No data traced, skip writing trace file"); + return; + } + + if(!tracing_enabled) + { + logger->warning("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); + } + + PajeFile paje(filename, start_time); + + const int container_type_task_manager = paje.DefineContainerType( 0, "Task Manager" ); + const int container_type_node = paje.DefineContainerType( container_type_task_manager, "Node"); + const int container_type_thread = paje.DefineContainerType( container_type_task_manager, "Thread"); + const int container_type_timer = container_type_thread; //paje.DefineContainerType( container_type_task_manager, "Timers"); + const int container_type_jobs = paje.DefineContainerType( container_type_task_manager, "Jobs"); + + const int state_type_job = paje.DefineStateType( container_type_jobs, "Job" ); + const int state_type_task = paje.DefineStateType( container_type_thread, "Task" ); + const int state_type_timer = paje.DefineStateType( container_type_timer, "Timer state" ); + + const int variable_type_active_threads = paje.DefineVariableType( container_type_jobs, "Active threads" ); + + const int container_task_manager = paje.CreateContainer( container_type_task_manager, 0, "The task manager" ); + const int container_jobs = paje.CreateContainer( container_type_jobs, container_task_manager, "Jobs" ); + paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 ); + + const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1; + std::vector container_nodes; + + for(int i=0; i thread_aliases; + if(trace_threads) + for (int i=0; i job_map; + std::map job_task_map; + + for(Job & j : jobs) + if(job_map.find(j.type) == job_map.end()) + { + string name = Demangle(j.type->name()); + job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 ); + job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 ); + } + + for(Job & j : jobs) + { + paje.PushState( j.start_time, state_type_job, container_jobs, job_map[j.type] ); + paje.PopState( j.stop_time, state_type_job, container_jobs ); + } + + std::set timer_ids; + std::map timer_aliases; + + for(auto & event : timer_events) + timer_ids.insert(event.timer_id); + + + for(auto & vtasks : tasks) + for (Task & t : vtasks) + if(t.id_type==Task::ID_TIMER) + timer_ids.insert(t.id); + + for(auto id : timer_ids) + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, "a timer" /* TODO: NgProfiler::GetName(id).c_str()*/, -1 ); + + int timerdepth = 0; + int maxdepth = 0; + for(auto & event : timer_events) + { + if(event.is_start) + { + timerdepth++; + maxdepth = timerdepth>maxdepth ? timerdepth : maxdepth; + } + else + timerdepth--; + } + + std::vector timer_container_aliases; + timer_container_aliases.resize(maxdepth); + for(int i=0; i links_merged; + links_merged.reserve(nlinks); + std::vector pos(nthreads); + + int nlinks_merged = 0; + while(nlinks_merged < nlinks) + { + int minpos = -1; + TTimePoint mintime; + for (int t = 0; t started_links; + + int link_type = paje.DefineLinkType(container_type_node, container_type_thread, container_type_thread, "links"); + + // match links + for ( auto & l : links_merged ) + { + if(l.is_start) + { + started_links.push_back(l); + } + else + { + unsigned int i = 0; + while(i +#include +#include // for __rdtsc() CPU time step counter + +#include "ngcore_api.hpp" // for NGCORE_API +#include "logging.hpp" // for logger + +namespace ngcore +{ + + extern NGCORE_API class PajeTrace *trace; + class PajeTrace + { + public: + typedef std::chrono::system_clock TClock; + // typedef TClock::time_point TTimePoint; + typedef size_t TTimePoint; + + protected: + std::shared_ptr logger = GetLogger("PajeTrace"); + private: + friend class TraceDisabler; + + NGCORE_API static size_t max_tracefile_size; + static bool trace_thread_counter; + static bool trace_threads; + + bool tracing_enabled; + TTimePoint start_time; + int nthreads; + + public: + + // Approximate number of events to trace. Tracing will + // be stopped if any thread reaches this number of events + unsigned int max_num_events_per_thread; + + static void SetTraceThreads( bool atrace_threads ) + { + trace_threads = atrace_threads; + } + + static void SetTraceThreadCounter( bool trace_threads ) + { + trace_thread_counter = trace_threads; + } + + static void SetMaxTracefileSize( size_t max_size ) + { + max_tracefile_size = max_size; + } + + std::string tracefile_name; + + struct Job + { + int job_id; + const std::type_info *type; + TTimePoint start_time; + TTimePoint stop_time; + }; + + struct Task + { + int thread_id; + + int id; + int id_type; + + int additional_value; + + TTimePoint start_time; + TTimePoint stop_time; + + static constexpr int ID_NONE = -1; + static constexpr int ID_JOB = 1; + static constexpr int ID_TIMER = 2; + }; + + struct TimerEvent + { + int timer_id; + TTimePoint time; + bool is_start; + int thread_id; + + bool operator < (const TimerEvent & other) const { return time < other.time; } + }; + + struct ThreadLink + { + int thread_id; + int key; + TTimePoint time; + bool is_start; + bool operator < (const ThreadLink & other) const { return time < other.time; } + }; + + std::vector > tasks; + std::vector jobs; + std::vector timer_events; + std::vector > links; + + TTimePoint GetTime() + { + // return TClock::now(); + return TTimePoint(__rdtsc()); + } + + public: + NGCORE_API void StopTracing(); + + PajeTrace(int anthreads, std::string aname = ""); + ~PajeTrace(); + + void StartTimer(int timer_id) + { + if(!tracing_enabled) return; + if(unlikely(timer_events.size() == max_num_events_per_thread)) + StopTracing(); + timer_events.push_back(TimerEvent{timer_id, GetTime(), true}); + } + + void StopTimer(int timer_id) + { + if(!tracing_enabled) return; + if(unlikely(timer_events.size() == max_num_events_per_thread)) + StopTracing(); + timer_events.push_back(TimerEvent{timer_id, GetTime(), false}); + } + + NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1) + { + if(!tracing_enabled) return -1; + if(!trace_threads && !trace_thread_counter) return -1; + if(unlikely(tasks[thread_id].size() == max_num_events_per_thread)) + StopTracing(); + int task_num = tasks[thread_id].size(); + tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTime()} ); + return task_num; + } + + void StopTask(int thread_id, int task_num) + { + if(!trace_threads && !trace_thread_counter) return; + if(task_num>=0) + tasks[thread_id][task_num].stop_time = GetTime(); + } + + void SetTask(int thread_id, int task_num, int additional_value) { + if(!trace_threads && !trace_thread_counter) return; + if(task_num>=0) + tasks[thread_id][task_num].additional_value = additional_value; + } + + void StartJob(int job_id, const std::type_info & type) + { + if(!tracing_enabled) return; + if(jobs.size() == max_num_events_per_thread) + StopTracing(); + jobs.push_back( Job{job_id, &type, GetTime()} ); + } + + void StopJob() + { + if(tracing_enabled) + jobs.back().stop_time = GetTime(); + } + + void StartLink(int thread_id, int key) + { + if(!tracing_enabled) return; + if(links[thread_id].size() == max_num_events_per_thread) + StopTracing(); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTime(), true} ); + } + + void StopLink(int thread_id, int key) + { + if(!tracing_enabled) return; + if(links[thread_id].size() == max_num_events_per_thread) + StopTracing(); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTime(), false} ); + } + + void Write( std::string filename ); + + }; + + class TraceDisabler + { + bool trace_thread_counter; + bool trace_threads; + + public: + TraceDisabler() + { + trace_thread_counter = PajeTrace::trace_thread_counter; + PajeTrace::trace_thread_counter = false; + trace_threads = PajeTrace::trace_threads; + PajeTrace::trace_threads = false; + } + + ~TraceDisabler() + { + PajeTrace::trace_thread_counter = trace_thread_counter; + PajeTrace::trace_threads = trace_threads; + } + }; +} + +#endif // NETGEN_CORE_PAJE_TRACE_HPP diff --git a/libsrc/core/utils.cpp b/libsrc/core/utils.cpp new file mode 100644 index 00000000..5fbb11a4 --- /dev/null +++ b/libsrc/core/utils.cpp @@ -0,0 +1,20 @@ +#include "utils.hpp" + +#ifndef WIN32 +#include +#endif + +namespace ngcore +{ +#ifdef WIN32 + // windows does demangling in typeid(T).name() + NGCORE_API std::string Demangle(const char* typeinfo) { return typeinfo; } +#else + NGCORE_API std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, + nullptr, + nullptr, + &status); } +} // namespace ngcore + +#endif + diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp new file mode 100644 index 00000000..f80d55d8 --- /dev/null +++ b/libsrc/core/utils.hpp @@ -0,0 +1,23 @@ +#ifndef NETGEN_CORE_UTILS_HPP +#define NETGEN_CORE_UTILS_HPP + +#include +#include + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + NGCORE_API std::string Demangle(const char* typeinfo); + +#if defined(__GNUC__) + inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } + inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } +#else + inline bool likely (bool x) { return x; } + inline bool unlikely (bool x) { return x; } +#endif + +} // namespace ngcore + +#endif // NETGEN_CORE_UTILS_HPP From 3a1cea6cbfa2046f4fcbd9832070b01838139ff8 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:54:50 +0100 Subject: [PATCH 08/28] [ngcore] Profiler --- libsrc/core/CMakeLists.txt | 4 +- libsrc/core/paje_trace.cpp | 134 +++++++++-------- libsrc/core/paje_trace.hpp | 62 +++----- libsrc/core/profiler.cpp | 106 +++++++++++++ libsrc/core/profiler.hpp | 286 ++++++++++++++++++++++++++++++++++++ libsrc/core/utils.cpp | 20 +++ libsrc/core/utils.hpp | 33 ++++- libsrc/general/ngpython.hpp | 11 +- 8 files changed, 537 insertions(+), 119 deletions(-) create mode 100644 libsrc/core/profiler.cpp create mode 100644 libsrc/core/profiler.hpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 3e10f58d..c43a79ab 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp profiler.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) @@ -32,7 +32,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp - exception.hpp symboltable.hpp paje_trace.hpp utils.hpp + exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 2742d25e..873a93d7 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -1,9 +1,9 @@ #include #include +#include #include #include #include -#include #include "archive.hpp" // for Demangle #include "paje_trace.hpp" @@ -23,13 +23,13 @@ namespace ngcore PajeTrace :: PajeTrace(int anthreads, std::string aname) { - start_time = GetTime(); + start_time = GetTimeCounter(); nthreads = anthreads; - tracefile_name = aname; + tracefile_name = std::move(aname); int bytes_per_event=33; - max_num_events_per_thread = std::min( (size_t)std::numeric_limits::max, max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); + max_num_events_per_thread = std::min( static_cast(std::numeric_limits::max()), max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); if(max_num_events_per_thread>0) { logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024); @@ -53,7 +53,7 @@ namespace ngcore PajeTrace :: ~PajeTrace() { - if(tracefile_name.size()>0) + if(!tracefile_name.empty()) Write(tracefile_name); } @@ -67,11 +67,9 @@ namespace ngcore tracing_enabled = false; } - using std::string; class PajeFile { public: - typedef PajeTrace::TTimePoint TTimePoint; static void Hue2RGB ( double x, double &r, double &g, double &b ) { double d = 1.0/6.0; @@ -139,36 +137,35 @@ namespace ngcore bool value_is_alias = true; bool operator < (const PajeEvent & other) const { - // Same times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState) + // Same start and stop times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState) if(time == other.time) return event_type < other.event_type; - else - return (time < other.time); + return (time < other.time); } - int write(char *buf) + int write(FILE *stream) { const int &key = id; const int &end_container = start_container; switch(event_type) { case PajeSetVariable: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); // NOLINT case PajeAddVariable: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); // NOLINT case PajeSubVariable: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); // NOLINT case PajePushState: if(value_is_alias) - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT else - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT case PajePopState: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); // NOLINT case PajeStartLink: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); // NOLINT case PajeEndLink: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); // NOLINT } return 0; } @@ -177,34 +174,46 @@ namespace ngcore std::vector events; public: - PajeFile( string filename, TTimePoint astart_time ) + PajeFile() = delete; + PajeFile(const PajeFile &) = delete; + PajeFile(PajeFile &&) = delete; + void operator=(const PajeFile &) = delete; + void operator=(PajeFile &&) = delete; + + PajeFile( const std::string & filename, TTimePoint astart_time ) { start_time = astart_time; - ctrace_stream = fopen (filename.c_str(),"w"); - fprintf(ctrace_stream, "%s", header ); + ctrace_stream = fopen (filename.c_str(),"w"); // NOLINT + fprintf(ctrace_stream, "%s", header ); // NOLINT alias_counter = 0; } - int DefineContainerType ( int parent_type, string name ) + + ~PajeFile() + { + fclose (ctrace_stream); // NOLINT + } + + int DefineContainerType ( int parent_type, const std::string & name ) { int alias = ++alias_counter; if(parent_type!=0) - fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT else - fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); + fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT return alias; } - int DefineVariableType ( int container_type, string name ) + int DefineVariableType ( int container_type, const std::string & name ) { int alias = ++alias_counter; - fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"1.0 1.0 1.0\"\n", PajeDefineVariableType, alias, container_type, name.c_str() ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"1.0 1.0 1.0\"\n", PajeDefineVariableType, alias, container_type, name.c_str() ); // NOLINT return alias; } - int DefineStateType ( int type, string name ) + int DefineStateType ( int type, const std::string & name ) { int alias = ++alias_counter; - fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); // NOLINT return alias; } @@ -213,38 +222,38 @@ namespace ngcore // Write("event not implemented"); // } - int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, string name) + int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, const std::string & name) { int alias = ++alias_counter; - fprintf( ctrace_stream, "%d\ta%d\ta%d\ta%d\ta%d\t\"%s\"\n", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\ta%d\ta%d\t\"%s\"\n", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); // NOLINT return alias; } - int DefineEntityValue (int type, string name, double hue = -1) + int DefineEntityValue (int type, const std::string & name, double hue = -1) { if(hue==-1) { - std::hash shash; + std::hash shash; size_t h = shash(name); - h ^= h>>32; - h = (uint32_t)h; + h ^= h>>32U; + h = static_cast(h); hue = h*1.0/std::numeric_limits::max(); } int alias = ++alias_counter; double r,g,b; Hue2RGB( hue, r, g, b ); - fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"%.15g %.15g %.15g\"\n", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"%.15g %.15g %.15g\"\n", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); // NOLINT return alias; } - int CreateContainer ( int type, int parent, string name ) + int CreateContainer ( int type, int parent, const std::string & name ) { int alias = ++alias_counter; if(parent!=0) - fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\ta%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\ta%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT else - fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT return alias; } void DestroyContainer () @@ -252,17 +261,17 @@ namespace ngcore void SetVariable (TTimePoint time, int type, int container, double value ) { - events.push_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); + events.emplace_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); } void AddVariable (TTimePoint time, int type, int container, double value ) { - events.push_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); + events.emplace_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); } void SubVariable (TTimePoint time, int type, int container, double value ) { - events.push_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); + events.emplace_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); } void SetState () @@ -270,12 +279,12 @@ namespace ngcore void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true ) { - events.push_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id) ); + events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) ); } void PopState ( TTimePoint time, int type, int container ) { - events.push_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); + events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); } void ResetState () @@ -283,12 +292,12 @@ namespace ngcore void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key ) { - events.push_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) ); + events.emplace_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) ); } void EndLink ( TTimePoint time, int type, int container, int value, int end_container, int key ) { - events.push_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); + events.emplace_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); } void NewEvent () @@ -299,12 +308,11 @@ namespace ngcore logger->info("Sorting traces..."); std::sort (events.begin(), events.end()); - char buf[2*MAX_TRACE_LINE_SIZE]; logger->info("Writing traces... "); - for (int i = 0; i < events.size(); i++) + for (auto & event : events) { - events[i].write( buf ); - fprintf( ctrace_stream, "%s", buf ); + event.write( ctrace_stream ); +// fprintf( ctrace_stream, "%s", buf ); // NOLINT } logger->info("Done"); } @@ -336,7 +344,7 @@ namespace ngcore NGCORE_API PajeTrace *trace; - void PajeTrace::Write( string filename ) + void PajeTrace::Write( const std::string & filename ) { int n_events = jobs.size() + timer_events.size(); for(auto & vtasks : tasks) @@ -352,7 +360,7 @@ namespace ngcore if(!tracing_enabled) { - logger->warning("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); + logger->warn("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); } PajeFile paje(filename, start_time); @@ -374,18 +382,19 @@ namespace ngcore paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 ); const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1; - std::vector container_nodes; + std::vector container_nodes; + container_nodes.reserve(num_nodes); for(int i=0; i thread_aliases; + thread_aliases.reserve(nthreads); if(trace_threads) for (int i=0; i job_map; @@ -394,7 +403,7 @@ namespace ngcore for(Job & j : jobs) if(job_map.find(j.type) == job_map.end()) { - string name = Demangle(j.type->name()); + std::string name = Demangle(j.type->name()); job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 ); job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 ); } @@ -437,8 +446,7 @@ namespace ngcore timer_container_aliases.resize(maxdepth); for(int i=0; i #include // for __rdtsc() CPU time step counter -#include "ngcore_api.hpp" // for NGCORE_API #include "logging.hpp" // for logger +#include "ngcore_api.hpp" // for NGCORE_API +#include "utils.hpp" namespace ngcore { @@ -15,15 +16,11 @@ namespace ngcore class PajeTrace { public: - typedef std::chrono::system_clock TClock; - // typedef TClock::time_point TTimePoint; - typedef size_t TTimePoint; + using TClock = std::chrono::system_clock; protected: std::shared_ptr logger = GetLogger("PajeTrace"); private: - friend class TraceDisabler; - NGCORE_API static size_t max_tracefile_size; static bool trace_thread_counter; static bool trace_threads; @@ -104,24 +101,24 @@ namespace ngcore std::vector timer_events; std::vector > links; - TTimePoint GetTime() - { - // return TClock::now(); - return TTimePoint(__rdtsc()); - } - public: NGCORE_API void StopTracing(); + PajeTrace() = delete; + PajeTrace(const PajeTrace &) = delete; + PajeTrace(PajeTrace &&) = delete; PajeTrace(int anthreads, std::string aname = ""); ~PajeTrace(); + void operator=(const PajeTrace &) = delete; + void operator=(PajeTrace &&) = delete; + void StartTimer(int timer_id) { if(!tracing_enabled) return; if(unlikely(timer_events.size() == max_num_events_per_thread)) StopTracing(); - timer_events.push_back(TimerEvent{timer_id, GetTime(), true}); + timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true}); } void StopTimer(int timer_id) @@ -129,7 +126,7 @@ namespace ngcore if(!tracing_enabled) return; if(unlikely(timer_events.size() == max_num_events_per_thread)) StopTracing(); - timer_events.push_back(TimerEvent{timer_id, GetTime(), false}); + timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), false}); } NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1) @@ -139,7 +136,7 @@ namespace ngcore if(unlikely(tasks[thread_id].size() == max_num_events_per_thread)) StopTracing(); int task_num = tasks[thread_id].size(); - tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTime()} ); + tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter()} ); return task_num; } @@ -147,7 +144,7 @@ namespace ngcore { if(!trace_threads && !trace_thread_counter) return; if(task_num>=0) - tasks[thread_id][task_num].stop_time = GetTime(); + tasks[thread_id][task_num].stop_time = GetTimeCounter(); } void SetTask(int thread_id, int task_num, int additional_value) { @@ -161,13 +158,13 @@ namespace ngcore if(!tracing_enabled) return; if(jobs.size() == max_num_events_per_thread) StopTracing(); - jobs.push_back( Job{job_id, &type, GetTime()} ); + jobs.push_back( Job{job_id, &type, GetTimeCounter()} ); } void StopJob() { if(tracing_enabled) - jobs.back().stop_time = GetTime(); + jobs.back().stop_time = GetTimeCounter(); } void StartLink(int thread_id, int key) @@ -175,7 +172,7 @@ namespace ngcore if(!tracing_enabled) return; if(links[thread_id].size() == max_num_events_per_thread) StopTracing(); - links[thread_id].push_back( ThreadLink{thread_id, key, GetTime(), true} ); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} ); } void StopLink(int thread_id, int key) @@ -183,33 +180,12 @@ namespace ngcore if(!tracing_enabled) return; if(links[thread_id].size() == max_num_events_per_thread) StopTracing(); - links[thread_id].push_back( ThreadLink{thread_id, key, GetTime(), false} ); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} ); } - void Write( std::string filename ); + void Write( const std::string & filename ); }; - - class TraceDisabler - { - bool trace_thread_counter; - bool trace_threads; - - public: - TraceDisabler() - { - trace_thread_counter = PajeTrace::trace_thread_counter; - PajeTrace::trace_thread_counter = false; - trace_threads = PajeTrace::trace_threads; - PajeTrace::trace_threads = false; - } - - ~TraceDisabler() - { - PajeTrace::trace_thread_counter = trace_thread_counter; - PajeTrace::trace_threads = trace_threads; - } - }; -} +} // namespace ngcore #endif // NETGEN_CORE_PAJE_TRACE_HPP diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp new file mode 100644 index 00000000..e3350145 --- /dev/null +++ b/libsrc/core/profiler.cpp @@ -0,0 +1,106 @@ +#include + +#include "profiler.hpp" + +namespace ngcore +{ + std::array NgProfiler::timers; // NOLINT + + std::string NgProfiler::filename; + + size_t dummy_thread_times[NgProfiler::SIZE]; + size_t * NgProfiler::thread_times = dummy_thread_times; // NOLINT + size_t dummy_thread_flops[NgProfiler::SIZE]; + size_t * NgProfiler::thread_flops = dummy_thread_flops; // NOLINT + + std::shared_ptr logger = GetLogger("Profiler"); // NOLINT + + NgProfiler :: NgProfiler() + { + for (auto & t : timers) + { + t.tottime = 0.0; + t.usedcounter = 0; + t.flops = 0.0; + } + } + + NgProfiler :: ~NgProfiler() + { + if (filename.length()) + { + logger->debug( "write profile to file {}", filename ); + FILE *prof = fopen(filename.c_str(),"w"); // NOLINT + Print (prof); + fclose(prof); // NOLINT + } + + } + + void NgProfiler :: Print (FILE * prof) + { + int i = 0; + for (auto & t : timers) + { + if (t.count != 0 || t.usedcounter != 0) + { + fprintf(prof,"job %3i calls %8li, time %6.4f sec",i,t.count,t.tottime); // NOLINT + if(t.flops != 0.0) + fprintf(prof,", MFlops = %6.2f",t.flops / (t.tottime) * 1e-6); // NOLINT + if(t.loads != 0.0) + fprintf(prof,", MLoads = %6.2f",t.loads / (t.tottime) * 1e-6); // NOLINT + if(t.stores != 0.0) + fprintf(prof,", MStores = %6.2f",t.stores / (t.tottime) * 1e-6); // NOLINT + if(t.usedcounter) + fprintf(prof," %s",t.name.c_str()); // NOLINT + fprintf(prof,"\n"); // NOLINT + } + i++; + } + } + + + int NgProfiler :: CreateTimer (const std::string & name) + { + static std::mutex createtimer_mutex; + int nr = -1; + { + std::lock_guard guard(createtimer_mutex); + for (int i = SIZE-1; i > 0; i--) + { + auto & t = timers[i]; + if (!t.usedcounter) + { + t.usedcounter = 1; + t.name = name; + nr = i; + break; + } + } + } + if (nr > -1) return nr; + static bool first_overflow = true; + if (first_overflow) + { + first_overflow = false; + NgProfiler::logger->warn("no more timer available, reusing last one"); + } + return 0; + } + + void NgProfiler :: Reset () + { + for(auto & t : timers) + { + t.tottime = 0.0; + t.count = 0; + t.flops = 0.0; + t.loads = 0; + t.stores = 0; + } + } + + NgProfiler prof; // NOLINT + + +} // namespace ngcore diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp new file mode 100644 index 00000000..b1b75dd5 --- /dev/null +++ b/libsrc/core/profiler.hpp @@ -0,0 +1,286 @@ +#ifndef NETGEN_CORE_PROFILER_HPP +#define NETGEN_CORE_PROFILER_HPP + +#include +#include + +#include "logging.hpp" +#include "paje_trace.hpp" +#include "utils.hpp" + +namespace ngcore +{ + class NgProfiler + { + public: + /// maximal number of timers + enum { SIZE = 8*1024 }; + + struct TimerVal + { + TimerVal() = default; + + double tottime = 0.0; + double starttime = 0.0; + double flops = 0.0; + double loads = 0.0; + double stores = 0.0; + long count = 0; + std::string name = ""; + int usedcounter = 0; + }; + + NGCORE_API static std::array timers; + + NGCORE_API static TTimePoint * thread_times; + NGCORE_API static TTimePoint * thread_flops; + NGCORE_API static std::shared_ptr logger; + private: + + static std::string filename; + public: + NgProfiler(); + ~NgProfiler(); + + NgProfiler(const NgProfiler &) = delete; + NgProfiler(NgProfiler &&) = delete; + void operator=(const NgProfiler &) = delete; + void operator=(NgProfiler &&) = delete; + + static void SetFileName (const std::string & afilename) { filename = afilename; } + + /// create new timer, use integer index + NGCORE_API static int CreateTimer (const std::string & name); + + NGCORE_API static void Reset (); + + + /// start timer of index nr + static void StartTimer (int nr) + { + timers[nr].starttime = WallTime(); timers[nr].count++; + } + + /// stop timer of index nr + static void StopTimer (int nr) + { + timers[nr].tottime += WallTime()-timers[nr].starttime; + } + + static void StartThreadTimer (size_t nr, size_t tid) + { + thread_times[tid*SIZE+nr] -= GetTimeCounter(); + } + + static void StopThreadTimer (size_t nr, size_t tid) + { + thread_times[tid*SIZE+nr] += GetTimeCounter(); + } + + static void AddThreadFlops (size_t nr, size_t tid, size_t flops) + { + thread_flops[tid*SIZE+nr] += flops; + } + + /// if you know number of flops, provide them to obtain the MFlop - rate + static void AddFlops (int nr, double aflops) { timers[nr].flops += aflops; } + static void AddLoads (int nr, double aloads) { timers[nr].loads += aloads; } + static void AddStores (int nr, double astores) { timers[nr].stores += astores; } + + static int GetNr (const std::string & name) + { + for (int i = SIZE-1; i >= 0; i--) + if (timers[i].name == name) + return i; + return -1; + } + + static double GetTime (int nr) + { + return timers[nr].tottime; + } + + static double GetTime (const std::string & name) + { + for (int i = SIZE-1; i >= 0; i--) + if (timers[i].name == name) + return GetTime (i); + return 0; + } + + static long int GetCounts (int nr) + { + return timers[nr].count; + } + + static double GetFlops (int nr) + { + return timers[nr].flops; + } + + /// change name + static void SetName (int nr, const std::string & name) { timers[nr].name = name; } + static std::string GetName (int nr) { return timers[nr].name; } + /// print profile + NGCORE_API static void Print (FILE * ost); + }; + + + + class Timer + { + int timernr; + int priority; + public: + Timer (const std::string & name, int apriority = 1) + : priority(apriority) + { + timernr = NgProfiler::CreateTimer (name); + } + void SetName (const std::string & name) + { + NgProfiler::SetName (timernr, name); + } + void Start () + { + if (priority <= 2) + NgProfiler::StartTimer (timernr); + if (priority <= 1) + if(trace) trace->StartTimer(timernr); + } + void Stop () + { + if (priority <= 2) + NgProfiler::StopTimer (timernr); + if (priority <= 1) + if(trace) trace->StopTimer(timernr); + } + void AddFlops (double aflops) + { + if (priority <= 2) + NgProfiler::AddFlops (timernr, aflops); + } + + double GetTime () { return NgProfiler::GetTime(timernr); } + long int GetCounts () { return NgProfiler::GetCounts(timernr); } + double GetMFlops () + { return NgProfiler::GetFlops(timernr) + / NgProfiler::GetTime(timernr) * 1e-6; } + operator int () { return timernr; } + }; + + + /** + Timer object. + Start / stop timer at constructor / destructor. + */ + class RegionTimer + { + Timer & timer; + public: + /// start timer + RegionTimer (Timer & atimer) : timer(atimer) { timer.Start(); } + /// stop timer + ~RegionTimer () { timer.Stop(); } + + RegionTimer() = delete; + RegionTimer(RegionTimer &&) = delete; + RegionTimer(const RegionTimer &) = delete; + void operator=(const RegionTimer &) = delete; + void operator=(RegionTimer &&) = delete; + }; + + class ThreadRegionTimer + { + size_t nr; + size_t tid; + public: + /// start timer + ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid) + { NgProfiler::StartThreadTimer(nr, tid); } + /// stop timer + ~ThreadRegionTimer () + { NgProfiler::StopThreadTimer(nr, tid); } + + ThreadRegionTimer() = delete; + ThreadRegionTimer(ThreadRegionTimer &&) = delete; + ThreadRegionTimer(const ThreadRegionTimer &) = delete; + void operator=(const ThreadRegionTimer &) = delete; + void operator=(ThreadRegionTimer &&) = delete; + }; + + class RegionTracer + { + int nr; + int thread_id; + public: + static constexpr int ID_JOB = PajeTrace::Task::ID_JOB; + static constexpr int ID_NONE = PajeTrace::Task::ID_NONE; + static constexpr int ID_TIMER = PajeTrace::Task::ID_TIMER; + + RegionTracer() = delete; + RegionTracer(RegionTracer &&) = delete; + RegionTracer(const RegionTracer &) = delete; + void operator=(const RegionTracer &) = delete; + void operator=(RegionTracer &&) = delete; + + /// start trace + RegionTracer (int athread_id, int region_id, int id_type = ID_NONE, int additional_value = -1 ) + : thread_id(athread_id) + { + if (trace) + nr = trace->StartTask (athread_id, region_id, id_type, additional_value); + } + /// start trace with timer + RegionTracer (int athread_id, Timer & timer, int additional_value = -1 ) + : thread_id(athread_id) + { + if (trace) + nr = trace->StartTask (athread_id, static_cast(timer), ID_TIMER, additional_value); + } + + /// set user defined value + void SetValue( int additional_value ) + { + if (trace) + trace->SetTask( thread_id, nr, additional_value ); + } + + /// stop trace + ~RegionTracer () + { + if (trace) + trace->StopTask (thread_id, nr); + } + }; + + + // Helper function for timings + // Run f() at least min_iterations times until max_time seconds elapsed + // returns minimum runtime for a call of f() + template + double RunTiming( TFunc f, double max_time = 0.5, int min_iterations = 10 ) + { + // Make sure the whole test run does not exceed maxtime + double tend = WallTime()+max_time; + + // warmup + f(); + + double tres = std::numeric_limits::max(); + int iteration = 0; + while(WallTime() #endif +#include namespace ngcore { @@ -14,6 +16,24 @@ namespace ngcore nullptr, nullptr, &status); } + + double ticks_per_second = [] () noexcept + { + auto tick_start = GetTimeCounter(); + double tstart = WallTime(); + double tend = WallTime()+0.001; + + // wait for 1ms and compare wall time with time counter + while(WallTime() wall_time_start = TClock::now(); + } // namespace ngcore #endif diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index f80d55d8..2c88629d 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -1,8 +1,10 @@ #ifndef NETGEN_CORE_UTILS_HPP #define NETGEN_CORE_UTILS_HPP -#include +#include #include +#include +#include // for __rdtsc() CPU time step counter #include "ngcore_api.hpp" // for NGCORE_API @@ -18,6 +20,35 @@ namespace ngcore inline bool unlikely (bool x) { return x; } #endif + using TClock = std::chrono::system_clock; + extern NGCORE_API const std::chrono::time_point wall_time_start; + + // Time in seconds since program start + inline double WallTime () noexcept + { + std::chrono::time_point now = TClock::now(); + std::chrono::duration elapsed_seconds = now-wall_time_start; + return elapsed_seconds.count(); + } + + // High precision clock counter register + using TTimePoint = size_t; + extern NGCORE_API double ticks_per_second; + + inline TTimePoint GetTimeCounter() noexcept + { + return TTimePoint(__rdtsc()); + } + + template + inline std::string ToString (const T& t) + { + std::stringstream ss; + ss << t; + return ss.str(); + } + + } // namespace ngcore #endif // NETGEN_CORE_UTILS_HPP diff --git a/libsrc/general/ngpython.hpp b/libsrc/general/ngpython.hpp index fa9862b1..0604cb00 100644 --- a/libsrc/general/ngpython.hpp +++ b/libsrc/general/ngpython.hpp @@ -66,16 +66,7 @@ namespace netgen return static_cast::pointer>(lambda); } - - template - inline std::string ToString (const T& t) - { - std::stringstream ss; - ss << t; - return ss.str(); - } - -} +} // namespace netgen #endif From 8c54fd70afddbcfa03f43636152a418b91493540 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:17 +0100 Subject: [PATCH 09/28] [gitlab-ci] Fix builds --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d493bdab..276a0ec8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,8 +14,8 @@ stages: - x64 before_script: - "echo off" - - 'call "%VS140COMNTOOLS%\..\..\VC\bin\amd64\vcvars64.bat"' - - set CMAKE_GENERATOR=Visual Studio 14 2015 Win64 + - 'call "%VS2017INSTALLDIR%\VC\Auxiliary\Build\vcvars64"' + - set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - set CI_DIR=C:\ci\%CI_PIPELINE_ID% - set NETGEN_BUILD_DIR=%CI_DIR%\build - set INSTALL_DIR=%CI_DIR%\install From 930d82ba38a508f444f8116fa1d4f0ad8abe8f1c Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:42 +0100 Subject: [PATCH 10/28] [lint] allow pointer arithmetic --- libsrc/core/.clang-tidy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 806e0616..63d05e89 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,5 +1,5 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 -WarningsAsErrors: '*' \ No newline at end of file +WarningsAsErrors: '*' From 8ab625c3fa9ba72506218954571c40d6ac94e38c Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:51 +0100 Subject: [PATCH 11/28] Fix build error --- libsrc/core/archive.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 04915cbc..6a4a0792 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -209,7 +209,6 @@ namespace ngcore // vector has special implementation (like a bitarray) therefore // it needs a special overload (this could probably be more efficient, but we // don't use it that often anyway) - template<> Archive& operator& (std::vector& v) { size_t size; From baca4a57a0d4744218c5f5ca20c7a4c5430f15c6 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:57:00 +0100 Subject: [PATCH 12/28] Fix link error --- libsrc/core/profiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index e3350145..bb95a111 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -13,7 +13,7 @@ namespace ngcore size_t dummy_thread_flops[NgProfiler::SIZE]; size_t * NgProfiler::thread_flops = dummy_thread_flops; // NOLINT - std::shared_ptr logger = GetLogger("Profiler"); // NOLINT + std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT NgProfiler :: NgProfiler() { From c6a401e0663c121d3b2cc2eba0be43097834c964 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 11:26:46 +0100 Subject: [PATCH 13/28] Remove old profiler.hpp --- libsrc/core/.clang-tidy | 2 +- libsrc/core/ngcore.hpp | 1 + libsrc/core/profiler.cpp | 2 +- libsrc/core/profiler.hpp | 26 ++++-- libsrc/general/CMakeLists.txt | 10 +-- libsrc/general/myadt.hpp | 3 +- libsrc/general/ngexception.cpp | 33 -------- libsrc/general/ngexception.hpp | 34 -------- libsrc/general/profiler.cpp | 131 ------------------------------ libsrc/general/profiler.hpp | 88 -------------------- libsrc/stlgeom/meshstlsurface.cpp | 1 - 11 files changed, 29 insertions(+), 302 deletions(-) delete mode 100644 libsrc/general/ngexception.cpp delete mode 100644 libsrc/general/ngexception.hpp delete mode 100644 libsrc/general/profiler.cpp delete mode 100644 libsrc/general/profiler.hpp diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 63d05e89..5742a3d8 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 153a0e6c..d73a3ed9 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -4,6 +4,7 @@ #include "archive.hpp" #include "exception.hpp" #include "logging.hpp" +#include "profiler.hpp" #include "symboltable.hpp" #include "version.hpp" diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index bb95a111..e24de4e3 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -4,7 +4,7 @@ namespace ngcore { - std::array NgProfiler::timers; // NOLINT + std::vector NgProfiler::timers(NgProfiler::SIZE); // NOLINT std::string NgProfiler::filename; diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index b1b75dd5..10a5cf0d 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -30,7 +30,7 @@ namespace ngcore int usedcounter = 0; }; - NGCORE_API static std::array timers; + NGCORE_API static std::vector timers; NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; @@ -69,17 +69,17 @@ namespace ngcore static void StartThreadTimer (size_t nr, size_t tid) { - thread_times[tid*SIZE+nr] -= GetTimeCounter(); + thread_times[tid*SIZE+nr] -= GetTimeCounter(); // NOLINT } static void StopThreadTimer (size_t nr, size_t tid) { - thread_times[tid*SIZE+nr] += GetTimeCounter(); + thread_times[tid*SIZE+nr] += GetTimeCounter(); // NOLINT } static void AddThreadFlops (size_t nr, size_t tid, size_t flops) { - thread_flops[tid*SIZE+nr] += flops; + thread_flops[tid*SIZE+nr] += flops; // NOLINT } /// if you know number of flops, provide them to obtain the MFlop - rate @@ -123,6 +123,22 @@ namespace ngcore static std::string GetName (int nr) { return timers[nr].name; } /// print profile NGCORE_API static void Print (FILE * ost); + + class RegionTimer + { + int nr; + public: + /// start timer + RegionTimer (int anr) : nr(anr) { NgProfiler::StartTimer(nr); } + /// stop timer + ~RegionTimer () { NgProfiler::StopTimer(nr); } + + RegionTimer() = delete; + RegionTimer(const RegionTimer &) = delete; + RegionTimer(RegionTimer &&) = delete; + void operator=(const RegionTimer &) = delete; + void operator=(RegionTimer &&) = delete; + }; }; @@ -184,8 +200,8 @@ namespace ngcore ~RegionTimer () { timer.Stop(); } RegionTimer() = delete; - RegionTimer(RegionTimer &&) = delete; RegionTimer(const RegionTimer &) = delete; + RegionTimer(RegionTimer &&) = delete; void operator=(const RegionTimer &) = delete; void operator=(RegionTimer &&) = delete; }; diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index b65fee96..f1c39183 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -1,8 +1,8 @@ add_definitions(-DNGINTERFACE_EXPORTS) add_library(gen OBJECT array.cpp bitarray.cpp dynamicmem.cpp flags.cpp - hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp - profiler.cpp seti.cpp sort.cpp spbita2d.cpp table.cpp + hashtabl.cpp mystring.cpp optmem.cpp parthreads.cpp + seti.cpp sort.cpp spbita2d.cpp table.cpp mpi_interface.cpp gzstream.cpp ) @@ -12,13 +12,11 @@ endif(NOT WIN32) set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) -install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) - install(FILES array.hpp autodiff.hpp autoptr.hpp bitarray.hpp dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp - ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp - optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp + ngsimd.hpp mystring.hpp netgenout.hpp ngpython.hpp + optmem.hpp parthreads.hpp seti.hpp sort.hpp spbita2d.hpp stack.hpp table.hpp template.hpp gzstream.h DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel diff --git a/libsrc/general/myadt.hpp b/libsrc/general/myadt.hpp index 7263d088..4284a42f 100644 --- a/libsrc/general/myadt.hpp +++ b/libsrc/general/myadt.hpp @@ -21,8 +21,8 @@ namespace netgen { using namespace ngcore; + using NgException = Exception; } -#include "ngexception.hpp" #include "parthreads.hpp" // #include "moveablemem.hpp" #include "dynamicmem.hpp" @@ -43,7 +43,6 @@ namespace netgen #include "sort.hpp" #include "stack.hpp" #include "mystring.hpp" -#include "profiler.hpp" #include "mpi_interface.hpp" #include "netgenout.hpp" diff --git a/libsrc/general/ngexception.cpp b/libsrc/general/ngexception.cpp deleted file mode 100644 index 6bcd2cc9..00000000 --- a/libsrc/general/ngexception.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************/ -/* File: ngexception.cpp */ -/* Author: Joachim Schoeberl */ -/* Date: 16. Jan. 02 */ -/**************************************************************************/ - -#include - -namespace netgen -{ - //using namespace netgen; - - - - NgException :: NgException (const string & s) - : m_what(s) - { - ; - } - - - NgException :: ~NgException () - { - ; - } - - /// append string to description - void NgException :: Append (const string & s) - { - m_what += s; - } - -} diff --git a/libsrc/general/ngexception.hpp b/libsrc/general/ngexception.hpp deleted file mode 100644 index 6e06498c..00000000 --- a/libsrc/general/ngexception.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef FILE_NGEXCEPTION -#define FILE_NGEXCEPTION - -/**************************************************************************/ -/* File: ngexception.hpp */ -/* Author: Joachim Schoeberl */ -/* Date: 16. Jan. 2002 */ -/**************************************************************************/ - -namespace netgen -{ - -/// Base class for all ng exceptions -class NgException : public std::exception -{ - /// verbal description of exception - string m_what; -public: - /// - DLL_HEADER NgException (const string & s); - /// - DLL_HEADER virtual ~NgException (); - - /// append string to description - DLL_HEADER void Append (const string & s); - // void Append (const char * s); - - /// verbal description of exception - const string & What() const { return m_what; } - virtual const char* what() const noexcept override { return m_what.c_str(); } -}; -} - -#endif diff --git a/libsrc/general/profiler.cpp b/libsrc/general/profiler.cpp deleted file mode 100644 index e6a9685b..00000000 --- a/libsrc/general/profiler.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************/ -/* File: profiler.cpp */ -/* Author: Joachim Schoeberl */ -/* Date: 19. Apr. 2002 */ -/**************************************************************************/ - - -#include - -namespace netgen -{ - //using namespace netgen; - - long int NgProfiler::tottimes[SIZE]; - long int NgProfiler::starttimes[SIZE]; - long int NgProfiler::counts[SIZE]; - string NgProfiler::names[SIZE]; - int NgProfiler::usedcounter[SIZE]; - - - NgProfiler :: NgProfiler() - { - for (int i = 0; i < SIZE; i++) - { - tottimes[i] = 0; - usedcounter[i] = 0; - } - - total_timer = CreateTimer ("total CPU time"); - StartTimer (total_timer); - } - - NgProfiler :: ~NgProfiler() - { -#ifndef PARALLEL - StopTimer (total_timer); -#endif - - //ofstream prof; - //prof.open("ng.prof"); - - // ofstream-constructor may be called after STL-stuff is destructed, - // which leads to an "order of destruction"-problem, - // thus we use the C-variant: - - if (getenv ("NGPROFILE")) - { - char filename[100]; -#ifdef PARALLEL - sprintf (filename, "netgen.prof.%d", id); -#else - sprintf (filename, "netgen.prof"); -#endif - - if (id == 0) printf ("write profile to file netgen.prof\n"); - FILE *prof = fopen(filename,"w"); - Print (prof); - fclose(prof); - } - } - - -// void NgProfiler :: Print (ostream & prof) -// { -// for (int i = 0; i < SIZE; i++) -// if (counts[i] != 0 || usedcounter[i] != 0) -// { -// prof.setf (ios::fixed, ios::floatfield); -// prof.setf (ios::showpoint); - -// prof // << "job " << setw(3) << i -// << "calls " << setw(8) << counts[i] -// << ", time " << setprecision(2) << setw(6) << double(tottimes[i]) / CLOCKS_PER_SEC << " sec"; - -// if (usedcounter[i]) -// prof << " " << names[i]; -// else -// prof << " " << i; - -// prof << endl; -// } -// } - - - void NgProfiler :: Print (FILE * prof) - { - for (int i = 0; i < SIZE; i++) - if (counts[i] != 0 || usedcounter[i] != 0) - { - //fprintf(prof,"job %3i calls %8i, time %6.2f sec",i,counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); -#ifndef USE_TSC - fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); -#else - fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / 2.7e9); -#endif - if(usedcounter[i]) - fprintf(prof," %s",names[i].c_str()); - else - fprintf(prof," %i",i); - fprintf(prof,"\n"); - } - } - - int NgProfiler :: CreateTimer (const string & name) - { - for (int i = SIZE-1; i > 0; i--) - if(names[i] == name) - return i; - - for (int i = SIZE-1; i > 0; i--) - if (!usedcounter[i]) - { - usedcounter[i] = 1; - names[i] = name; - return i; - } - return -1; - } - - - void NgProfiler :: ClearTimers () - { - for (int i = 0; i < SIZE; i++) - { - tottimes[i] = 0; - counts[i] = 0; - } - } - - NgProfiler prof; -} diff --git a/libsrc/general/profiler.hpp b/libsrc/general/profiler.hpp deleted file mode 100644 index 98039114..00000000 --- a/libsrc/general/profiler.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef FILE_NG_PROFILER -#define FILE_NG_PROFILER - -/**************************************************************************/ -/* File: profiler.hpp */ -/* Author: Joachim Schoeberl */ -/* Date: 5. Jan. 2005 */ -/**************************************************************************/ - - - -#ifdef VTRACE -#include "vt_user.h" -#else - #define VT_USER_START(n) - #define VT_USER_END(n) - #define VT_TRACER(n) -#endif - - -// #define USE_TSC -#ifdef USE_TSC -#include // for __rdtsc() CPU time step counter -#endif - -namespace netgen -{ - -class NgProfiler -{ - enum { SIZE = 1000 }; - - static long int tottimes[SIZE]; - static long int starttimes[SIZE]; - static long int counts[SIZE]; - static string names[SIZE]; - static int usedcounter[SIZE]; - - int total_timer; -public: - NgProfiler(); - ~NgProfiler(); - static int CreateTimer (const string & name); -#ifndef USE_TSC - static void StartTimer (int nr) - { - starttimes[nr] = clock(); counts[nr]++; - // VT_USER_START (const_cast (names[nr].c_str())); - VT_USER_START ( (char * const) (names[nr].c_str())); - } - static void StopTimer (int nr) - { - tottimes[nr] += clock()-starttimes[nr]; - VT_USER_END (const_cast (names[nr].c_str())); - } -#else - static void StartTimer (int nr) - { - starttimes[nr] = __rdtsc(); counts[nr]++; - // VT_USER_START (const_cast (names[nr].c_str())); - // VT_USER_START ( (char * const) (names[nr].c_str())); - } - static void StopTimer (int nr) - { - tottimes[nr] += __rdtsc()-starttimes[nr]; - VT_USER_END (const_cast (names[nr].c_str())); - } -#endif - - - //static void Print (ostream & ost); - static void Print (FILE * prof); - - static void ClearTimers (); - - class RegionTimer - { - int nr; - public: - RegionTimer (int anr) : nr(anr) - { StartTimer (nr); } - ~RegionTimer () { StopTimer (nr); } - }; -}; - -} - -#endif diff --git a/libsrc/stlgeom/meshstlsurface.cpp b/libsrc/stlgeom/meshstlsurface.cpp index 4e267193..02753fb8 100644 --- a/libsrc/stlgeom/meshstlsurface.cpp +++ b/libsrc/stlgeom/meshstlsurface.cpp @@ -598,7 +598,6 @@ void STLSurfaceMeshing1 (STLGeometry & geom, for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++) { - if (fnr == 100) NgProfiler::ClearTimers(); if (!opensegsperface[fnr]) continue; if (multithread.terminate) return; From 5fa0cb850afef271b30a8c7963305ca70be4a5e7 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 11:54:28 +0100 Subject: [PATCH 14/28] Fix cmake error --- libsrc/general/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index f1c39183..f5c16e82 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -6,10 +6,6 @@ add_library(gen OBJECT mpi_interface.cpp gzstream.cpp ) -if(NOT WIN32) - target_link_libraries(gen ngcore) -endif(NOT WIN32) - set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(FILES From 58007f1eaf5eb8409f7affc09bba8a8a79ba4705 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 11:54:28 +0100 Subject: [PATCH 15/28] Fix cmake error --- libsrc/general/CMakeLists.txt | 4 ---- libsrc/gprim/CMakeLists.txt | 3 --- libsrc/linalg/CMakeLists.txt | 4 ---- 3 files changed, 11 deletions(-) diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index f1c39183..f5c16e82 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -6,10 +6,6 @@ add_library(gen OBJECT mpi_interface.cpp gzstream.cpp ) -if(NOT WIN32) - target_link_libraries(gen ngcore) -endif(NOT WIN32) - set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(FILES diff --git a/libsrc/gprim/CMakeLists.txt b/libsrc/gprim/CMakeLists.txt index ac4b8f11..3957476a 100644 --- a/libsrc/gprim/CMakeLists.txt +++ b/libsrc/gprim/CMakeLists.txt @@ -3,9 +3,6 @@ add_library(gprim OBJECT adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp ) -if(NOT WIN32) - target_link_libraries(gprim ngcore) -endif(NOT WIN32) set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) diff --git a/libsrc/linalg/CMakeLists.txt b/libsrc/linalg/CMakeLists.txt index 9f35d751..a5a5a4f2 100644 --- a/libsrc/linalg/CMakeLists.txt +++ b/libsrc/linalg/CMakeLists.txt @@ -4,10 +4,6 @@ add_library( la OBJECT set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) -if(NOT WIN32) - target_link_libraries(la ngcore) -endif(NOT WIN32) - install(FILES densemat.hpp linalg.hpp opti.hpp polynomial.hpp vector.hpp From 90de81f96e6d0eaee601f8c4431434d0ee118ab6 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 13:18:27 +0100 Subject: [PATCH 16/28] Fix wrong header include on Windows --- libsrc/core/utils.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index 2c88629d..c8dc1e9e 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -4,7 +4,12 @@ #include #include #include + +#ifdef WIN32 +#include // for __rdtsc() CPU time step counter +#else #include // for __rdtsc() CPU time step counter +#endif // WIN32 #include "ngcore_api.hpp" // for NGCORE_API From 74a4cd7d93bd485d01fe4eb07ddd04b7237ff043 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 13:18:27 +0100 Subject: [PATCH 17/28] Fix wrong header include on Windows --- libsrc/core/paje_trace.hpp | 1 - libsrc/core/utils.hpp | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index d2584487..2addc0e3 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -3,7 +3,6 @@ #include #include -#include // for __rdtsc() CPU time step counter #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index 2c88629d..c8dc1e9e 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -4,7 +4,12 @@ #include #include #include + +#ifdef WIN32 +#include // for __rdtsc() CPU time step counter +#else #include // for __rdtsc() CPU time step counter +#endif // WIN32 #include "ngcore_api.hpp" // for NGCORE_API From 8659e4aa84c6db40a4278559e980de87598b10e9 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 13:49:59 +0100 Subject: [PATCH 18/28] Remove double (class and method) NGCORE_API --- libsrc/core/symboltable.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/core/symboltable.hpp b/libsrc/core/symboltable.hpp index 53c07dd4..582a7a37 100644 --- a/libsrc/core/symboltable.hpp +++ b/libsrc/core/symboltable.hpp @@ -45,7 +45,7 @@ namespace ngcore } /// INDEX of symbol name, throws exception if unused - NGCORE_API size_t Index (const std::string & name) const + size_t Index (const std::string & name) const { for (size_t i = 0; i < names.size(); i++) if (names[i] == name) return i; @@ -53,7 +53,7 @@ namespace ngcore } /// Index of symbol name, returns -1 if unused - NGCORE_API int CheckIndex (const std::string & name) const + int CheckIndex (const std::string & name) const { for (int i = 0; i < names.size(); i++) if (names[i] == name) return i; From e46787dd5d8c04004d4322ae8b8286f42372dd52 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 7 Jan 2019 14:17:43 +0100 Subject: [PATCH 19/28] fixes for profiler to work with ngsolve --- libsrc/core/paje_trace.hpp | 8 ++++---- libsrc/core/profiler.cpp | 8 ++++---- libsrc/core/profiler.hpp | 6 ++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index d2584487..83c66bab 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -22,8 +22,8 @@ namespace ngcore std::shared_ptr logger = GetLogger("PajeTrace"); private: NGCORE_API static size_t max_tracefile_size; - static bool trace_thread_counter; - static bool trace_threads; + NGCORE_API static bool trace_thread_counter; + NGCORE_API static bool trace_threads; bool tracing_enabled; TTimePoint start_time; @@ -107,8 +107,8 @@ namespace ngcore PajeTrace() = delete; PajeTrace(const PajeTrace &) = delete; PajeTrace(PajeTrace &&) = delete; - PajeTrace(int anthreads, std::string aname = ""); - ~PajeTrace(); + NGCORE_API PajeTrace(int anthreads, std::string aname = ""); + NGCORE_API ~PajeTrace(); void operator=(const PajeTrace &) = delete; void operator=(PajeTrace &&) = delete; diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index e24de4e3..f738fd55 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -8,10 +8,10 @@ namespace ngcore std::string NgProfiler::filename; - size_t dummy_thread_times[NgProfiler::SIZE]; - size_t * NgProfiler::thread_times = dummy_thread_times; // NOLINT - size_t dummy_thread_flops[NgProfiler::SIZE]; - size_t * NgProfiler::thread_flops = dummy_thread_flops; // NOLINT + size_t NgProfiler::dummy_thread_times[NgProfiler::SIZE]; + size_t * NgProfiler::thread_times = NgProfiler::dummy_thread_times; // NOLINT + size_t NgProfiler::dummy_thread_flops[NgProfiler::SIZE]; + size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops; // NOLINT std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index 10a5cf0d..f7415881 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -35,9 +35,11 @@ namespace ngcore NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; NGCORE_API static std::shared_ptr logger; + NGCORE_API static size_t dummy_thread_times[NgProfiler::SIZE]; + NGCORE_API static size_t dummy_thread_flops[NgProfiler::SIZE]; private: - static std::string filename; + NGCORE_API static std::string filename; public: NgProfiler(); ~NgProfiler(); @@ -143,7 +145,7 @@ namespace ngcore - class Timer + class NGCORE_API Timer { int timernr; int priority; From 99c95757a3860ddd3c74f8ac4bc279117d21873f Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 7 Jan 2019 15:17:56 +0100 Subject: [PATCH 20/28] [ngcore] ngspickle ngcore_api --- libsrc/core/archive.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 6a4a0792..2848b8f1 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -943,7 +943,7 @@ namespace ngcore }; template - auto NGSPickle() + NGCORE_API auto NGSPickle() { return pybind11::pickle([](T* self) { From 247b2a289287de67a9a113cba9107f512d48552a Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 8 Jan 2019 11:26:29 +0100 Subject: [PATCH 21/28] [cmake] Replace object libraries with interface libraries --- libsrc/general/CMakeLists.txt | 14 +++++++------- libsrc/gprim/CMakeLists.txt | 10 +++++----- libsrc/linalg/CMakeLists.txt | 10 +++++----- libsrc/meshing/CMakeLists.txt | 12 +++--------- nglib/CMakeLists.txt | 5 +---- 5 files changed, 21 insertions(+), 30 deletions(-) diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index f5c16e82..3f6c2aad 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -1,13 +1,13 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(gen OBJECT - array.cpp bitarray.cpp dynamicmem.cpp flags.cpp - hashtabl.cpp mystring.cpp optmem.cpp parthreads.cpp - seti.cpp sort.cpp spbita2d.cpp table.cpp - mpi_interface.cpp gzstream.cpp +add_library(gen INTERFACE) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources(gen INTERFACE + ${sdir}/array.cpp ${sdir}/bitarray.cpp ${sdir}/dynamicmem.cpp ${sdir}/flags.cpp + ${sdir}/hashtabl.cpp ${sdir}/mystring.cpp ${sdir}/optmem.cpp ${sdir}/parthreads.cpp + ${sdir}/seti.cpp ${sdir}/sort.cpp ${sdir}/spbita2d.cpp ${sdir}/table.cpp + ${sdir}/mpi_interface.cpp ${sdir}/gzstream.cpp ) -set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) - install(FILES array.hpp autodiff.hpp autoptr.hpp bitarray.hpp dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp diff --git a/libsrc/gprim/CMakeLists.txt b/libsrc/gprim/CMakeLists.txt index 3957476a..402973dc 100644 --- a/libsrc/gprim/CMakeLists.txt +++ b/libsrc/gprim/CMakeLists.txt @@ -1,11 +1,11 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(gprim OBJECT - adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp - geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp +add_library(gprim INTERFACE) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources(gprim INTERFACE + ${sdir}/adtree.cpp ${sdir}/geom2d.cpp ${sdir}/geom3d.cpp ${sdir}/geomfuncs.cpp + ${sdir}/geomtest3d.cpp ${sdir}/transform3d.cpp ${sdir}/spline.cpp ${sdir}/splinegeometry.cpp ) -set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) - install(FILES adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp geomobjects2.hpp geomobjects.hpp geomops2.hpp geomops.hpp geomtest3d.hpp gprim.hpp diff --git a/libsrc/linalg/CMakeLists.txt b/libsrc/linalg/CMakeLists.txt index a5a5a4f2..a8ab1b5a 100644 --- a/libsrc/linalg/CMakeLists.txt +++ b/libsrc/linalg/CMakeLists.txt @@ -1,8 +1,8 @@ -add_library( la OBJECT - densemat.cpp polynomial.cpp bfgs.cpp linopt.cpp linsearch.cpp - ) - -set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) +add_library( la INTERFACE ) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources( la INTERFACE + ${sdir}/densemat.cpp ${sdir}/polynomial.cpp ${sdir}/bfgs.cpp ${sdir}/linopt.cpp ${sdir}/linsearch.cpp +) install(FILES densemat.hpp linalg.hpp opti.hpp diff --git a/libsrc/meshing/CMakeLists.txt b/libsrc/meshing/CMakeLists.txt index bc9f7f18..0c7433cc 100644 --- a/libsrc/meshing/CMakeLists.txt +++ b/libsrc/meshing/CMakeLists.txt @@ -1,12 +1,4 @@ add_definitions(-DNGINTERFACE_EXPORTS) -if(NOT WIN32) - set(mesh_object_libs - $ - $ - $ - ) -endif(NOT WIN32) - add_library(mesh ${NG_LIB_TYPE} adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp @@ -29,8 +21,10 @@ if(APPLE) set_target_properties( mesh PROPERTIES SUFFIX ".so") endif(APPLE) +target_link_libraries( mesh PUBLIC ngcore PRIVATE gprim la gen ) + if(NOT WIN32) - target_link_libraries( mesh ngcore ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) + target_link_libraries( mesh PUBLIC ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) install( TARGETS mesh ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/nglib/CMakeLists.txt b/nglib/CMakeLists.txt index ff8bd1d5..5f705c8c 100644 --- a/nglib/CMakeLists.txt +++ b/nglib/CMakeLists.txt @@ -8,9 +8,6 @@ if(WIN32) $ $ $ - $ - $ - $ $ $ @@ -32,7 +29,7 @@ if(NOT WIN32) endif(USE_GUI) endif(NOT WIN32) -target_link_libraries(nglib PUBLIC ngcore) +target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore) target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) From 460ee696fdf82b1c94d0c0fc91b0f259efd5bfd9 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 8 Jan 2019 11:30:11 +0100 Subject: [PATCH 22/28] [cmake] Link ngcore to other libraries --- CMakeLists.txt | 8 +++++++- libsrc/csg/CMakeLists.txt | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29a73670..cf153b4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,13 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL) endif(NOT CMAKE_BUILD_TYPE) -cmake_minimum_required(VERSION 3.1.3) +if(WIN32) + # we are linking to object libraries on Windows + cmake_minimum_required(VERSION 3.12) +else(WIN32) + cmake_minimum_required(VERSION 3.1.3) +endif(WIN32) + if(NOT WIN32) option( USE_NATIVE_ARCH "build which -march=native" ON) endif(NOT WIN32) diff --git a/libsrc/csg/CMakeLists.txt b/libsrc/csg/CMakeLists.txt index 224a48e4..d05d62c1 100644 --- a/libsrc/csg/CMakeLists.txt +++ b/libsrc/csg/CMakeLists.txt @@ -12,11 +12,11 @@ if(APPLE) endif(APPLE) if(NOT WIN32) - target_link_libraries(csg mesh ${PYTHON_LIBRARIES}) - target_link_libraries(csg ${PYTHON_LIBRARIES}) + target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES}) install( TARGETS csg ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries(csg PUBLIC ngcore) if(USE_GUI) add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp ) From 4a563f09affee6050ea983e99e639990500d4bdf Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 8 Jan 2019 13:12:12 +0100 Subject: [PATCH 23/28] Fix build errors on Windows --- libsrc/core/CMakeLists.txt | 3 ++- libsrc/core/archive.hpp | 2 +- libsrc/core/symboltable.hpp | 2 +- libsrc/core/utils.cpp | 3 +-- libsrc/geom2d/CMakeLists.txt | 2 ++ libsrc/occ/CMakeLists.txt | 6 ++++-- libsrc/stlgeom/CMakeLists.txt | 5 ++++- nglib/CMakeLists.txt | 3 ++- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index c43a79ab..46a2230b 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -29,6 +29,7 @@ install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) if(USE_PYTHON) target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON) target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS}) + target_link_libraries(ngcore PUBLIC ${PYTHON_LIBRARIES}) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp @@ -41,7 +42,7 @@ endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) if(USE_PYTHON) pybind11_add_module(pyngcore SHARED python_ngcore.cpp) - target_link_libraries(pyngcore PUBLIC ngcore) + target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES}) set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}") install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen) endif(USE_PYTHON) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 2848b8f1..6a4a0792 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -943,7 +943,7 @@ namespace ngcore }; template - NGCORE_API auto NGSPickle() + auto NGSPickle() { return pybind11::pickle([](T* self) { diff --git a/libsrc/core/symboltable.hpp b/libsrc/core/symboltable.hpp index 582a7a37..fdab713c 100644 --- a/libsrc/core/symboltable.hpp +++ b/libsrc/core/symboltable.hpp @@ -19,7 +19,7 @@ namespace ngcore Complexity by name access is linear, by index is constant. */ template - class NGCORE_API SymbolTable + class SymbolTable { std::vector names; std::vector data; diff --git a/libsrc/core/utils.cpp b/libsrc/core/utils.cpp index ae831447..82fcfb31 100644 --- a/libsrc/core/utils.cpp +++ b/libsrc/core/utils.cpp @@ -16,6 +16,7 @@ namespace ngcore nullptr, nullptr, &status); } +#endif double ticks_per_second = [] () noexcept { @@ -36,5 +37,3 @@ namespace ngcore } // namespace ngcore -#endif - diff --git a/libsrc/geom2d/CMakeLists.txt b/libsrc/geom2d/CMakeLists.txt index 754c79fb..26d0db92 100644 --- a/libsrc/geom2d/CMakeLists.txt +++ b/libsrc/geom2d/CMakeLists.txt @@ -9,6 +9,8 @@ if(NOT WIN32) install( TARGETS geom2d ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries(geom2d ngcore) + if(USE_GUI) add_library(geom2dvis ${NG_LIB_TYPE} vsgeom2d.cpp) if(NOT WIN32) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index a244e85b..1f093ad8 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -8,11 +8,13 @@ if(USE_GUI) add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) endif(USE_GUI) +target_link_libraries(occ PUBLIC ngcore) + if(NOT WIN32) - target_link_libraries( occ ngcore ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) + target_link_libraries( occ PUBLIC ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) install( TARGETS occ ${NG_INSTALL_DIR}) if (USE_GUI) - target_link_libraries( occvis occ ) + target_link_libraries( occvis PUBLIC occ ) install( TARGETS occvis ${NG_INSTALL_DIR}) endif(USE_GUI) endif(NOT WIN32) diff --git a/libsrc/stlgeom/CMakeLists.txt b/libsrc/stlgeom/CMakeLists.txt index 7b87a649..8925c828 100644 --- a/libsrc/stlgeom/CMakeLists.txt +++ b/libsrc/stlgeom/CMakeLists.txt @@ -4,10 +4,13 @@ add_library(stl ${NG_LIB_TYPE} ) if(NOT WIN32) - target_link_libraries( stl ngcore mesh ${PYTHON_LIBRARIES}) + target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) install( TARGETS stl ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries( stl ngcore ) + + if(USE_GUI) add_library(stlvis ${NG_LIB_TYPE} vsstl.cpp diff --git a/nglib/CMakeLists.txt b/nglib/CMakeLists.txt index 5f705c8c..7253230a 100644 --- a/nglib/CMakeLists.txt +++ b/nglib/CMakeLists.txt @@ -29,7 +29,8 @@ if(NOT WIN32) endif(USE_GUI) endif(NOT WIN32) -target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore) +# target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore) +target_link_libraries(nglib PUBLIC ngcore) target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) From bcb2935dbb703f6b3c3f974ca9473c8966362e7b Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 11 Jan 2019 10:34:07 +0100 Subject: [PATCH 24/28] Fix build errors --- libsrc/core/logging.hpp | 3 +++ libsrc/core/profiler.hpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index e0e3efd6..6d3a40c8 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -43,6 +43,9 @@ namespace spdlog class logger { public: + template + void log_helper() { std::clog << t; } + template void log_helper( T t) { std::clog << t; } diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index f7415881..96a3fc44 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -124,7 +124,7 @@ namespace ngcore static void SetName (int nr, const std::string & name) { timers[nr].name = name; } static std::string GetName (int nr) { return timers[nr].name; } /// print profile - NGCORE_API static void Print (FILE * ost); + NGCORE_API static void Print (FILE * prof); class RegionTimer { From 0b2011a4a60f240eeee08e48f9bbdf5ebb51058b Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 11 Jan 2019 13:12:45 +0100 Subject: [PATCH 25/28] Set timer names in paje trace --- libsrc/core/paje_trace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 873a93d7..b3abf262 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -427,7 +427,7 @@ namespace ngcore timer_ids.insert(t.id); for(auto id : timer_ids) - timer_aliases[id] = paje.DefineEntityValue( state_type_timer, "a timer" /* TODO: NgProfiler::GetName(id).c_str()*/, -1 ); + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id).c_str(), -1 ); int timerdepth = 0; int maxdepth = 0; From a40e70526ede50f04914c5c368a7b933e1a4918d Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 11 Jan 2019 13:25:43 +0100 Subject: [PATCH 26/28] Fix build errors --- libsrc/core/logging.hpp | 3 +-- libsrc/core/paje_trace.cpp | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index 6d3a40c8..d5fbf1ac 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -43,8 +43,7 @@ namespace spdlog class logger { public: - template - void log_helper() { std::clog << t; } + void log_helper() {} template void log_helper( T t) { std::clog << t; } diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index b3abf262..23d9e49e 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -7,6 +7,7 @@ #include "archive.hpp" // for Demangle #include "paje_trace.hpp" +#include "profiler.hpp" static constexpr int MAX_TRACE_LINE_SIZE = 50; extern const char *header; @@ -427,7 +428,7 @@ namespace ngcore timer_ids.insert(t.id); for(auto id : timer_ids) - timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id).c_str(), -1 ); + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id), -1 ); int timerdepth = 0; int maxdepth = 0; From 4aa7e76bd1e89c041e4109ac48e871fd7060f095 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 14 Jan 2019 13:04:27 +0100 Subject: [PATCH 27/28] MPI-Parallel output of profiler --- libsrc/core/profiler.cpp | 11 +++++++++++ libsrc/core/utils.cpp | 3 +++ libsrc/core/utils.hpp | 3 +++ libsrc/general/mpi_interface.hpp | 5 ++--- libsrc/general/netgenout.hpp | 5 +---- libsrc/meshing/global.cpp | 4 ---- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index f738fd55..29a69182 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -35,6 +35,17 @@ namespace ngcore fclose(prof); // NOLINT } + if (getenv ("NGPROFILE")) + { + std::string filename = "netgen.prof"; +#ifdef PARALLEL + filename += "."+ToString(id); +#endif + if (id == 0) logger->info( "write profile to file {}", filename ); + FILE *prof = fopen(filename.c_str(),"w"); // NOLINT + Print (prof); + fclose(prof); // NOLINT + } } void NgProfiler :: Print (FILE * prof) diff --git a/libsrc/core/utils.cpp b/libsrc/core/utils.cpp index 82fcfb31..0347d244 100644 --- a/libsrc/core/utils.cpp +++ b/libsrc/core/utils.cpp @@ -8,6 +8,9 @@ namespace ngcore { + // parallel netgen + int id = 0, ntasks = 1; + #ifdef WIN32 // windows does demangling in typeid(T).name() NGCORE_API std::string Demangle(const char* typeinfo) { return typeinfo; } diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index c8dc1e9e..da90e1d3 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -15,6 +15,9 @@ namespace ngcore { + // MPI rank, nranks TODO: Rename + extern NGCORE_API int id, ntasks; + NGCORE_API std::string Demangle(const char* typeinfo); #if defined(__GNUC__) diff --git a/libsrc/general/mpi_interface.hpp b/libsrc/general/mpi_interface.hpp index c45494b6..91cb0af3 100644 --- a/libsrc/general/mpi_interface.hpp +++ b/libsrc/general/mpi_interface.hpp @@ -14,9 +14,8 @@ namespace netgen { - - extern DLL_HEADER int id, ntasks; - + using ngcore::id; + using ngcore::ntasks; #ifdef PARALLEL diff --git a/libsrc/general/netgenout.hpp b/libsrc/general/netgenout.hpp index fafe495e..076a6df1 100644 --- a/libsrc/general/netgenout.hpp +++ b/libsrc/general/netgenout.hpp @@ -4,14 +4,11 @@ // #include // #include // #include +#include "mpi_interface.hpp" namespace netgen { -#ifdef PARALLEL -extern int id; -extern int ntasks; -#endif DLL_HEADER extern int printmessage_importance; DLL_HEADER extern int printdots; diff --git a/libsrc/meshing/global.cpp b/libsrc/meshing/global.cpp index df6bcece..e5036cde 100644 --- a/libsrc/meshing/global.cpp +++ b/libsrc/meshing/global.cpp @@ -50,10 +50,6 @@ namespace netgen string ngdir = "."; - // parallel netgen - int id = 0, ntasks = 1; - - void Ng_PrintDest(const char * s) { if (id == 0) From 9a20974418cefda94ee6cfab00349d94799302ba Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 14 Jan 2019 13:07:10 +0100 Subject: [PATCH 28/28] Disable SPDLOG by default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf153b4c..bf7980e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ option( USE_CCACHE "use ccache") option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON) option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) -option( USE_SPDLOG "Enable spd log logging" ON) +option( USE_SPDLOG "Enable spd log logging" OFF) option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF) option( CHECK_RANGE "Check array range access, automatically enabled if built in debug mode" OFF)