diff --git a/Examples/python/fitting/ex09_FitSpecular/FitSpecularBasics.py b/Examples/python/fitting/ex09_FitSpecular/FitSpecularBasics.py index 29b5044add9288d85955fbb3532f711c9199f63a..4b1ac76424ff30870d246bc602289976d0611469 100644 --- a/Examples/python/fitting/ex09_FitSpecular/FitSpecularBasics.py +++ b/Examples/python/fitting/ex09_FitSpecular/FitSpecularBasics.py @@ -85,7 +85,7 @@ def make_axis(ax_values): name = "inc_angles" nbins = ax_values.size boundaries = np.array([(ax_values[i] + ax_values[i+1])/2 - for i in xrange(nbins-1)]) + for i in range(nbins-1)]) boundaries = np.insert(boundaries, 0, 2 * boundaries[0] - boundaries[1]) boundaries = np.insert(boundaries, nbins, 2 * boundaries[-1] - boundaries[-2]) return ba.VariableBinAxis(name, nbins, boundaries) diff --git a/Tests/Functional/Core/CoreSpecial/CMakeLists.txt b/Tests/Functional/Core/CoreSpecial/CMakeLists.txt index 4e6a77ba7d925c33fb6f1c7a6cd39a42391e6464..3c936a4059232f8b0ea47497968a4b7d60ed92bc 100644 --- a/Tests/Functional/Core/CoreSpecial/CMakeLists.txt +++ b/Tests/Functional/Core/CoreSpecial/CMakeLists.txt @@ -4,6 +4,7 @@ set(test_cases BatchSimulation PolDWBAMagCylinders # CoreIO +# DetectorTest ) file(GLOB source_files "*.cpp") diff --git a/Tests/Functional/Core/CoreSpecial/CoreSpecialTestFactory.cpp b/Tests/Functional/Core/CoreSpecial/CoreSpecialTestFactory.cpp index 5087711ea064bf3667c96b79c71074d0d8152d77..f61c1a8c36a165c9542917397d7dc48f4b8e9787 100644 --- a/Tests/Functional/Core/CoreSpecial/CoreSpecialTestFactory.cpp +++ b/Tests/Functional/Core/CoreSpecial/CoreSpecialTestFactory.cpp @@ -15,6 +15,7 @@ #include "CoreSpecialTestFactory.h" #include "BatchSimulation.h" +#include "DetectorTest.h" #include "PolDWBAMagCylinders.h" #include "CoreIOTest.h" @@ -31,4 +32,8 @@ CoreSpecialTestFactory::CoreSpecialTestFactory() registerItem("CoreIO", create_new<CoreIOTest>, "Input/output of heavy files"); + + registerItem("DetectorTest", + create_new<DetectorTest>, + "Performance on set of detectors of different size"); } diff --git a/Tests/Functional/Core/CoreSpecial/DetectorTest.cpp b/Tests/Functional/Core/CoreSpecial/DetectorTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba574f6431cd1d0dd2499c5c08022809ed074db3 --- /dev/null +++ b/Tests/Functional/Core/CoreSpecial/DetectorTest.cpp @@ -0,0 +1,164 @@ +#include "Benchmark.h" +#include "DetectorTest.h" +#include "GISASSimulation.h" +#include "RectangularDetector.h" +#include "SampleBuilderFactory.h" +#include "SimulationElement.h" +#include "SphericalDetector.h" +#include "Units.h" +#include <iomanip> + +namespace +{ +// functions for setting up and running simulations +RectangularDetector rectangularDetector(size_t size); +SphericalDetector sphericalDetector(size_t size); +std::unique_ptr<Instrument> createInstrument(const IDetector& detector); +std::unique_ptr<GISASSimulation> createSimulation(const Instrument& instr); +void test_sim_elements(const IDetector& detector); +void test_run_simulation(const IDetector& detector); + +// creating formatted strings for output +template<typename T> +std::string makeString(T value); +} + +DetectorTest::DetectorTest() + : m_input_parameters{{32, 1000}, + {128, 50}, + {512, 4}, + {1024, 1}, + {2048, 1}} + , m_data_table(createTableWithHeader()) + , m_init_table_size(m_data_table.size()) +{} + +DetectorTest::~DetectorTest() = default; + +bool DetectorTest::runTest() +{ + std::cout << "Runnging LargeDetectorTest..." << std::endl; + + for (const auto& test_config: m_input_parameters) { + const size_t detector_size = test_config.first; + const int number_of_runs = test_config.second; + auto result = runSingleSizeDetectorTest(detector_size, number_of_runs); + writeDataToTable(std::move(result), number_of_runs); + } + + printResult(); + + return true; +} + +std::unique_ptr<Benchmark> DetectorTest::runSingleSizeDetectorTest(size_t size, + int run_n_times) const +{ + std::unique_ptr<Benchmark> bench(new Benchmark); + + bench->test_method("elements_rect", + [size]() { test_sim_elements(rectangularDetector(size)); }, run_n_times); + bench->test_method("run_rect", + [size]() { test_run_simulation(rectangularDetector(size)); }, run_n_times); + bench->test_method("elements_spher", + [size]() { test_sim_elements(sphericalDetector(size)); }, run_n_times); + bench->test_method("run_spher", + [size]() { test_run_simulation(sphericalDetector(size)); }, run_n_times); + + return bench; +} + +DetectorTest::OutputDataTable DetectorTest::createTableWithHeader() const +{ + OutputDataTable data_table; + data_table.push_back(makeString("Parameters")); + data_table.push_back(makeString("Runs")); + for (const auto& test_conf: m_input_parameters) { + const std::string dim = std::to_string(test_conf.first); + data_table[0] += makeString(dim + "x" + dim); + data_table[1] += makeString(test_conf.second); + } + return data_table; +} + +void DetectorTest::writeDataToTable(std::unique_ptr<Benchmark> test_result, int n_runs) +{ + const auto& result_data = test_result->retrieveData(); + size_t i = m_init_table_size; + for (auto iter = result_data.begin(); iter != result_data.end(); ++iter, ++i) { + if (i + 1 > m_data_table.size()) + m_data_table.push_back(makeString(iter->first)); + m_data_table[i] += makeString(iter->second->runTime() / n_runs); + } +} + +void DetectorTest::printResult() +{ + for (const auto& str: m_data_table) + std::cout << str << std::endl; +} + +namespace +{ +void test_sim_elements(const IDetector& detector) +{ + auto instr = createInstrument(detector); + instr->initDetector(); + instr->createSimulationElements(); +} + +void test_run_simulation(const IDetector& detector) +{ + auto instr = createInstrument(detector); + auto simulation = createSimulation(*instr); + simulation->runSimulation(); +} + +RectangularDetector rectangularDetector(size_t size) +{ + const double width_mm = 10; + const double height_mm = 10; + const double distance_mm = 10; + RectangularDetector detector(size, width_mm, size, height_mm); + detector.setPerpendicularToReflectedBeam(distance_mm); + return detector; +} + +SphericalDetector sphericalDetector(size_t size) +{ + return SphericalDetector(size, -2.0 * Units::degree, 2.0 * Units::degree, size, + 0.0 * Units::degree, 2.0 * Units::degree); +} + +std::unique_ptr<Instrument> createInstrument(const IDetector& detector) +{ + const kvector_t zplus(0.0, 0.0, 1.0); + + std::unique_ptr<Instrument> result(new Instrument); + result->setBeamParameters(1.0 * Units::angstrom, 0.2 * Units::degree, 0.0 * Units::degree); + result->setBeamPolarization(zplus); + result->setDetector(detector); + result->setAnalyzerProperties(zplus, 1.0, 0.5); + return result; +} + +std::unique_ptr<GISASSimulation> createSimulation(const Instrument& instr) +{ + std::unique_ptr<GISASSimulation> result(new GISASSimulation()); + result->setInstrument(instr); + + SampleBuilderFactory sampleFactory; + std::shared_ptr<class IMultiLayerBuilder> builder( + sampleFactory.create("MagneticSubstrateZeroFieldBuilder").release()); + result->setSampleBuilder(builder); + return result; +} + +template<typename T> +std::string makeString(T value) { + static const size_t cell_width = 20; + std::ostringstream output_stream; + output_stream << std::setw(cell_width) << std::setfill(' ') << value; + return output_stream.str(); +} +} diff --git a/Tests/Functional/Core/CoreSpecial/DetectorTest.h b/Tests/Functional/Core/CoreSpecial/DetectorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..efa4611c9bef5bafad8342d9e339858b42e81bd8 --- /dev/null +++ b/Tests/Functional/Core/CoreSpecial/DetectorTest.h @@ -0,0 +1,58 @@ +// ************************************************************************** // +// +// BornAgain: simulate and fit scattering at grazing incidence +// +//! @file Tests/Functional/Core/CoreSpecial/DetectorTest.h +//! @brief Defines class DetectorTest +//! +//! @homepage http://www.bornagainproject.org +//! @license GNU General Public License v3 or higher (see COPYING) +//! @copyright Forschungszentrum Jülich GmbH 2017 +//! @authors Scientific Computing Group at MLZ Garching +//! @authors J. Burle, J. M. Fisher, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke +// +// ************************************************************************** // + +#ifndef DETECTORTEST_H +#define DETECTORTEST_H + +#include "IFunctionalTest.h" +#include <vector> + +class Simulation; +class Benchmark; + +//! Functional test for measuring simulation performance on detectors of different sizes. +//! No comparison with reference data provided since it is not the concern +//! of the test. + +class DetectorTest : public IFunctionalTest +{ +public: + DetectorTest(); + virtual ~DetectorTest(); + +private: + typedef std::vector<std::string> OutputDataTable; + + virtual bool runTest() override; + + //! Runs tests on a detector of size \f$ size \cross size \f$. + //! _run_n_times_ is the number of repetitions + std::unique_ptr<Benchmark> runSingleSizeDetectorTest(size_t size, int run_n_times) const; + + //! Creates a table with header and no content + OutputDataTable createTableWithHeader() const; + + //! Writes data to table + void writeDataToTable(std::unique_ptr<Benchmark> test_result, int n_runs); + + void printResult(); + + //! Vector of pairs (detector size, number of runs) for running subtests + const std::vector<std::pair<size_t, int>> m_input_parameters; + OutputDataTable m_data_table; //!< output data table with running times + const size_t m_init_table_size; +}; + +#endif // DETECTOR_H diff --git a/Tests/Functional/TestMachinery/Benchmark.h b/Tests/Functional/TestMachinery/Benchmark.h index f84c04a32fc18936cbc3f826a84dfd65e59a9b73..7b82cf12214dcd61287e768d94db0926d0dd8d87 100644 --- a/Tests/Functional/TestMachinery/Benchmark.h +++ b/Tests/Functional/TestMachinery/Benchmark.h @@ -40,6 +40,7 @@ private: class BA_CORE_API_ Benchmark { + typedef OrderedMap<std::string, Duration*> BenchmarkMap; public: Benchmark() {} ~Benchmark(); @@ -48,11 +49,12 @@ public: void stop(const std::string& name); double runTime(const std::string& name); std::string report() const; + const BenchmarkMap& retrieveData() const {return m_data;} void test_method(const std::string& name, std::function<void(void)> f, int ntries); private: - OrderedMap<std::string, Duration* > m_data; + BenchmarkMap m_data; }; #endif // COREIOTEST_H diff --git a/dev-tools/log/perf_history.txt b/dev-tools/log/perf_history.txt index c40b8fe43db0a9247cdacd0912b80a56eb003567..970d5a3315efd16149429ff0602c2d4721899264 100644 --- a/dev-tools/log/perf_history.txt +++ b/dev-tools/log/perf_history.txt @@ -635,10 +635,12 @@ domain2gui: 1.136, gui2domain: 1.734, realTime: 1.274 # after qtpropertybrowserframework removal compile time: real 4m29.715s, user 25m18.486s, sys 1m53.298s -# after unit tests refactoring (no numerics in functional tests), after SessionModel refactoring -| date | hostname | sysinfo | python | total cpu | total wall | MultiLayer | CylindersInDWBA | RotatedPyramids | CoreShell | SquareLattice | RadialParaCrystal | HexParaCrystal | SSCA | Mesocrystal | PolMagCyl | Custom FF | -| 2017-12-18 10:07:41 | scgsun | Linux x86_64 | 2.7 | 89.6946 | 13.7180 | 0.5314 | 0.5718 | 3.1055 | 0.3623 | 2.0929 | 0.5021 | 2.5312 | 0.8436 | 0.4270 | 1.9687 | 0.7815 | -domain2gui: 0.844, gui2domain: 1.542, realTime : 1.243 -make check real: 0m31.140s, user 0m56.692s: sys 0m3.284s - +# 2017-12-15 +# before refactoring in Simulation and GISASSimulation for large detectors (CoreSpecial/DetectorTest) + Parameters 32x32 128x128 512x512 1024x1024 2048x2048 + Runs 1000 50 4 1 1 + elements_rect 0.000311 0.0043 0.0825 0.346 1.411 + run_rect 0.012466 0.10014 1.36325 5.629 21.577 + elements_spher 0.000212 0.00328 0.061 0.278 1.125 + run_spher 0.011658 0.07922 1.382 5.289 19.969