Skip to content
Snippets Groups Projects
Commit 16bae318 authored by Adrien Crovato's avatar Adrien Crovato
Browse files

Restart clean. fpm as submodule of waves (depends on fwk and tbox). Add timers.

parent 696fb5ad
No related branches found
No related tags found
1 merge request!1Version 0.1.0 (setup)
Pipeline #1562 failed
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle: LLVM
UseTab: Never
IndentWidth: 4
BreakBeforeBraces: Allman
SortIncludes: false
ColumnLimit: 0
AccessModifierOffset: -4
# gitlab-ci file for fpm # gitlab-ci file for fpm
default: default:
image: rboman/waves-py3:2020.1 image: rboman/waves-py3:2020.3
before_script: before_script:
- source /opt/intel/mkl/bin/mklvars.sh intel64 - source /opt/intel/mkl/bin/mklvars.sh intel64
- source /opt/intel/tbb/bin/tbbvars.sh intel64 - source /opt/intel/tbb/bin/tbbvars.sh intel64
...@@ -11,14 +11,26 @@ stages: ...@@ -11,14 +11,26 @@ stages:
- test - test
build: build:
image: rboman/waves-py3:2020.1 image: rboman/waves-py3:2020.3
stage: build stage: build
script: script:
- printenv | sort - 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 - rm -rf build workspace
- mkdir build - mkdir build
- cd build - cd build
- cmake -Wno-dev .. - cmake -DCMAKE_PREFIX_PATH=../../waves -Wno-dev ..
- make -j $(nproc) - make -j $(nproc)
artifacts: artifacts:
paths: paths:
...@@ -37,8 +49,8 @@ doxygen: ...@@ -37,8 +49,8 @@ doxygen:
dependencies: dependencies:
- build - build
ctest-py3: ctest:
image: rboman/waves-py3:2020.1 image: rboman/waves-py3:2020.3
stage: test stage: test
script: script:
- cd build - cd build
...@@ -46,4 +58,3 @@ ctest-py3: ...@@ -46,4 +58,3 @@ ctest-py3:
#timeout: 10 hours # will be available in 12.3 #timeout: 10 hours # will be available in 12.3
dependencies: dependencies:
- build - build
...@@ -22,8 +22,16 @@ FILE(GLOB ISRCS *.i) ...@@ -22,8 +22,16 @@ FILE(GLOB ISRCS *.i)
SET(CMAKE_SWIG_FLAGS "") SET(CMAKE_SWIG_FLAGS "")
SET_SOURCE_FILES_PROPERTIES(${ISRCS} PROPERTIES CPLUSPLUS ON) 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 SET(SWINCFLAGS
-I${PROJECT_SOURCE_DIR}/fpm/src -I${PROJECT_SOURCE_DIR}/fpm/src
${WAVES_SINCLUDE_DIRS}
) )
SET_SOURCE_FILES_PROPERTIES(${ISRCS} PROPERTIES SWIG_FLAGS "${SWINCFLAGS}") SET_SOURCE_FILES_PROPERTIES(${ISRCS} PROPERTIES SWIG_FLAGS "${SWINCFLAGS}")
...@@ -35,10 +43,11 @@ endif() ...@@ -35,10 +43,11 @@ endif()
MACRO_DebugPostfix(_fpmw) MACRO_DebugPostfix(_fpmw)
TARGET_INCLUDE_DIRECTORIES(_fpmw PRIVATE ${PROJECT_SOURCE_DIR}/fpm/_src TARGET_INCLUDE_DIRECTORIES(_fpmw PRIVATE ${PROJECT_SOURCE_DIR}/fpm/_src
${WAVES_SWIG_DIRS}
${PYTHON_INCLUDE_PATH} ${PYTHON_INCLUDE_PATH}
) )
SWIG_LINK_LIBRARIES(fpmw SWIG_LINK_LIBRARIES(fpmw
fpm ${PYTHON_LIBRARIES} fpm ${WAVES_LIBRARIES} ${PYTHON_LIBRARIES}
) )
...@@ -14,4 +14,4 @@ ...@@ -14,4 +14,4 @@
* limitations under the License. * limitations under the License.
*/ */
#include "fObject.h" #include "fTimers.h"
...@@ -36,34 +36,33 @@ threads="1" ...@@ -36,34 +36,33 @@ threads="1"
#include <sstream> #include <sstream>
#include <typeinfo> #include <typeinfo>
#include "fpm.h" #include "fwkw.h"
#include "tboxw.h"
#include "fpmw.h" #include "fpmw.h"
#include "fpm.h"
%} %}
%include "fpmw.swg" %include "fwkw.swg"
%import "tboxw.i"
%include "fpm.h" %include "fpm.h"
%include <std_shared_ptr.i> %include "fTimers.h"
%shared_ptr(fpm::fSharedObject);
%include "fObject.h"
namespace fpm { namespace fpm {
%extend Timers {
%extend fObject { Timer &getitem(std::string const &name)
std::string __str__() { {
std::stringstream str; str << *self; return (*self)[name];
return str.str();
} }
}
%extend fSharedObject { %pythoncode {
std::string __str__() { def __getitem__(self, name):
std::stringstream str; str << *self; return self.getitem(name)
return str.str();
} }
} }
}; };
//%include <std_shared_ptr.i>
/*
* 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<<;
...@@ -32,5 +32,9 @@ FIND_PACKAGE(EIGEN 3.3.4 REQUIRED) ...@@ -32,5 +32,9 @@ FIND_PACKAGE(EIGEN 3.3.4 REQUIRED)
TARGET_INCLUDE_DIRECTORIES(fpm PUBLIC ${EIGEN_INCLUDE_DIRS}) TARGET_INCLUDE_DIRECTORIES(fpm PUBLIC ${EIGEN_INCLUDE_DIRS})
TARGET_COMPILE_DEFINITIONS(fpm PUBLIC EIGEN_DONT_PARALLELIZE) 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)")
/*
* 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;
}
}
...@@ -14,62 +14,63 @@ ...@@ -14,62 +14,63 @@
* limitations under the License. * limitations under the License.
*/ */
#ifndef FOBJECT_H #ifndef FTIMERS_H
#define FOBJECT_H #define FTIMERS_H
#include "fpm.h" #include "fpm.h"
#include <iostream> #include "wObject.h"
#include <map>
#include <chrono>
namespace fpm namespace fpm
{ {
/** /**
* @brief Base class of all virtual objects * @brief Basic and portable timer
* * @author Adrien Crovato
* The only purpose of this class is that it avoids many copy/paste for * @todo use clock_gettime for POSIX (https://en.cppreference.com/w/cpp/chrono/c/clock)?
* the print function (__str__() fct) in SWIG/python
*/ */
class FPM_API Timer
class FPM_API fObject
{ {
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: public:
fObject() = default; Timer();
virtual ~fObject() {} virtual ~Timer() {}
fObject(const fObject &) = delete;
fObject &operator=(const fObject &) = delete;
#ifndef SWIG void reset();
friend FPM_API std::ostream &operator<<(std::ostream &out, fObject const &obj); void start();
virtual void write(std::ostream &out) const; void stop();
#endif inline double getWall() const;
inline double getCpu() const;
}; };
#include "fTimers.inl"
/** /**
* @brief Base class of smart-pointed objects (shared_ptr) * @brief Collection of timers
* * @author Romain Boman, Adrien Crovato
* 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 Timers : public fwk::wObject
class FPM_API fSharedObject
{ {
private:
std::map<std::string, Timer> timers; ///< set of timers
public: public:
fSharedObject() = default; Timers() : fwk::wObject() {}
virtual ~fSharedObject() {} virtual ~Timers() {}
fSharedObject(const fSharedObject &) = delete;
fSharedObject &operator=(const fSharedObject &) = delete;
#ifndef SWIG #ifndef SWIG
friend FPM_API std::ostream &operator<<(std::ostream &out, fSharedObject const &obj); Timer &operator[](std::string const &name);
virtual void write(std::ostream &out) const; virtual void write(std::ostream &out) const override;
#endif #endif //SWIG
}; };
} // namespace fpm } // namespace fpm
#endif //FOBJECT_H #endif //FTIMERS_H
...@@ -14,32 +14,18 @@ ...@@ -14,32 +14,18 @@
* limitations under the License. * limitations under the License.
*/ */
#include "fObject.h" /**
* @brief Compute the wall-clock (ellasped) time from "start" to "stop"
namespace fpm */
{ inline double Timer::getWall() const
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)
{ {
obj.write(out); return std::chrono::duration<double>(tE - tS).count();
return out;
} }
void fSharedObject::write(std::ostream &out) const /**
* @brief Compute the cpu (user) time from "start" to "stop"
*/
inline double Timer::getCpu() const
{ {
} return (cE - cS) / (double)CLOCKS_PER_SEC;
}
} // namespace fpm \ No newline at end of file
...@@ -29,26 +29,15 @@ ...@@ -29,26 +29,15 @@
#define FPM_API #define FPM_API
#endif #endif
#ifdef _MSC_VER #include "tbox.h"
#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
namespace fpm namespace fpm
{ {
class fObject; // utilities
class fTimer;
class fTimers;
} // namespace fpm } // namespace fpm
#endif //FPM_H #endif //FPM_H
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2020 University of Liège # Copyright 2020 University of Liège
...@@ -15,17 +15,38 @@ ...@@ -15,17 +15,38 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# basic test # Test the timers
# Adrien Crovato
import fpm import fpm
import time
from fwk.testing import * from fwk.testing import *
from fwk.coloring import ccolors from fwk.coloring import ccolors
def main(): 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) print(ccolors.ANSI_BLUE + 'PyTesting...' + ccolors.ANSI_RESET)
tests = CTests() 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__': if __name__ == '__main__':
main() main()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment