From 16bae31827f2075f70261e8ce4b57079a475649e Mon Sep 17 00:00:00 2001 From: acrovato <a.crovato@uliege.be> Date: Fri, 3 Jul 2020 12:26:12 +0200 Subject: [PATCH] Restart clean. fpm as submodule of waves (depends on fwk and tbox). Add timers. --- .clang-format | 8 +++ .gitlab-ci.yml | 23 +++++-- fpm/_src/CMakeLists.txt | 11 +++- fpm/_src/fpmw.h | 2 +- fpm/_src/fpmw.i | 31 +++++---- fpm/_src/fpmw.swg | 80 ----------------------- fpm/src/CMakeLists.txt | 6 +- fpm/src/fObject.h | 75 --------------------- fpm/src/fTimers.cpp | 97 ++++++++++++++++++++++++++++ fpm/src/fTimers.h | 76 ++++++++++++++++++++++ fpm/src/{fObject.cpp => fTimers.inl} | 36 ++++------- fpm/src/fpm.h | 19 ++---- fpm/tests/{basic.py => timers.py} | 29 +++++++-- 13 files changed, 269 insertions(+), 224 deletions(-) create mode 100644 .clang-format delete mode 100644 fpm/_src/fpmw.swg delete mode 100644 fpm/src/fObject.h create mode 100644 fpm/src/fTimers.cpp create mode 100644 fpm/src/fTimers.h rename fpm/src/{fObject.cpp => fTimers.inl} (60%) rename fpm/tests/{basic.py => timers.py} (55%) diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e5fd772 --- /dev/null +++ b/.clang-format @@ -0,0 +1,8 @@ +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +BasedOnStyle: LLVM +UseTab: Never +IndentWidth: 4 +BreakBeforeBraces: Allman +SortIncludes: false +ColumnLimit: 0 +AccessModifierOffset: -4 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6e1c814..90501d3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ # gitlab-ci file for fpm default: - image: rboman/waves-py3:2020.1 + image: rboman/waves-py3:2020.3 before_script: - source /opt/intel/mkl/bin/mklvars.sh intel64 - source /opt/intel/tbb/bin/tbbvars.sh intel64 @@ -11,14 +11,26 @@ stages: - test build: - image: rboman/waves-py3:2020.1 + image: rboman/waves-py3:2020.3 stage: build script: - printenv | sort + - cd .. + - rm -rf waves + - wget -q https://gitlab.uliege.be/am-dept/waves/-/archive/feature_fpm/waves-feature_fpm.tar.bz2 + - tar xf waves-feature_fpm.tar.bz2 + - rm waves-feature_fpm.tar.bz2 + - mv waves-feature_fpm waves + - cd waves + - mkdir build + - cd build + - cmake -Wno-dev -C ../CMake/disable-trilinos.cmake .. + - make -j $(nproc) + - cd ../../fpm - rm -rf build workspace - mkdir build - cd build - - cmake -Wno-dev .. + - cmake -DCMAKE_PREFIX_PATH=../../waves -Wno-dev .. - make -j $(nproc) artifacts: paths: @@ -37,8 +49,8 @@ doxygen: dependencies: - build -ctest-py3: - image: rboman/waves-py3:2020.1 +ctest: + image: rboman/waves-py3:2020.3 stage: test script: - cd build @@ -46,4 +58,3 @@ ctest-py3: #timeout: 10 hours # will be available in 12.3 dependencies: - build - diff --git a/fpm/_src/CMakeLists.txt b/fpm/_src/CMakeLists.txt index 059425a..a137601 100644 --- a/fpm/_src/CMakeLists.txt +++ b/fpm/_src/CMakeLists.txt @@ -22,8 +22,16 @@ FILE(GLOB ISRCS *.i) SET(CMAKE_SWIG_FLAGS "") SET_SOURCE_FILES_PROPERTIES(${ISRCS} PROPERTIES CPLUSPLUS ON) +FOREACH(dir ${WAVES_INCLUDE_DIRS}) + LIST(APPEND WAVES_SINCLUDE_DIRS "-I${dir}") +ENDFOREACH() +FOREACH(dir ${WAVES_SWIG_DIRS}) + LIST(APPEND WAVES_SINCLUDE_DIRS "-I${dir}") +ENDFOREACH() + SET(SWINCFLAGS -I${PROJECT_SOURCE_DIR}/fpm/src +${WAVES_SINCLUDE_DIRS} ) SET_SOURCE_FILES_PROPERTIES(${ISRCS} PROPERTIES SWIG_FLAGS "${SWINCFLAGS}") @@ -35,10 +43,11 @@ endif() MACRO_DebugPostfix(_fpmw) TARGET_INCLUDE_DIRECTORIES(_fpmw PRIVATE ${PROJECT_SOURCE_DIR}/fpm/_src + ${WAVES_SWIG_DIRS} ${PYTHON_INCLUDE_PATH} ) SWIG_LINK_LIBRARIES(fpmw - fpm ${PYTHON_LIBRARIES} + fpm ${WAVES_LIBRARIES} ${PYTHON_LIBRARIES} ) diff --git a/fpm/_src/fpmw.h b/fpm/_src/fpmw.h index 5967301..ce160ec 100644 --- a/fpm/_src/fpmw.h +++ b/fpm/_src/fpmw.h @@ -14,4 +14,4 @@ * limitations under the License. */ -#include "fObject.h" +#include "fTimers.h" diff --git a/fpm/_src/fpmw.i b/fpm/_src/fpmw.i index 2da4432..a9bb68b 100644 --- a/fpm/_src/fpmw.i +++ b/fpm/_src/fpmw.i @@ -36,34 +36,33 @@ threads="1" #include <sstream> #include <typeinfo> -#include "fpm.h" +#include "fwkw.h" +#include "tboxw.h" #include "fpmw.h" +#include "fpm.h" + %} -%include "fpmw.swg" +%include "fwkw.swg" +%import "tboxw.i" %include "fpm.h" -%include <std_shared_ptr.i> - -%shared_ptr(fpm::fSharedObject); -%include "fObject.h" +%include "fTimers.h" namespace fpm { - -%extend fObject { - std::string __str__() { - std::stringstream str; str << *self; - return str.str(); +%extend Timers { + Timer &getitem(std::string const &name) + { + return (*self)[name]; } -} -%extend fSharedObject { - std::string __str__() { - std::stringstream str; str << *self; - return str.str(); + %pythoncode { +def __getitem__(self, name): + return self.getitem(name) } } }; +//%include <std_shared_ptr.i> diff --git a/fpm/_src/fpmw.swg b/fpm/_src/fpmw.swg deleted file mode 100644 index 169ce32..0000000 --- a/fpm/_src/fpmw.swg +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2020 University of Liège - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - // common includes - -// !! mingw + c++11 + python: -// cmath doit être inclus AVANT Python.h (et en particulier pyconfig.h) -// car il renomme hypot en _hypoth (bidouille liée au visual) -%begin %{ -#if defined(_WIN32) && defined(__GNUC__) -#include <cmath> -#endif -%} - -// petite bidouille pour pouvoir compiler avec "threads=1" et iterer sur des std_vector -// (sinon ca explose � la destruction de l'iterateur) -%nothread swig::SwigPyIterator::~SwigPyIterator(); - -%include "std_string.i" -%include "exception.i" -%include "std_vector.i" -%include "std_list.i" -%include "std_map.i" - -// from: http://swig.10945.n7.nabble.com/Trapping-Swig-DirectorException-td6013.html -// le code suivant permet de voir la call stack dans les appels C++ => python - -%{ - static void handle_exception(void) { - try { - throw; - } catch (std::exception &e) { - std::stringstream txt; - txt << e.what(); // << ' ' << typeid(e).name(); - PyErr_SetString(PyExc_RuntimeError, e.what()); - } - catch(...) - { - PyErr_SetString(PyExc_RuntimeError, "Unknown C++ Runtime Error"); - } - } -%} - -%exception { - try { - $action - } catch (...) { - // Note that if a director method failed, the Python error indicator - // already contains full details of the exception, and it will be - // reraised when we go to SWIG_fail; so no need to convert the C++ - // exception back to a Python one - if (!PyErr_Occurred()) { - handle_exception(); - } - SWIG_fail; - } -} - -%feature("director:except") { - if ($error != NULL) { - throw Swig::DirectorMethodException(); - } -} - - -%ignore operator<<; - diff --git a/fpm/src/CMakeLists.txt b/fpm/src/CMakeLists.txt index e19d83a..54ef33c 100644 --- a/fpm/src/CMakeLists.txt +++ b/fpm/src/CMakeLists.txt @@ -32,5 +32,9 @@ FIND_PACKAGE(EIGEN 3.3.4 REQUIRED) TARGET_INCLUDE_DIRECTORIES(fpm PUBLIC ${EIGEN_INCLUDE_DIRS}) TARGET_COMPILE_DEFINITIONS(fpm PUBLIC EIGEN_DONT_PARALLELIZE) -SOURCE_GROUP(base REGULAR_EXPRESSION ".*\\.(cpp|inl|hpp|h)") +# -- WAVES +FIND_PACKAGE(WAVES REQUIRED) +TARGET_INCLUDE_DIRECTORIES(fpm PUBLIC ${WAVES_INCLUDE_DIRS}) +TARGET_LINK_LIBRARIES(fpm ${WAVES_LIBRARIES}) +SOURCE_GROUP(base REGULAR_EXPRESSION ".*\\.(cpp|inl|hpp|h)") diff --git a/fpm/src/fObject.h b/fpm/src/fObject.h deleted file mode 100644 index 27a6948..0000000 --- a/fpm/src/fObject.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2020 University of Liège - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FOBJECT_H -#define FOBJECT_H - -#include "fpm.h" -#include <iostream> - -namespace fpm -{ - -/** - * @brief Base class of all virtual objects - * - * The only purpose of this class is that it avoids many copy/paste for - * the print function (__str__() fct) in SWIG/python - */ - -class FPM_API fObject -{ -public: - fObject() = default; - virtual ~fObject() {} - fObject(const fObject &) = delete; - fObject &operator=(const fObject &) = delete; - -#ifndef SWIG - friend FPM_API std::ostream &operator<<(std::ostream &out, fObject const &obj); - virtual void write(std::ostream &out) const; -#endif -}; - -/** - * @brief Base class of smart-pointed objects (shared_ptr) - * - * This base class is only required for "print" in SWIG/python. - * std::cout << *o works from C++ (it calls "write") even if the object inherits from wObject - * which is not defined in SWIG as shared_ptr-managed object - * However "print o" fails in python if the shared object inherits from wObject. - * This class also avoids a warning in SWIG telling that some derived or base classes are not - * managed by shared_ptr. - */ - -class FPM_API fSharedObject -{ -public: - fSharedObject() = default; - virtual ~fSharedObject() {} - fSharedObject(const fSharedObject &) = delete; - fSharedObject &operator=(const fSharedObject &) = delete; - -#ifndef SWIG - friend FPM_API std::ostream &operator<<(std::ostream &out, fSharedObject const &obj); - virtual void write(std::ostream &out) const; -#endif -}; - -} // namespace fpm - -#endif //FOBJECT_H - diff --git a/fpm/src/fTimers.cpp b/fpm/src/fTimers.cpp new file mode 100644 index 0000000..f2d6838 --- /dev/null +++ b/fpm/src/fTimers.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fTimers.h" +#include <iomanip> + +using namespace fpm; + +Timer::Timer() : isOn(false) +{ + reset(); +} + +/** + * @brief Reset the timer + */ +void Timer::reset() +{ + if (!isOn) + { + start(); + stop(); + } + else + throw std::runtime_error("Cannot reset a running timer!\n"); +} + +/** + * @brief Start the timer + */ +void Timer::start() +{ + if (!isOn) + { + tS = std::chrono::high_resolution_clock::now(); + cS = std::clock(); + isOn = true; + } + else + throw std::runtime_error("Cannot start a running timer!\n"); +} + +/** + * @brief Stop the timer + */ +void Timer::stop() +{ + if (isOn) + { + tE = std::chrono::high_resolution_clock::now(); + cE = std::clock(); + isOn = false; + } + else + throw std::runtime_error("Cannot stop a non-running timer!\n"); +} + +/** + * @brief Access/create a given timer + */ +Timer &Timers::operator[](std::string const &name) +{ + return timers[name]; +} + +/** + * @brief Print the times of all timers + */ +void Timers::write(std::ostream &out) const +{ + out << std::fixed << std::setprecision(1); + out << std::setw(20) << std::left << "Timer" + << std::setw(15) << std::right << "Wall-clock (s)" + << std::setw(15) << std::right << "CPU (s)" + << std::endl; + + for (auto const tm : timers) + { + out << std::setw(20) << std::left << tm.first + << std::setw(15) << std::right << tm.second.getWall() + << std::setw(15) << std::right << tm.second.getCpu() + << std::endl; + } +} diff --git a/fpm/src/fTimers.h b/fpm/src/fTimers.h new file mode 100644 index 0000000..510df45 --- /dev/null +++ b/fpm/src/fTimers.h @@ -0,0 +1,76 @@ +/* + * Copyright 2020 University of Liège + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FTIMERS_H +#define FTIMERS_H + +#include "fpm.h" +#include "wObject.h" +#include <map> +#include <chrono> + +namespace fpm +{ + +/** + * @brief Basic and portable timer + * @author Adrien Crovato + * @todo use clock_gettime for POSIX (https://en.cppreference.com/w/cpp/chrono/c/clock)? + */ +class FPM_API Timer +{ +private: + bool isOn; ///< status + std::chrono::high_resolution_clock::time_point tS; ///< start time (wall-clock) + std::chrono::high_resolution_clock::time_point tE; ///< stop time (wall-clock) + std::clock_t cS; ///< start time (cpu) + std::clock_t cE; ///< stop time (cpu) + +public: + Timer(); + virtual ~Timer() {} + + void reset(); + void start(); + void stop(); + inline double getWall() const; + inline double getCpu() const; +}; + +#include "fTimers.inl" + +/** + * @brief Collection of timers + * @author Romain Boman, Adrien Crovato + */ +class FPM_API Timers : public fwk::wObject +{ +private: + std::map<std::string, Timer> timers; ///< set of timers + +public: + Timers() : fwk::wObject() {} + virtual ~Timers() {} + +#ifndef SWIG + Timer &operator[](std::string const &name); + virtual void write(std::ostream &out) const override; +#endif //SWIG +}; + +} // namespace fpm + +#endif //FTIMERS_H diff --git a/fpm/src/fObject.cpp b/fpm/src/fTimers.inl similarity index 60% rename from fpm/src/fObject.cpp rename to fpm/src/fTimers.inl index 55e8ca7..1fae112 100644 --- a/fpm/src/fObject.cpp +++ b/fpm/src/fTimers.inl @@ -14,32 +14,18 @@ * limitations under the License. */ -#include "fObject.h" - -namespace fpm -{ - -FPM_API std::ostream & -operator<<(std::ostream &out, fObject const &obj) -{ - obj.write(out); - return out; -} - -void fObject::write(std::ostream &out) const -{ -} - -FPM_API std::ostream & -operator<<(std::ostream &out, fSharedObject const &obj) +/** + * @brief Compute the wall-clock (ellasped) time from "start" to "stop" + */ +inline double Timer::getWall() const { - obj.write(out); - return out; + return std::chrono::duration<double>(tE - tS).count(); } -void fSharedObject::write(std::ostream &out) const +/** + * @brief Compute the cpu (user) time from "start" to "stop" + */ +inline double Timer::getCpu() const { -} - -} // namespace fpm - + return (cE - cS) / (double)CLOCKS_PER_SEC; +} \ No newline at end of file diff --git a/fpm/src/fpm.h b/fpm/src/fpm.h index e925020..e408ab5 100644 --- a/fpm/src/fpm.h +++ b/fpm/src/fpm.h @@ -29,26 +29,15 @@ #define FPM_API #endif -#ifdef _MSC_VER -#if !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -#pragma warning(disable : 4251) // DLL/templates non exportes -#pragma warning(disable : 4275) // non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' - -#define NOMINMAX // avoids the definition of "min/max" macro in <minwindef.h> (which could shadow std::max) - -#endif //_MSC_VER - +#include "tbox.h" namespace fpm { -class fObject; +// utilities +class fTimer; +class fTimers; } // namespace fpm - #endif //FPM_H - diff --git a/fpm/tests/basic.py b/fpm/tests/timers.py similarity index 55% rename from fpm/tests/basic.py rename to fpm/tests/timers.py index 6da436c..1c66613 100644 --- a/fpm/tests/basic.py +++ b/fpm/tests/timers.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright 2020 University of Liège @@ -15,17 +15,38 @@ # See the License for the specific language governing permissions and # limitations under the License. -# basic test +# Test the timers +# Adrien Crovato import fpm +import time from fwk.testing import * from fwk.coloring import ccolors def main(): - a = 10.0 + tms = fpm.Timers() + tms['1'].start() + time.sleep(0.3) + tms['1'].stop() + tms['2'].start() + tic = time.perf_counter() + dummy() + toc = time.perf_counter() + tms['2'].stop() + print(ccolors.ANSI_BLUE + 'PyTiming...' + ccolors.ANSI_RESET) + print(tms) + print(ccolors.ANSI_BLUE + 'PyTesting...' + ccolors.ANSI_RESET) tests = CTests() - tests.add(CTest('test', a, 10., 1e-2)) + tests.add(CTest('1w', tms['1'].getWall(), 0.3, 2e-2)) + tests.add(CTest('1u', tms['1'].getCpu(), 0.0, 1e-2)) + tests.add(CTest('2w', tms['2'].getWall(), toc - tic, 2e-2)) + tests.add(CTest('2u', tms['2'].getCpu(), toc - tic, 2e-2)) + tests.run() + +def dummy(): + for i in range(0, int(1e7)): + a = 1+1 if __name__ == '__main__': main() -- GitLab