Skip to content
Snippets Groups Projects
Commit 6a379fcb authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

[i410e] rm ISimulation::compute ()

Merging branch 'i410e'  into 'main'.

See merge request !1276
parents 6310b197 b590ec41
No related branches found
No related tags found
1 merge request!1276rm ISimulation::compute
Pipeline #85902 passed
...@@ -14,12 +14,15 @@ ...@@ -14,12 +14,15 @@
#include "Base/Progress/DelayedProgressCounter.h" #include "Base/Progress/DelayedProgressCounter.h"
#include "Base/Progress/ProgressHandler.h" #include "Base/Progress/ProgressHandler.h"
#include <stdexcept>
DelayedProgressCounter::DelayedProgressCounter(ProgressHandler* p_progress, size_t interval) DelayedProgressCounter::DelayedProgressCounter(ProgressHandler* progress, size_t interval)
: m_progress(p_progress) : m_progress(progress)
, m_interval(interval) , m_interval(interval)
, m_count(0) , m_count(0)
{ {
if (!progress->alive())
throw std::runtime_error("dead process (user interrupt?)");
} }
void DelayedProgressCounter::stepProgress() void DelayedProgressCounter::stepProgress()
......
...@@ -26,7 +26,7 @@ class ProgressHandler; ...@@ -26,7 +26,7 @@ class ProgressHandler;
class DelayedProgressCounter { class DelayedProgressCounter {
public: public:
DelayedProgressCounter(ProgressHandler* p_progress, size_t interval); DelayedProgressCounter(ProgressHandler* progress, size_t interval);
~DelayedProgressCounter() = default; ~DelayedProgressCounter() = default;
//! Increments inner counter; at regular intervals updates progress handler. //! Increments inner counter; at regular intervals updates progress handler.
......
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Sim/Computation/ComputationStatus.h
//! @brief Defines and implements interface class ComputationStatus.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#ifdef SWIG
#error no need to expose this header to Swig
#endif // SWIG
#ifndef BORNAGAIN_SIM_COMPUTATION_COMPUTATIONSTATUS_H
#define BORNAGAIN_SIM_COMPUTATION_COMPUTATIONSTATUS_H
#include <string>
//! Completion status (flag and text) of a numeric computation.
class ComputationStatus {
public:
ComputationStatus()
: m_status(IDLE)
{
}
bool isCompleted() const { return m_status == COMPLETED; }
std::string errorMessage() const { return m_error_message; }
void setRunning() { m_status = RUNNING; }
void setCompleted() { m_status = COMPLETED; }
void setFailed(const std::string& message)
{
m_error_message = message;
m_status = FAILED;
}
private:
enum ESimulationStatus { IDLE, RUNNING, COMPLETED, FAILED };
ESimulationStatus m_status;
std::string m_error_message;
};
#endif // BORNAGAIN_SIM_COMPUTATION_COMPUTATIONSTATUS_H
...@@ -43,8 +43,6 @@ DWBAComputation::~DWBAComputation() = default; ...@@ -43,8 +43,6 @@ DWBAComputation::~DWBAComputation() = default;
void DWBAComputation::runProtected() void DWBAComputation::runProtected()
{ {
for (auto it = m_begin_it; it != m_end_it; ++it) { for (auto it = m_begin_it; it != m_end_it; ++it) {
if (!m_progress->alive())
break;
DiffuseElement& ele = *it; DiffuseElement& ele = *it;
const Fluxes fluxes_in = m_re_sample.fluxesIn(ele.getKi()); const Fluxes fluxes_in = m_re_sample.fluxesIn(ele.getKi());
......
...@@ -21,35 +21,13 @@ IComputation::IComputation(const ReSample& re_sample, const SimulationOptions& o ...@@ -21,35 +21,13 @@ IComputation::IComputation(const ReSample& re_sample, const SimulationOptions& o
ProgressHandler& progress) ProgressHandler& progress)
: m_re_sample(re_sample) : m_re_sample(re_sample)
, m_options(options) , m_options(options)
, m_progress(&progress) , m_progress_counter(std::make_unique<DelayedProgressCounter>(&progress, 100))
{ {
} }
IComputation::~IComputation() = default; IComputation::~IComputation() = default;
void IComputation::setProgressHandler(ProgressHandler* progress) const
{
m_progress_counter = std::make_unique<DelayedProgressCounter>(progress, 100);
}
void IComputation::stepProgress() const void IComputation::stepProgress() const
{ {
if (m_progress_counter) m_progress_counter->stepProgress();
m_progress_counter->stepProgress();
}
void IComputation::compute()
{
m_status.setRunning();
try {
if (!m_progress->alive())
return;
setProgressHandler(m_progress);
runProtected(); // <--- here the main work is done
m_status.setCompleted();
} catch (const std::exception& ex) {
m_status.setFailed(ex.what());
}
} }
...@@ -18,11 +18,9 @@ ...@@ -18,11 +18,9 @@
#ifndef BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H #ifndef BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H
#define BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H #define BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H
#include "Sim/Computation/ComputationStatus.h"
#include <memory> #include <memory>
class DelayedProgressCounter; class DelayedProgressCounter;
class MultiLayer;
class ReSample; class ReSample;
class ProgressHandler; class ProgressHandler;
class SimulationOptions; class SimulationOptions;
...@@ -38,26 +36,17 @@ public: ...@@ -38,26 +36,17 @@ public:
ProgressHandler& progress); ProgressHandler& progress);
virtual ~IComputation(); virtual ~IComputation();
//! Calls runProtected(), catches exceptions, sets m_status. //! Runs computation. May throw.
void compute(); virtual void runProtected() = 0;
bool isCompleted() const { return m_status.isCompleted(); }
std::string errorMessage() const { return m_status.errorMessage(); }
protected: protected:
void setProgressHandler(ProgressHandler* progress) const;
void stepProgress() const; void stepProgress() const;
const ReSample& m_re_sample; const ReSample& m_re_sample;
const SimulationOptions& m_options; const SimulationOptions& m_options;
ProgressHandler* m_progress;
private: private:
//! Runs computation. May throw. To be called from runProtected(), which catches exceptions.
virtual void runProtected() = 0;
mutable std::unique_ptr<DelayedProgressCounter> m_progress_counter; mutable std::unique_ptr<DelayedProgressCounter> m_progress_counter;
ComputationStatus m_status;
}; };
#endif // BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H #endif // BORNAGAIN_SIM_COMPUTATION_ICOMPUTATION_H
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "Sim/Computation/IComputation.h" #include "Sim/Computation/IComputation.h"
#include <gsl/gsl_errno.h> #include <gsl/gsl_errno.h>
#include <iostream> #include <iostream>
#include <mutex>
#include <thread> #include <thread>
namespace { namespace {
...@@ -130,7 +131,7 @@ SimulationResult ISimulation::simulate() ...@@ -130,7 +131,7 @@ SimulationResult ISimulation::simulate()
prepareSimulation(); prepareSimulation();
const auto re_sample = ReSample::make(*m_sample, options(), force_polarized()); const ReSample re_sample = ReSample::make(*m_sample, options(), force_polarized());
const size_t total_size = numberOfElements(); const size_t total_size = numberOfElements();
size_t param_combinations = distributionHandler().getTotalNumberOfSamples(); size_t param_combinations = distributionHandler().getTotalNumberOfSamples();
...@@ -217,41 +218,44 @@ void ISimulation::runSingleSimulation(const ReSample& re_sample, size_t batch_st ...@@ -217,41 +218,44 @@ void ISimulation::runSingleSimulation(const ReSample& re_sample, size_t batch_st
if (n_threads == 1) { if (n_threads == 1) {
// Run computation in current thread. // Run computation in current thread.
const auto& c = createComputation(re_sample, batch_start, batch_size); try {
c->compute(); // <---- here most work is done (unthreaded case)! const auto& c = createComputation(re_sample, batch_start, batch_size);
if (!c->isCompleted()) c->runProtected(); // <---- here most work is done (unthreaded case)!
throw std::runtime_error("Unexpected error in simulation:\n" + c->errorMessage()); } catch (const std::exception& ex) {
throw std::runtime_error(std::string("Unexpected error in simulation:\n") + ex.what());
}
} else { } else {
// Create batch computations. // Launch computation threads.
std::vector<std::unique_ptr<IComputation>> computations; std::vector<std::unique_ptr<std::thread>> threads;
std::vector<std::string> failure_messages;
std::mutex mutex;
for (size_t i_thread = 0; i_thread < n_threads; ++i_thread) { for (size_t i_thread = 0; i_thread < n_threads; ++i_thread) {
const size_t thread_start = batch_start + startIndex(n_threads, i_thread, batch_size); const size_t thread_start = batch_start + startIndex(n_threads, i_thread, batch_size);
const size_t thread_size = batchSize(n_threads, i_thread, batch_size); const size_t thread_size = batchSize(n_threads, i_thread, batch_size);
if (thread_size == 0) if (thread_size == 0)
break; break;
computations.emplace_back(createComputation(re_sample, thread_start, thread_size)); threads.emplace_back(new std::thread(
[this, &re_sample, &failure_messages, &mutex, thread_start, thread_size]() {
try {
const auto& c = createComputation(re_sample, thread_start, thread_size);
c->runProtected(); // <---- here most work is done (threaded case)!
} catch (const std::exception& ex) {
mutex.lock();
failure_messages.push_back(ex.what());
mutex.unlock();
}
}));
} }
// Run computations in several threads.
std::vector<std::unique_ptr<std::thread>> threads;
for (const auto& c : computations)
threads.emplace_back(new std::thread([&c]() {
c->compute(); // <---- here most work is done (threaded case)!
}));
// Wait for threads to complete. // Wait for threads to complete.
for (auto& thread : threads) for (auto& thread : threads)
thread->join(); thread->join();
// Check successful completion. // Check successful completion.
std::vector<std::string> failure_messages;
for (const auto& c : computations)
if (!c->isCompleted())
failure_messages.push_back(c->errorMessage());
if (!failure_messages.empty()) if (!failure_messages.empty())
throw std::runtime_error("Unexpected error in simulation thread(s):\n" throw std::runtime_error("Unexpected error(s) in simulation thread(s):\n"
+ BaseUtils::String::join(failure_messages, " --- ")); + BaseUtils::String::join(failure_messages, "\n"));
} }
normalize(batch_start, batch_size); normalize(batch_start, batch_size);
......
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