From 5edf4e25df7adab1051c9e4b26b3f4f306cd982a Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 20 Mar 2021 15:19:02 -0400 Subject: [PATCH 01/47] adds file_stream_writer and run_adaptive_sampler method for parallel --- src/stan/callbacks/file_stream_writer.hpp | 119 ++++++++++++++++++ src/stan/callbacks/stream_logger.hpp | 2 +- src/stan/callbacks/stream_writer.hpp | 2 +- src/stan/callbacks/tee_writer.hpp | 2 +- .../services/util/generate_transitions.hpp | 5 +- .../services/util/run_adaptive_sampler.hpp | 87 ++++++++++++- .../callbacks/file_stream_writer_test.cpp | 47 +++++++ 7 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 src/stan/callbacks/file_stream_writer.hpp create mode 100644 src/test/unit/callbacks/file_stream_writer_test.cpp diff --git a/src/stan/callbacks/file_stream_writer.hpp b/src/stan/callbacks/file_stream_writer.hpp new file mode 100644 index 00000000000..1d9725b6656 --- /dev/null +++ b/src/stan/callbacks/file_stream_writer.hpp @@ -0,0 +1,119 @@ +#ifndef STAN_CALLBACKS_FILE_STREAM_WRITER_HPP +#define STAN_CALLBACKS_FILE_STREAM_WRITER_HPP + +#include +#include +#include +#include + +namespace stan { +namespace callbacks { + +/** + * file_stream_writer is an implementation + * of writer that writes to a file. + */ +class file_stream_writer final : public writer { + public: + /** + * Constructs a file stream writer with an output stream + * and an optional prefix for comments. + * + * @param[in, out] A unique pointer to a type inheriting from `std::ostream` + * @param[in] comment_prefix string to stream before each comment line. + * Default is "". + */ + explicit file_stream_writer(std::unique_ptr&& output, + const std::string& comment_prefix = "") + : output_(std::move(output)), comment_prefix_(comment_prefix) {} + + + file_stream_writer(); + file_stream_writer(file_stream_writer& other) = delete; + file_stream_writer(file_stream_writer&& other) : + output_(std::move(other.output_)), comment_prefix_(std::move(other.comment_prefix_)) {} + /** + * Virtual destructor + */ + virtual ~file_stream_writer() {} + + /** + * Writes a set of names on a single line in csv format followed + * by a newline. + * + * Note: the names are not escaped. + * + * @param[in] names Names in a std::vector + */ + void operator()(const std::vector& names) { + write_vector(names); + } + /** + * Get the underlying stream + */ + auto& get_stream() { + return *output_; + } + + /** + * Writes a set of values in csv format followed by a newline. + * + * Note: the precision of the output is determined by the settings + * of the stream on construction. + * + * @param[in] state Values in a std::vector + */ + void operator()(const std::vector& state) { write_vector(state); } + + /** + * Writes the comment_prefix to the stream followed by a newline. + */ + void operator()() { *output_ << comment_prefix_ << std::endl; } + + /** + * Writes the comment_prefix then the message followed by a newline. + * + * @param[in] message A string + */ + void operator()(const std::string& message) { + *output_ << comment_prefix_ << message << std::endl; + } + + private: + /** + * Output stream + */ + std::unique_ptr output_; + + /** + * Comment prefix to use when printing comments: strings and blank lines + */ + std::string comment_prefix_; + + /** + * Writes a set of values in csv format followed by a newline. + * + * Note: the precision of the output is determined by the settings + * of the stream on construction. + * + * @param[in] v Values in a std::vector + */ + template + void write_vector(const std::vector& v) { + if (v.empty()) + return; + + typename std::vector::const_iterator last = v.end(); + --last; + + for (typename std::vector::const_iterator it = v.begin(); it != last; + ++it) + *output_ << *it << ","; + *output_ << v.back() << std::endl; + } +}; + +} +} + +#endif diff --git a/src/stan/callbacks/stream_logger.hpp b/src/stan/callbacks/stream_logger.hpp index 6e6cca07e64..677add7c707 100644 --- a/src/stan/callbacks/stream_logger.hpp +++ b/src/stan/callbacks/stream_logger.hpp @@ -14,7 +14,7 @@ namespace callbacks { * logger that writes messages to separate * std::stringstream outputs. */ -class stream_logger : public logger { +class stream_logger final : public logger { private: std::ostream& debug_; std::ostream& info_; diff --git a/src/stan/callbacks/stream_writer.hpp b/src/stan/callbacks/stream_writer.hpp index 6519531c0ac..226f16a76e1 100644 --- a/src/stan/callbacks/stream_writer.hpp +++ b/src/stan/callbacks/stream_writer.hpp @@ -13,7 +13,7 @@ namespace callbacks { * stream_writer is an implementation * of writer that writes to a stream. */ -class stream_writer : public writer { +class stream_writer final : public writer { public: /** * Constructs a stream writer with an output stream diff --git a/src/stan/callbacks/tee_writer.hpp b/src/stan/callbacks/tee_writer.hpp index 8eca4af61a7..c491832e9ec 100644 --- a/src/stan/callbacks/tee_writer.hpp +++ b/src/stan/callbacks/tee_writer.hpp @@ -16,7 +16,7 @@ namespace callbacks { * For any call to this writer, it will tee the call to both writers * provided in the constructor. */ -class tee_writer : public writer { +class tee_writer final : public writer { public: /** * Constructor accepting two writers. diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index 1516c6f0f99..8ad93706c6a 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -44,7 +44,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, util::mcmc_writer& mcmc_writer, stan::mcmc::sample& init_s, Model& model, RNG& base_rng, callbacks::interrupt& callback, - callbacks::logger& logger) { + callbacks::logger& logger, size_t n_chain = 0) { for (int m = 0; m < num_iterations; ++m) { callback(); @@ -52,6 +52,9 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, && (start + m + 1 == finish || m == 0 || (m + 1) % refresh == 0)) { int it_print_width = std::ceil(std::log10(static_cast(finish))); std::stringstream message; + if (n_chain > 0) { + message << "Chain [" << (n_chain + 1) << "]"; + } message << "Iteration: "; message << std::setw(it_print_width) << m + 1 + start << " / " << finish; message << " [" << std::setw(3) diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index ba0135158dd..39e1f5a88b8 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -34,7 +34,7 @@ namespace util { * @param[in,out] sample_writer writer for draws * @param[in,out] diagnostic_writer writer for diagnostic information */ -template +template void run_adaptive_sampler(Sampler& sampler, Model& model, std::vector& cont_vector, int num_warmup, int num_samples, int num_thin, int refresh, @@ -87,6 +87,91 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, / 1000.0; writer.write_timing(warm_delta_t, sample_delta_t); } + +template +void run_adaptive_sampler(Sampler& sampler, Model& model, + std::vector>& cont_vector, + int num_warmup, int num_samples, int num_thin, + int refresh, bool save_warmup, RNG& rng, + callbacks::interrupt& interrupt, + callbacks::logger& logger, + std::vector& sample_writer, + std::vector& diagnostic_writer, + size_t n_chains = 0) { + std::vector writers; + writers.reserve(n_chain); + std::vector samples; + samples.reserve(n_chain); + + for (int i = 0; i < n_chain; ++i) { + auto&& sample_writer = sample_writers[i]; + auto&& diagnostic_writer = diagnostic_writers[i]; + auto&& sampler = samplers[i]; + Eigen::Map cont_params(cont_vectors[i].data(), + cont_vectors[i].size()); + sampler.engage_adaptation(); + try { + sampler.z().q = cont_params; + sampler.init_stepsize(logger); + } catch (const std::exception& e) { + logger.info("Exception initializing step size."); + logger.info(e.what()); + return; + } + writers.emplace_back(sample_writer, diagnostic_writer, logger); + samples.emplace_back(cont_params, 0, 0); + } + std::vector warm_delta_v(n_chain, 0); + tbb::parallel_for( + tbb::blocked_range(0, n_chain, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, &samples, + &warm_delta_v, &writers, &samplers, &model, &cont_vectors, &rngs, + &interrupt, &logger, &sample_writers, + &diagnostic_writers](const tbb::blocked_range& r) { + for (size_t i = r.begin(); i != r.end(); ++i) { + auto&& writer = writers[i]; + auto&& sampler = samplers[i]; + auto&& samp = samples[i]; + + // Headers + writer.write_sample_names(samp, sampler, model); + writer.write_diagnostic_names(samp, sampler, model); + + auto start_warm = std::chrono::steady_clock::now(); + util::generate_transitions(sampler, num_warmup, 0, + num_warmup + num_samples, num_thin, + refresh, save_warmup, true, writer, samp, + model, rngs[i], interrupt, logger, i); + auto end_warm = std::chrono::steady_clock::now(); + warm_delta_v[i] + = std::chrono::duration_cast( + end_warm - start_warm) + .count() + / 1000.0; + sampler.disengage_adaptation(); + auto&& sample_writer = sample_writers[i]; + auto&& sampler = samplers[i]; + writer.write_adapt_finish(sampler); + sampler.write_sampler_state(sample_writer); + + auto start_sample = std::chrono::steady_clock::now(); + util::generate_transitions(sampler, num_samples, num_warmup, + num_warmup + num_samples, num_thin, + refresh, true, false, writer, samp, model, + rngs[i], interrupt, logger, i); + auto end_sample = std::chrono::steady_clock::now(); + double sample_delta_t + = std::chrono::duration_cast( + end_sample - start_sample) + .count() + / 1000.0; + writer.write_timing(warm_delta_v[i], sample_delta_t); + } + }, + tbb::simple_partitioner()); +} + } // namespace util } // namespace services } // namespace stan diff --git a/src/test/unit/callbacks/file_stream_writer_test.cpp b/src/test/unit/callbacks/file_stream_writer_test.cpp new file mode 100644 index 00000000000..b24142c381b --- /dev/null +++ b/src/test/unit/callbacks/file_stream_writer_test.cpp @@ -0,0 +1,47 @@ +#include +#include +#include + +class StanInterfaceCallbacksStreamWriter : public ::testing::Test { + public: + StanInterfaceCallbacksStreamWriter() + : writer(std::make_unique(std::stringstream{})) {} + + void SetUp() { + static_cast(writer.get_stream()).str(std::string()); + static_cast(writer.get_stream()).clear(); + } + void TearDown() {} + + stan::callbacks::file_stream_writer writer; +}; + +TEST_F(StanInterfaceCallbacksStreamWriter, double_vector) { + const int N = 5; + std::vector x; + for (int n = 0; n < N; ++n) + x.push_back(n); + + EXPECT_NO_THROW(writer(x)); + EXPECT_EQ("0,1,2,3,4\n", static_cast(writer.get_stream()).str()); +} + +TEST_F(StanInterfaceCallbacksStreamWriter, string_vector) { + const int N = 5; + std::vector x; + for (int n = 0; n < N; ++n) + x.push_back(boost::lexical_cast(n)); + + EXPECT_NO_THROW(writer(x)); + EXPECT_EQ("0,1,2,3,4\n", static_cast(writer.get_stream()).str()); +} + +TEST_F(StanInterfaceCallbacksStreamWriter, null) { + EXPECT_NO_THROW(writer()); + EXPECT_EQ("\n", static_cast(writer.get_stream()).str()); +} + +TEST_F(StanInterfaceCallbacksStreamWriter, string) { + EXPECT_NO_THROW(writer("message")); + EXPECT_EQ("message\n", static_cast(writer.get_stream()).str()); +} From faa5eb0de817c0f41475cb7ca65dc3f41f6d6674 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sat, 20 Mar 2021 22:20:33 -0400 Subject: [PATCH 02/47] fix grammar error for parallel run_adaptive_sampler --- .../services/util/run_adaptive_sampler.hpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 39e1f5a88b8..094be9d3304 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -88,17 +89,15 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, writer.write_timing(warm_delta_t, sample_delta_t); } -template -void run_adaptive_sampler(Sampler& sampler, Model& model, - std::vector>& cont_vector, - int num_warmup, int num_samples, int num_thin, - int refresh, bool save_warmup, RNG& rng, +template +void run_adaptive_sampler(std::vector& samplers, Model& model, + std::vector>& cont_vectors, int num_warmup, + int num_samples, int num_thin, int refresh, + bool save_warmup, std::vector& rngs, callbacks::interrupt& interrupt, callbacks::logger& logger, - std::vector& sample_writer, - std::vector& diagnostic_writer, - size_t n_chains = 0) { + std::vector& sample_writers, + std::vector& diagnostic_writers, size_t n_chain) { std::vector writers; writers.reserve(n_chain); std::vector samples; @@ -151,7 +150,6 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, / 1000.0; sampler.disengage_adaptation(); auto&& sample_writer = sample_writers[i]; - auto&& sampler = samplers[i]; writer.write_adapt_finish(sampler); sampler.write_sampler_state(sample_writer); From 751403fa0ae9bdc4f963e70f03ded2edf98e6f37 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 21 Mar 2021 02:35:29 +0000 Subject: [PATCH 03/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/callbacks/file_stream_writer.hpp | 18 ++++++++---------- .../services/util/run_adaptive_sampler.hpp | 12 +++++++----- .../unit/callbacks/file_stream_writer_test.cpp | 9 ++++++--- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/stan/callbacks/file_stream_writer.hpp b/src/stan/callbacks/file_stream_writer.hpp index 1d9725b6656..e182321f831 100644 --- a/src/stan/callbacks/file_stream_writer.hpp +++ b/src/stan/callbacks/file_stream_writer.hpp @@ -23,15 +23,15 @@ class file_stream_writer final : public writer { * @param[in] comment_prefix string to stream before each comment line. * Default is "". */ - explicit file_stream_writer(std::unique_ptr&& output, - const std::string& comment_prefix = "") + explicit file_stream_writer(std::unique_ptr&& output, + const std::string& comment_prefix = "") : output_(std::move(output)), comment_prefix_(comment_prefix) {} - file_stream_writer(); file_stream_writer(file_stream_writer& other) = delete; - file_stream_writer(file_stream_writer&& other) : - output_(std::move(other.output_)), comment_prefix_(std::move(other.comment_prefix_)) {} + file_stream_writer(file_stream_writer&& other) + : output_(std::move(other.output_)), + comment_prefix_(std::move(other.comment_prefix_)) {} /** * Virtual destructor */ @@ -51,9 +51,7 @@ class file_stream_writer final : public writer { /** * Get the underlying stream */ - auto& get_stream() { - return *output_; - } + auto& get_stream() { return *output_; } /** * Writes a set of values in csv format followed by a newline. @@ -113,7 +111,7 @@ class file_stream_writer final : public writer { } }; -} -} +} // namespace callbacks +} // namespace stan #endif diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 094be9d3304..f1a5946689c 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -89,15 +89,17 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, writer.write_timing(warm_delta_t, sample_delta_t); } -template +template void run_adaptive_sampler(std::vector& samplers, Model& model, - std::vector>& cont_vectors, int num_warmup, - int num_samples, int num_thin, int refresh, - bool save_warmup, std::vector& rngs, + std::vector>& cont_vectors, + int num_warmup, int num_samples, int num_thin, + int refresh, bool save_warmup, std::vector& rngs, callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& sample_writers, - std::vector& diagnostic_writers, size_t n_chain) { + std::vector& diagnostic_writers, + size_t n_chain) { std::vector writers; writers.reserve(n_chain); std::vector samples; diff --git a/src/test/unit/callbacks/file_stream_writer_test.cpp b/src/test/unit/callbacks/file_stream_writer_test.cpp index b24142c381b..b3a64e4dcca 100644 --- a/src/test/unit/callbacks/file_stream_writer_test.cpp +++ b/src/test/unit/callbacks/file_stream_writer_test.cpp @@ -23,7 +23,8 @@ TEST_F(StanInterfaceCallbacksStreamWriter, double_vector) { x.push_back(n); EXPECT_NO_THROW(writer(x)); - EXPECT_EQ("0,1,2,3,4\n", static_cast(writer.get_stream()).str()); + EXPECT_EQ("0,1,2,3,4\n", + static_cast(writer.get_stream()).str()); } TEST_F(StanInterfaceCallbacksStreamWriter, string_vector) { @@ -33,7 +34,8 @@ TEST_F(StanInterfaceCallbacksStreamWriter, string_vector) { x.push_back(boost::lexical_cast(n)); EXPECT_NO_THROW(writer(x)); - EXPECT_EQ("0,1,2,3,4\n", static_cast(writer.get_stream()).str()); + EXPECT_EQ("0,1,2,3,4\n", + static_cast(writer.get_stream()).str()); } TEST_F(StanInterfaceCallbacksStreamWriter, null) { @@ -43,5 +45,6 @@ TEST_F(StanInterfaceCallbacksStreamWriter, null) { TEST_F(StanInterfaceCallbacksStreamWriter, string) { EXPECT_NO_THROW(writer("message")); - EXPECT_EQ("message\n", static_cast(writer.get_stream()).str()); + EXPECT_EQ("message\n", + static_cast(writer.get_stream()).str()); } From a08ba353b4011cbc1104a40ce1e2add14ddbe0a6 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 21 Mar 2021 14:23:02 -0400 Subject: [PATCH 04/47] adds test for parallel adaptive --- .../services/util/generate_transitions.hpp | 3 +- .../services/util/run_adaptive_sampler.hpp | 10 +- .../unit/services/instrumented_callbacks.hpp | 37 +++- .../run_adaptive_sampler_parallel_test.cpp | 208 ++++++++++++++++++ 4 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index 8ad93706c6a..53261a33435 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -51,7 +51,8 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, if (refresh > 0 && (start + m + 1 == finish || m == 0 || (m + 1) % refresh == 0)) { int it_print_width = std::ceil(std::log10(static_cast(finish))); - std::stringstream message; + std::string mes; + std::stringstream message(mes, std::ios_base::in); if (n_chain > 0) { message << "Chain [" << (n_chain + 1) << "]"; } diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index f1a5946689c..d27225a3c6a 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -124,10 +124,11 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, samples.emplace_back(cont_params, 0, 0); } std::vector warm_delta_v(n_chain, 0); + std::vector sample_delta_v(n_chain, 0); tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, &samples, - &warm_delta_v, &writers, &samplers, &model, &cont_vectors, &rngs, + &warm_delta_v, &sample_delta_v, &writers, &samplers, &model, &cont_vectors, &rngs, &interrupt, &logger, &sample_writers, &diagnostic_writers](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { @@ -161,15 +162,18 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, refresh, true, false, writer, samp, model, rngs[i], interrupt, logger, i); auto end_sample = std::chrono::steady_clock::now(); - double sample_delta_t + sample_delta_v[i] = std::chrono::duration_cast( end_sample - start_sample) .count() / 1000.0; - writer.write_timing(warm_delta_v[i], sample_delta_t); } }, tbb::simple_partitioner()); + for (int i = 0; i < n_chain; ++i) { + writers[i].write_timing(warm_delta_v[i], sample_delta_v[i]); + } + } } // namespace util diff --git a/src/test/unit/services/instrumented_callbacks.hpp b/src/test/unit/services/instrumented_callbacks.hpp index 5df61c17f74..a0f866aef08 100644 --- a/src/test/unit/services/instrumented_callbacks.hpp +++ b/src/test/unit/services/instrumented_callbacks.hpp @@ -9,7 +9,7 @@ #include #include #include - +#include namespace stan { namespace test { namespace unit { @@ -27,7 +27,7 @@ class instrumented_interrupt : public stan::callbacks::interrupt { unsigned int call_count() { return counter_; } private: - unsigned int counter_; + std::atomic counter_; }; /** @@ -96,9 +96,8 @@ class instrumented_writer : public stan::callbacks::writer { unsigned int call_count() { unsigned int n = 0; - for (std::map::iterator it = counter_.begin(); - it != counter_.end(); ++it) - n += it->second; + for (auto& it : counter_) + n += it.second; return n; } @@ -137,7 +136,7 @@ class instrumented_writer : public stan::callbacks::writer { std::vector string_values() { return string; }; private: - std::map counter_; + std::map> counter_; std::vector > string_double; std::vector > string_int; std::vector > string_string; @@ -156,35 +155,53 @@ class instrumented_writer : public stan::callbacks::writer { */ class instrumented_logger : public stan::callbacks::logger { public: + std::mutex logger_guard; instrumented_logger() {} - void debug(const std::string& message) { debug_.push_back(message); } + void debug(const std::string& message) { + std::lock_guard guard(logger_guard); + debug_.push_back(message); + } void debug(const std::stringstream& message) { + std::lock_guard guard(logger_guard); debug_.push_back(message.str()); } - void info(const std::string& message) { info_.push_back(message); } + void info(const std::string& message) { + std::lock_guard guard(logger_guard); + info_.push_back(message); + } void info(const std::stringstream& message) { + std::lock_guard guard(logger_guard); info_.push_back(message.str()); } - void warn(const std::string& message) { warn_.push_back(message); } + void warn(const std::string& message) { + std::lock_guard guard(logger_guard); + warn_.push_back(message); + } void warn(const std::stringstream& message) { + std::lock_guard guard(logger_guard); warn_.push_back(message.str()); } - void error(const std::string& message) { error_.push_back(message); } + void error(const std::string& message) { + std::lock_guard guard(logger_guard); + error_.push_back(message); + } void error(const std::stringstream& message) { + std::lock_guard guard(logger_guard); error_.push_back(message.str()); } void fatal(const std::string& message) { fatal_.push_back(message); } void fatal(const std::stringstream& message) { + std::lock_guard guard(logger_guard); fatal_.push_back(message.str()); } diff --git a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp new file mode 100644 index 00000000000..ed52f2a9ec4 --- /dev/null +++ b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp @@ -0,0 +1,208 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class ServicesUtil : public testing::Test { + using model_t = stan::mcmc::adapt_unit_e_nuts; + public: + ServicesUtil() + : model(context, 0, &model_log), + rng(3), + cont_vector(3, std::vector{0, 0}), + sampler(), + num_warmup(0), + num_samples(0), + num_thin(1), + refresh(0), + n_chain(3), + save_warmup(false) { + rng.clear(); + for (int i = 0; i < 3; ++i) { + rng[i] = std::move(stan::services::util::create_rng(0, 1)); + sampler.push_back(model_t(model, rng[i])); + sample_writer.push_back(stan::test::unit::instrumented_writer{}); + diagnostic_writer.push_back(stan::test::unit::instrumented_writer{}); + } + } + + std::stringstream model_log; + stan::io::empty_var_context context; + stan_model model; + std::vector> cont_vector; + std::vector rng; + stan::test::unit::instrumented_interrupt interrupt; + std::vector sample_writer, diagnostic_writer; + stan::test::unit::instrumented_logger logger; + std::vector sampler; + int num_warmup, num_samples, num_thin, refresh, n_chain; + bool save_warmup; +}; + +TEST_F(ServicesUtil, all_zero) { + stan::services::util::run_adaptive_sampler( + sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + EXPECT_EQ(0, interrupt.call_count()); + + EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ(logger.call_count(), logger.call_count_info()) + << "No other calls to logger"; + + EXPECT_EQ(8, sample_writer[0].call_count()); + EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) + << "adaptation info + elapsed time"; + EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; + + EXPECT_EQ(6, diagnostic_writer[0].call_count()); + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; + +} + +TEST_F(ServicesUtil, num_warmup_no_save) { + num_warmup = 1000; + stan::services::util::run_adaptive_sampler( + sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + EXPECT_EQ(num_warmup * 3, interrupt.call_count()); + + EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ(logger.call_count(), logger.call_count_info()) + << "No other calls to logger"; + + EXPECT_EQ(8, sample_writer[0].call_count()); + EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) + << "adaptation info + elapsed time"; + EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; + + EXPECT_EQ(6, diagnostic_writer[0].call_count()); + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; +} + +TEST_F(ServicesUtil, num_warmup_save) { + num_warmup = 1000; + save_warmup = true; + stan::services::util::run_adaptive_sampler( + sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + EXPECT_EQ((num_warmup) * 3, interrupt.call_count()); + + EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ(logger.call_count(), logger.call_count_info()) + << "No other calls to logger"; + + EXPECT_EQ(num_warmup + 8, sample_writer[0].call_count()); + EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) + << "adaptation info + elapsed time"; + EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ(num_warmup, sample_writer[0].call_count("vector_double")) + << "warmup draws"; + + EXPECT_EQ(num_warmup + 6, diagnostic_writer[0].call_count()); + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ(num_warmup, diagnostic_writer[0].call_count("vector_double")) + << "warmup draws"; +} + +TEST_F(ServicesUtil, num_samples) { + num_samples = 1000; + stan::services::util::run_adaptive_sampler( + sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + EXPECT_EQ(num_samples * 3, interrupt.call_count()); + + EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ(logger.call_count(), logger.call_count_info()) + << "No other calls to logger"; + + EXPECT_EQ(num_samples + 8, sample_writer[0].call_count()); + EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) + << "adaptation info + elapsed time"; + EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) + << "num_samples draws"; + + EXPECT_EQ(num_samples + 6, diagnostic_writer[0].call_count()); + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) + << "num_samples draws"; +} + +TEST_F(ServicesUtil, num_warmup_save_num_samples_num_thin) { + num_warmup = 500; + save_warmup = true; + num_samples = 500; + num_thin = 10; + stan::services::util::run_adaptive_sampler( + sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + EXPECT_EQ((num_warmup + num_samples) * 3, interrupt.call_count()); + + EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ(logger.call_count(), logger.call_count_info()) + << "No other calls to logger"; + + EXPECT_EQ((num_warmup + num_samples) / num_thin + 8, + sample_writer[0].call_count()); + EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ((num_warmup + num_samples) / num_thin, + sample_writer[0].call_count("vector_double")) + << "thinned warmup and draws"; + + EXPECT_EQ((num_warmup + num_samples) / num_thin + 6, + diagnostic_writer[0].call_count()); + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ((num_warmup + num_samples) / num_thin, + diagnostic_writer[0].call_count("vector_double")) + << "thinned warmup and draws"; +} + +TEST_F(ServicesUtil, num_warmup_num_samples_refresh) { + num_warmup = 500; + num_samples = 500; + refresh = 10; + stan::services::util::run_adaptive_sampler( + sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + EXPECT_EQ((num_warmup + num_samples) * 3, interrupt.call_count()); + + EXPECT_EQ((num_warmup * 3 + num_samples * 3) / refresh + (2 + 3 + 2) * 3, + logger.call_count()) + << "Writes 1 to start warmup, 1 to start post-warmup, and " + << "(num_warmup + num_samples) / refresh, then the elapsed time"; + EXPECT_EQ(logger.call_count(), logger.call_count_info()) + << "No other calls to logger"; + + EXPECT_EQ(num_samples + 8, sample_writer[0].call_count()); + EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) << "draws"; + + EXPECT_EQ(num_samples + 6, diagnostic_writer[0].call_count()); + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; + EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; + EXPECT_EQ(num_samples, diagnostic_writer[0].call_count("vector_double")) + << "draws"; +} From a4c9679f3f2b8efd16360ccd117527ef18980ea5 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Sun, 21 Mar 2021 18:23:32 +0000 Subject: [PATCH 05/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../services/util/run_adaptive_sampler.hpp | 11 +++-- .../unit/services/instrumented_callbacks.hpp | 28 ++++++------- .../run_adaptive_sampler_parallel_test.cpp | 42 +++++++++++-------- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index d27225a3c6a..042662fe81e 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -128,8 +128,8 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, &samples, - &warm_delta_v, &sample_delta_v, &writers, &samplers, &model, &cont_vectors, &rngs, - &interrupt, &logger, &sample_writers, + &warm_delta_v, &sample_delta_v, &writers, &samplers, &model, + &cont_vectors, &rngs, &interrupt, &logger, &sample_writers, &diagnostic_writers](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { auto&& writer = writers[i]; @@ -170,10 +170,9 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, } }, tbb::simple_partitioner()); - for (int i = 0; i < n_chain; ++i) { - writers[i].write_timing(warm_delta_v[i], sample_delta_v[i]); - } - + for (int i = 0; i < n_chain; ++i) { + writers[i].write_timing(warm_delta_v[i], sample_delta_v[i]); + } } } // namespace util diff --git a/src/test/unit/services/instrumented_callbacks.hpp b/src/test/unit/services/instrumented_callbacks.hpp index a0f866aef08..0c47312df30 100644 --- a/src/test/unit/services/instrumented_callbacks.hpp +++ b/src/test/unit/services/instrumented_callbacks.hpp @@ -103,33 +103,33 @@ class instrumented_writer : public stan::callbacks::writer { unsigned int call_count(std::string s) { return counter_[s]; } - std::vector > string_double_values() { + std::vector> string_double_values() { return string_double; }; - std::vector > string_int_values() { + std::vector> string_int_values() { return string_int; }; - std::vector > string_string_values() { + std::vector> string_string_values() { return string_string; }; - std::vector > > + std::vector>> string_pdouble_int_values() { return string_pdouble_int; }; - std::vector > + std::vector> string_pdouble_int_int_values() { return string_pdouble_int_int; }; - std::vector > vector_string_values() { + std::vector> vector_string_values() { return vector_string; }; - std::vector > vector_double_values() { + std::vector> vector_double_values() { return vector_double; }; @@ -137,13 +137,13 @@ class instrumented_writer : public stan::callbacks::writer { private: std::map> counter_; - std::vector > string_double; - std::vector > string_int; - std::vector > string_string; - std::vector > > string_pdouble_int; - std::vector > string_pdouble_int_int; - std::vector > vector_string; - std::vector > vector_double; + std::vector> string_double; + std::vector> string_int; + std::vector> string_string; + std::vector>> string_pdouble_int; + std::vector> string_pdouble_int_int; + std::vector> vector_string; + std::vector> vector_double; std::vector string; }; diff --git a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp index ed52f2a9ec4..48324624148 100644 --- a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp +++ b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp @@ -9,6 +9,7 @@ class ServicesUtil : public testing::Test { using model_t = stan::mcmc::adapt_unit_e_nuts; + public: ServicesUtil() : model(context, 0, &model_log), @@ -21,13 +22,13 @@ class ServicesUtil : public testing::Test { refresh(0), n_chain(3), save_warmup(false) { - rng.clear(); - for (int i = 0; i < 3; ++i) { - rng[i] = std::move(stan::services::util::create_rng(0, 1)); - sampler.push_back(model_t(model, rng[i])); - sample_writer.push_back(stan::test::unit::instrumented_writer{}); - diagnostic_writer.push_back(stan::test::unit::instrumented_writer{}); - } + rng.clear(); + for (int i = 0; i < 3; ++i) { + rng[i] = std::move(stan::services::util::create_rng(0, 1)); + sampler.push_back(model_t(model, rng[i])); + sample_writer.push_back(stan::test::unit::instrumented_writer{}); + diagnostic_writer.push_back(stan::test::unit::instrumented_writer{}); + } } std::stringstream model_log; @@ -36,7 +37,8 @@ class ServicesUtil : public testing::Test { std::vector> cont_vector; std::vector rng; stan::test::unit::instrumented_interrupt interrupt; - std::vector sample_writer, diagnostic_writer; + std::vector sample_writer, + diagnostic_writer; stan::test::unit::instrumented_logger logger; std::vector sampler; int num_warmup, num_samples, num_thin, refresh, n_chain; @@ -60,10 +62,10 @@ TEST_F(ServicesUtil, all_zero) { EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; EXPECT_EQ(6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) + << "header line"; EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; - } TEST_F(ServicesUtil, num_warmup_no_save) { @@ -84,7 +86,8 @@ TEST_F(ServicesUtil, num_warmup_no_save) { EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; EXPECT_EQ(6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) + << "header line"; EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; } @@ -95,7 +98,7 @@ TEST_F(ServicesUtil, num_warmup_save) { stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); - EXPECT_EQ((num_warmup) * 3, interrupt.call_count()); + EXPECT_EQ((num_warmup)*3, interrupt.call_count()); EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) @@ -110,7 +113,8 @@ TEST_F(ServicesUtil, num_warmup_save) { << "warmup draws"; EXPECT_EQ(num_warmup + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) + << "header line"; EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; EXPECT_EQ(num_warmup, diagnostic_writer[0].call_count("vector_double")) @@ -137,7 +141,8 @@ TEST_F(ServicesUtil, num_samples) { << "num_samples draws"; EXPECT_EQ(num_samples + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) + << "header line"; EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) @@ -169,7 +174,8 @@ TEST_F(ServicesUtil, num_warmup_save_num_samples_num_thin) { EXPECT_EQ((num_warmup + num_samples) / num_thin + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) + << "header line"; EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; EXPECT_EQ((num_warmup + num_samples) / num_thin, @@ -197,10 +203,12 @@ TEST_F(ServicesUtil, num_warmup_num_samples_refresh) { EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) << "draws"; + EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) + << "draws"; EXPECT_EQ(num_samples + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) << "header line"; + EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) + << "header line"; EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; EXPECT_EQ(num_samples, diagnostic_writer[0].call_count("vector_double")) From 04836ef2bd7f4055b1fd63e581bbc72c54fa9380 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 21 Mar 2021 14:43:07 -0400 Subject: [PATCH 06/47] include mutex --- src/test/unit/services/instrumented_callbacks.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/unit/services/instrumented_callbacks.hpp b/src/test/unit/services/instrumented_callbacks.hpp index 0c47312df30..797959ef0ee 100644 --- a/src/test/unit/services/instrumented_callbacks.hpp +++ b/src/test/unit/services/instrumented_callbacks.hpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace stan { namespace test { namespace unit { From 0608601e01c3c2fb9788ae36619ea1c649949f68 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 21 Mar 2021 14:54:15 -0400 Subject: [PATCH 07/47] make stream_writer not final --- src/stan/callbacks/stream_writer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stan/callbacks/stream_writer.hpp b/src/stan/callbacks/stream_writer.hpp index 226f16a76e1..6519531c0ac 100644 --- a/src/stan/callbacks/stream_writer.hpp +++ b/src/stan/callbacks/stream_writer.hpp @@ -13,7 +13,7 @@ namespace callbacks { * stream_writer is an implementation * of writer that writes to a stream. */ -class stream_writer final : public writer { +class stream_writer : public writer { public: /** * Constructs a stream writer with an output stream From 3ebbc5caf42485edb8ddfb38a51f4fe4ac8ffba9 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Sun, 21 Mar 2021 15:29:31 -0400 Subject: [PATCH 08/47] init threadpool --- .../unit/services/util/run_adaptive_sampler_parallel_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp index 48324624148..2fd2d91ddaf 100644 --- a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp +++ b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp @@ -7,6 +7,8 @@ #include #include +auto&& blah = stan::math::init_threadpool_tbb(); + class ServicesUtil : public testing::Test { using model_t = stan::mcmc::adapt_unit_e_nuts; From a3bf12b36249cf82a4b81e4a06ad58f159f14638 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Mar 2021 11:25:26 -0400 Subject: [PATCH 09/47] update generate_transitions and cleanup run_adaptive_sampler --- .../services/util/generate_transitions.hpp | 3 +- .../services/util/run_adaptive_sampler.hpp | 41 ++++++++----------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index 53261a33435..8ad93706c6a 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -51,8 +51,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, if (refresh > 0 && (start + m + 1 == finish || m == 0 || (m + 1) % refresh == 0)) { int it_print_width = std::ceil(std::log10(static_cast(finish))); - std::string mes; - std::stringstream message(mes, std::ios_base::in); + std::stringstream message; if (n_chain > 0) { message << "Chain [" << (n_chain + 1) << "]"; } diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 042662fe81e..001d4cc9c68 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -100,18 +100,18 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, std::vector& sample_writers, std::vector& diagnostic_writers, size_t n_chain) { - std::vector writers; - writers.reserve(n_chain); + if (n_chain == 0) { + run_adaptive_sampler(samplers[0], model, cont_vectors[0], num_warmup, num_samples, + num_thin, refresh, save_warmup, rngs[0], interrupt, logger, sample_writers[0], + diagnostic_writers[0]); + } std::vector samples; samples.reserve(n_chain); - for (int i = 0; i < n_chain; ++i) { - auto&& sample_writer = sample_writers[i]; - auto&& diagnostic_writer = diagnostic_writers[i]; auto&& sampler = samplers[i]; - Eigen::Map cont_params(cont_vectors[i].data(), - cont_vectors[i].size()); sampler.engage_adaptation(); + Eigen::Map cont_params(cont_vectors[i].data(), + cont_vectors[i].size()); try { sampler.z().q = cont_params; sampler.init_stepsize(logger); @@ -120,19 +120,17 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, logger.info(e.what()); return; } - writers.emplace_back(sample_writer, diagnostic_writer, logger); samples.emplace_back(cont_params, 0, 0); } - std::vector warm_delta_v(n_chain, 0); - std::vector sample_delta_v(n_chain, 0); tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, &samples, - &warm_delta_v, &sample_delta_v, &writers, &samplers, &model, - &cont_vectors, &rngs, &interrupt, &logger, &sample_writers, + &samplers, &model, + &rngs, &interrupt, &logger, &sample_writers, &diagnostic_writers](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { - auto&& writer = writers[i]; + auto&& sample_writer = sample_writers[i]; + auto writer = services::util::mcmc_writer(sample_writer, diagnostic_writers[i], logger); auto&& sampler = samplers[i]; auto&& samp = samples[i]; @@ -140,39 +138,36 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, writer.write_sample_names(samp, sampler, model); writer.write_diagnostic_names(samp, sampler, model); - auto start_warm = std::chrono::steady_clock::now(); + const auto start_warm = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_warmup, 0, num_warmup + num_samples, num_thin, refresh, save_warmup, true, writer, samp, model, rngs[i], interrupt, logger, i); - auto end_warm = std::chrono::steady_clock::now(); - warm_delta_v[i] + const auto end_warm = std::chrono::steady_clock::now(); + auto warm_delta = std::chrono::duration_cast( end_warm - start_warm) .count() / 1000.0; sampler.disengage_adaptation(); - auto&& sample_writer = sample_writers[i]; writer.write_adapt_finish(sampler); sampler.write_sampler_state(sample_writer); - auto start_sample = std::chrono::steady_clock::now(); + const auto start_sample = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_samples, num_warmup, num_warmup + num_samples, num_thin, refresh, true, false, writer, samp, model, rngs[i], interrupt, logger, i); - auto end_sample = std::chrono::steady_clock::now(); - sample_delta_v[i] + const auto end_sample = std::chrono::steady_clock::now(); + auto sample_delta = std::chrono::duration_cast( end_sample - start_sample) .count() / 1000.0; + writer.write_timing(warm_delta, sample_delta); } }, tbb::simple_partitioner()); - for (int i = 0; i < n_chain; ++i) { - writers[i].write_timing(warm_delta_v[i], sample_delta_v[i]); - } } } // namespace util From 5c7b0bddd3b60b722ed245c420f07ef211ea31c3 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 24 Mar 2021 16:21:38 +0000 Subject: [PATCH 10/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/services/util/run_adaptive_sampler.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 001d4cc9c68..ef325eb807b 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -101,9 +101,10 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, std::vector& diagnostic_writers, size_t n_chain) { if (n_chain == 0) { - run_adaptive_sampler(samplers[0], model, cont_vectors[0], num_warmup, num_samples, - num_thin, refresh, save_warmup, rngs[0], interrupt, logger, sample_writers[0], - diagnostic_writers[0]); + run_adaptive_sampler(samplers[0], model, cont_vectors[0], num_warmup, + num_samples, num_thin, refresh, save_warmup, rngs[0], + interrupt, logger, sample_writers[0], + diagnostic_writers[0]); } std::vector samples; samples.reserve(n_chain); @@ -111,7 +112,7 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, auto&& sampler = samplers[i]; sampler.engage_adaptation(); Eigen::Map cont_params(cont_vectors[i].data(), - cont_vectors[i].size()); + cont_vectors[i].size()); try { sampler.z().q = cont_params; sampler.init_stepsize(logger); @@ -125,12 +126,12 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, &samples, - &samplers, &model, - &rngs, &interrupt, &logger, &sample_writers, + &samplers, &model, &rngs, &interrupt, &logger, &sample_writers, &diagnostic_writers](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { auto&& sample_writer = sample_writers[i]; - auto writer = services::util::mcmc_writer(sample_writer, diagnostic_writers[i], logger); + auto writer = services::util::mcmc_writer( + sample_writer, diagnostic_writers[i], logger); auto&& sampler = samplers[i]; auto&& samp = samples[i]; From 117274f0ebc8e89b9b3d95c4799fcb50db759089 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Mar 2021 14:01:08 -0400 Subject: [PATCH 11/47] start diag_e_adapt parallel --- lib/stan_math | 2 +- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 75 ++++++++++++++++++- .../util/create_unit_e_dense_inv_metric.hpp | 16 ++-- .../util/create_unit_e_diag_inv_metric.hpp | 12 ++- src/stan/services/util/initialize.hpp | 4 +- src/test/unit/services/check_adaptation.hpp | 4 +- 6 files changed, 89 insertions(+), 24 deletions(-) diff --git a/lib/stan_math b/lib/stan_math index 51669a650fb..91bbd128146 160000 --- a/lib/stan_math +++ b/lib/stan_math @@ -1 +1 @@ -Subproject commit 51669a650fbd2a57f1163342d30c597351080cf5 +Subproject commit 91bbd128146d97cb7a0646f97770191db45bf93d diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 8d03373e1a5..85a6ee3c35d 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -66,7 +66,6 @@ int hmc_nuts_diag_e_adapt( callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer) { boost::ecuyer1988 rng = util::create_rng(random_seed, chain); - std::vector disc_vector; std::vector cont_vector = util::initialize( model, init, rng, init_radius, true, logger, init_writer); @@ -154,6 +153,80 @@ int hmc_nuts_diag_e_adapt( interrupt, logger, init_writer, sample_writer, diagnostic_writer); } +template +int hmc_nuts_diag_e_adapt( + Model& model, const std::vector& init, + const std::vector& init_inv_metric, unsigned int random_seed, + unsigned int chain, double init_radius, int num_warmup, int num_samples, + int num_thin, bool save_warmup, int refresh, double stepsize, + double stepsize_jitter, int max_depth, double delta, double gamma, + double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, + unsigned int window, callbacks::interrupt& interrupt, + callbacks::logger& logger, callbacks::writer& init_writer, + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + using sample_t = stan::mcmc::adapt_diag_e_nuts; + std::vector rngs; + rngs.reserve(n_chain); + std::vector> cont_vectors; + cont_vectors.reserve(n_chain); + std::vector samplers; + samplers.reserve(n_chain); + try { + for (int i = 0; i < n_chain; ++i) { + rngs.emplace_back(util::create_rng(random_seed, chain + i)); + cont_vectors.emplace_back(util::initialize( + model, init[i], rngs[i], init_radius, true, logger, init_writer)); + samplers.emplace_back(model, rngs[i]); + Eigen::VectorXd inv_metric = util::read_diag_inv_metric(init_inv_metric[i], + model.num_params_r(), logger); + util::validate_diag_inv_metric(inv_metric, logger); + + samplers[i].set_metric(inv_metric); + samplers[i].set_nominal_stepsize(stepsize); + samplers[i].set_stepsize_jitter(stepsize_jitter); + samplers[i].set_max_depth(max_depth); + + samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); + samplers[i].get_stepsize_adaptation().set_delta(delta); + samplers[i].get_stepsize_adaptation().set_gamma(gamma); + samplers[i].get_stepsize_adaptation().set_kappa(kappa); + samplers[i].get_stepsize_adaptation().set_t0(t0); + samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, window, + logger); + + } + } catch (const std::domain_error& e) { + return error_codes::CONFIG; + } + util::run_adaptive_sampler( + samplers, model, cont_vectors, num_warmup, num_samples, num_thin, refresh, + save_warmup, rngs, interrupt, logger, sample_writer, diagnostic_writer, n_chain); + + return error_codes::OK; +} + +template +int hmc_nuts_diag_e_adapt( + Model& model, const std::vector& init, unsigned int random_seed, + unsigned int chain, double init_radius, int num_warmup, int num_samples, + int num_thin, bool save_warmup, int refresh, double stepsize, + double stepsize_jitter, int max_depth, double delta, double gamma, + double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, + unsigned int window, callbacks::interrupt& interrupt, + callbacks::logger& logger, callbacks::writer& init_writer, + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + stan::io::dump dmp + = util::create_unit_e_diag_inv_metric(model.num_params_r()); + std::vector unit_e_metrics(n_chain, dmp); + return hmc_nuts_diag_e_adapt( + model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); +} + + + } // namespace sample } // namespace services } // namespace stan diff --git a/src/stan/services/util/create_unit_e_dense_inv_metric.hpp b/src/stan/services/util/create_unit_e_dense_inv_metric.hpp index 60de41e0875..8d2a7bd60c6 100644 --- a/src/stan/services/util/create_unit_e_dense_inv_metric.hpp +++ b/src/stan/services/util/create_unit_e_dense_inv_metric.hpp @@ -17,17 +17,13 @@ namespace util { * @return var_context */ inline stan::io::dump create_unit_e_dense_inv_metric(size_t num_params) { - Eigen::MatrixXd inv_metric(num_params, num_params); - inv_metric.setIdentity(); - size_t num_elements = num_params * num_params; + auto num_params_str = std::to_string(num_params); + std::string dims("),.Dim=c(" + num_params_str + ", " + num_params_str + "))"); + Eigen::IOFormat + RFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ",", "", "", + "inv_metric <- structure(c(", dims); std::stringstream txt; - txt << "inv_metric <- structure(c("; - for (size_t i = 0; i < num_elements; i++) { - txt << inv_metric(i); - if (i < num_elements - 1) - txt << ", "; - } - txt << "),.Dim=c(" << num_params << ", " << num_params << "))"; + txt << Eigen::MatrixXd::Identity(num_params, num_params).format(RFmt); return stan::io::dump(txt); } } // namespace util diff --git a/src/stan/services/util/create_unit_e_diag_inv_metric.hpp b/src/stan/services/util/create_unit_e_diag_inv_metric.hpp index 18375e68f94..a3800fe14eb 100644 --- a/src/stan/services/util/create_unit_e_diag_inv_metric.hpp +++ b/src/stan/services/util/create_unit_e_diag_inv_metric.hpp @@ -16,14 +16,12 @@ namespace util { * @return var_context */ inline stan::io::dump create_unit_e_diag_inv_metric(size_t num_params) { + std::string dims("),.Dim=c(" + std::to_string(num_params) + "))"); + Eigen::IOFormat + RFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ",", "", "", + "inv_metric <- structure(c(", dims); std::stringstream txt; - txt << "inv_metric <- structure(c("; - for (size_t i = 0; i < num_params; ++i) { - txt << "1.0"; - if (i < num_params - 1) - txt << ", "; - } - txt << "),.Dim=c(" << num_params << "))"; + txt << Eigen::VectorXd::Ones(num_params).format(RFmt); return stan::io::dump(txt); } } // namespace util diff --git a/src/stan/services/util/initialize.hpp b/src/stan/services/util/initialize.hpp index fd180819b99..c871c49fbd5 100644 --- a/src/stan/services/util/initialize.hpp +++ b/src/stan/services/util/initialize.hpp @@ -65,8 +65,8 @@ namespace util { * std::domain_error) * @return valid unconstrained parameters for the model */ -template -std::vector initialize(Model& model, const stan::io::var_context& init, +template +std::vector initialize(Model& model, const InitContext& init, RNG& rng, double init_radius, bool print_timing, stan::callbacks::logger& logger, stan::callbacks::writer& init_writer) { diff --git a/src/test/unit/services/check_adaptation.hpp b/src/test/unit/services/check_adaptation.hpp index e5d3f52dd4c..fb8fe3e3f04 100644 --- a/src/test/unit/services/check_adaptation.hpp +++ b/src/test/unit/services/check_adaptation.hpp @@ -14,9 +14,7 @@ namespace test { namespace unit { double stod(const std::string& val) { - char tmp[val.length()]; - strcpy(tmp, val.c_str()); - return atof(tmp); + return atof(val.c_str()); } void check_adaptation(const size_t& num_params, From 99d64c1deb63ca123330373a04a31914c93f9391 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Mar 2021 15:15:59 -0400 Subject: [PATCH 12/47] adds tests for parallel adapter --- .../hmc_nuts_diag_e_adapt_parallel_test.cpp | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp new file mode 100644 index 00000000000..5e90c450566 --- /dev/null +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include + +auto&& blah = stan::math::init_threadpool_tbb(); + +static constexpr size_t num_chains = 4; +class ServicesSampleHmcNutsDiagEAdaptPar : public testing::Test { + public: + ServicesSampleHmcNutsDiagEAdaptPar() : model(data_context, 0, &model_log) { + for (int i = 0; i < num_chains; ++i) { + parameter.push_back(stan::test::unit::instrumented_writer{}); + diagnostic.push_back(stan::test::unit::instrumented_writer{}); + context.push_back(stan::io::empty_var_context{}); + } + } + stan::io::empty_var_context data_context; + std::stringstream model_log; + stan::test::unit::instrumented_logger logger; + stan::test::unit::instrumented_writer init; + std::vector parameter, diagnostic; + std::vector context; + stan_model model; +}; + +TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, call_count) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 200; + int num_samples = 400; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 50; + unsigned int term_buffer = 50; + unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic, num_chains); + + EXPECT_EQ(0, return_code); + + int num_output_lines = (num_warmup + num_samples) / num_thin; + EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); + for (int i = 0; i < num_chains; ++i) { + EXPECT_EQ(1, parameter[i].call_count("vector_string")); + EXPECT_EQ(num_output_lines, parameter[i].call_count("vector_double")); + EXPECT_EQ(1, diagnostic[i].call_count("vector_string")); + EXPECT_EQ(num_output_lines, diagnostic[i].call_count("vector_double")); + } +} + +TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, parameter_checks) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 200; + int num_samples = 400; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 50; + unsigned int term_buffer = 50; + unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic, num_chains); + + for (size_t i = 0; i < num_chains; ++i) { + std::vector> parameter_names; + parameter_names = parameter[i].vector_string_values(); + std::vector> parameter_values; + parameter_values = parameter[i].vector_double_values(); + std::vector> diagnostic_names; + diagnostic_names = diagnostic[i].vector_string_values(); + std::vector> diagnostic_values; + diagnostic_values = diagnostic[i].vector_double_values(); + + // Expectations of parameter parameter names. + ASSERT_EQ(9, parameter_names[0].size()); + EXPECT_EQ("lp__", parameter_names[0][0]); + EXPECT_EQ("accept_stat__", parameter_names[0][1]); + EXPECT_EQ("stepsize__", parameter_names[0][2]); + EXPECT_EQ("treedepth__", parameter_names[0][3]); + EXPECT_EQ("n_leapfrog__", parameter_names[0][4]); + EXPECT_EQ("divergent__", parameter_names[0][5]); + EXPECT_EQ("energy__", parameter_names[0][6]); + EXPECT_EQ("x", parameter_names[0][7]); + EXPECT_EQ("y", parameter_names[0][8]); + + // Expect one name per parameter value. + EXPECT_EQ(parameter_names[0].size(), parameter_values[0].size()); + EXPECT_EQ(diagnostic_names[0].size(), diagnostic_values[0].size()); + + EXPECT_EQ((num_warmup + num_samples) / num_thin, parameter_values.size()); + + // Expect one call to set parameter names, and one set of output per + // iteration. + EXPECT_EQ("lp__", diagnostic_names[0][0]); + EXPECT_EQ("accept_stat__", diagnostic_names[0][1]); + } + EXPECT_EQ(return_code, 0); +} + + +TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, output_regression) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 200; + int num_samples = 400; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 50; + unsigned int term_buffer = 50; + unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + stan::services::sample::hmc_nuts_diag_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic, num_chains); + + std::vector init_values; + init_values = init.string_values(); + + EXPECT_EQ(0, init_values.size()); + + EXPECT_EQ(num_chains, logger.find_info("Elapsed Time:")); + EXPECT_EQ(num_chains, logger.find_info("seconds (Warm-up)")); + EXPECT_EQ(num_chains, logger.find_info("seconds (Sampling)")); + EXPECT_EQ(num_chains, logger.find_info("seconds (Total)")); + EXPECT_EQ(0, logger.call_count_error()); +} From ebeb1f9b1e801b28e5f3418388ca706db21274d3 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Mar 2021 18:25:17 -0400 Subject: [PATCH 13/47] remove statics from softmax metric and cleanup tests --- .../mcmc/hmc/hamiltonians/softabs_metric.hpp | 12 ++--- .../services/util/run_adaptive_sampler.hpp | 36 +++++++-------- .../run_adaptive_sampler_parallel_test.cpp | 44 ++++++++++--------- 3 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/stan/mcmc/hmc/hamiltonians/softabs_metric.hpp b/src/stan/mcmc/hmc/hamiltonians/softabs_metric.hpp index 10f24dffe48..da2e392c90b 100644 --- a/src/stan/mcmc/hmc/hamiltonians/softabs_metric.hpp +++ b/src/stan/mcmc/hmc/hamiltonians/softabs_metric.hpp @@ -174,26 +174,26 @@ class softabs_metric : public base_hamiltonian { // Threshold below which a power series // approximation of the softabs function is used - static double lower_softabs_thresh; + static constexpr double lower_softabs_thresh = 1e-4; // Threshold above which an asymptotic // approximation of the softabs function is used - static double upper_softabs_thresh; + static constexpr double upper_softabs_thresh = 18; // Threshold below which an exact derivative is // used in the Jacobian calculation instead of // finite differencing - static double jacobian_thresh; + static constexpr double jacobian_thresh = 1e-10; }; template -double softabs_metric::lower_softabs_thresh = 1e-4; +constexpr double softabs_metric::lower_softabs_thresh; template -double softabs_metric::upper_softabs_thresh = 18; +constexpr double softabs_metric::upper_softabs_thresh; template -double softabs_metric::jacobian_thresh = 1e-10; +constexpr double softabs_metric::jacobian_thresh; } // namespace mcmc } // namespace stan #endif diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index ef325eb807b..908116d281a 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -106,34 +106,28 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, interrupt, logger, sample_writers[0], diagnostic_writers[0]); } - std::vector samples; - samples.reserve(n_chain); - for (int i = 0; i < n_chain; ++i) { - auto&& sampler = samplers[i]; - sampler.engage_adaptation(); - Eigen::Map cont_params(cont_vectors[i].data(), - cont_vectors[i].size()); - try { - sampler.z().q = cont_params; - sampler.init_stepsize(logger); - } catch (const std::exception& e) { - logger.info("Exception initializing step size."); - logger.info(e.what()); - return; - } - samples.emplace_back(cont_params, 0, 0); - } tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, &samples, - &samplers, &model, &rngs, &interrupt, &logger, &sample_writers, + [num_warmup, num_samples, num_thin, refresh, save_warmup, + &samplers, &model, &rngs, &interrupt, &logger, &sample_writers, &cont_vectors, &diagnostic_writers](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { + auto&& sampler = samplers[i]; + sampler.engage_adaptation(); + Eigen::Map cont_params(cont_vectors[i].data(), + cont_vectors[i].size()); + try { + sampler.z().q = cont_params; + sampler.init_stepsize(logger); + } catch (const std::exception& e) { + logger.info("Exception initializing step size."); + logger.info(e.what()); + return; + } + stan::mcmc::sample samp(cont_params, 0, 0); auto&& sample_writer = sample_writers[i]; auto writer = services::util::mcmc_writer( sample_writer, diagnostic_writers[i], logger); - auto&& sampler = samplers[i]; - auto&& samp = samples[i]; // Headers writer.write_sample_names(samp, sampler, model); diff --git a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp index 2fd2d91ddaf..55b710f20f3 100644 --- a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp +++ b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp @@ -9,23 +9,25 @@ auto&& blah = stan::math::init_threadpool_tbb(); +static constexpr size_t num_chains = 5; + class ServicesUtil : public testing::Test { using model_t = stan::mcmc::adapt_unit_e_nuts; public: ServicesUtil() : model(context, 0, &model_log), - rng(3), - cont_vector(3, std::vector{0, 0}), + rng(num_chains), + cont_vector(num_chains, std::vector{0, 0}), sampler(), num_warmup(0), num_samples(0), num_thin(1), refresh(0), - n_chain(3), + n_chain(num_chains), save_warmup(false) { rng.clear(); - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < num_chains; ++i) { rng[i] = std::move(stan::services::util::create_rng(0, 1)); sampler.push_back(model_t(model, rng[i])); sample_writer.push_back(stan::test::unit::instrumented_writer{}); @@ -50,10 +52,10 @@ class ServicesUtil : public testing::Test { TEST_F(ServicesUtil, all_zero) { stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); EXPECT_EQ(0, interrupt.call_count()); - EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -74,10 +76,10 @@ TEST_F(ServicesUtil, num_warmup_no_save) { num_warmup = 1000; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); - EXPECT_EQ(num_warmup * 3, interrupt.call_count()); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + EXPECT_EQ(num_warmup * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -99,10 +101,10 @@ TEST_F(ServicesUtil, num_warmup_save) { save_warmup = true; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); - EXPECT_EQ((num_warmup)*3, interrupt.call_count()); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + EXPECT_EQ((num_warmup) * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -127,10 +129,10 @@ TEST_F(ServicesUtil, num_samples) { num_samples = 1000; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); - EXPECT_EQ(num_samples * 3, interrupt.call_count()); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + EXPECT_EQ(num_samples * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -158,10 +160,10 @@ TEST_F(ServicesUtil, num_warmup_save_num_samples_num_thin) { num_thin = 10; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); - EXPECT_EQ((num_warmup + num_samples) * 3, interrupt.call_count()); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * 3, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -191,10 +193,10 @@ TEST_F(ServicesUtil, num_warmup_num_samples_refresh) { refresh = 10; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, 3); - EXPECT_EQ((num_warmup + num_samples) * 3, interrupt.call_count()); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); - EXPECT_EQ((num_warmup * 3 + num_samples * 3) / refresh + (2 + 3 + 2) * 3, + EXPECT_EQ((num_warmup * num_chains + num_samples * num_chains) / refresh + (2 + 3 + 2) * num_chains, logger.call_count()) << "Writes 1 to start warmup, 1 to start post-warmup, and " << "(num_warmup + num_samples) / refresh, then the elapsed time"; From 558eeb06c46337fe8f619bff792c368eb96d047f Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 24 Mar 2021 18:56:44 -0400 Subject: [PATCH 14/47] use normal diag_e_adapt if n_chain == 0 --- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 132 ++++++++++-------- 1 file changed, 73 insertions(+), 59 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 85a6ee3c35d..6f9b2776f3b 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -53,17 +53,17 @@ namespace sample { * @param[in,out] diagnostic_writer Writer for diagnostic information * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( - Model& model, const stan::io::var_context& init, - const stan::io::var_context& init_inv_metric, unsigned int random_seed, + Model& model, const InitContext& init, + const InitMetricContext& init_inv_metric, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& init_writer, - callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer) { + SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { boost::ecuyer1988 rng = util::create_rng(random_seed, chain); std::vector cont_vector = util::initialize( @@ -132,28 +132,26 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] diagnostic_writer Writer for diagnostic information * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( - Model& model, const stan::io::var_context& init, unsigned int random_seed, + Model& model, const InitContext& init, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& init_writer, - callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer) { + SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { stan::io::dump dmp = util::create_unit_e_diag_inv_metric(model.num_params_r()); - stan::io::var_context& unit_e_metric = dmp; - return hmc_nuts_diag_e_adapt( - model, init, unit_e_metric, random_seed, chain, init_radius, num_warmup, + model, init, dmp, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, diagnostic_writer); } -template +template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, const std::vector& init_inv_metric, unsigned int random_seed, @@ -163,49 +161,57 @@ int hmc_nuts_diag_e_adapt( double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& init_writer, - std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - using sample_t = stan::mcmc::adapt_diag_e_nuts; - std::vector rngs; - rngs.reserve(n_chain); - std::vector> cont_vectors; - cont_vectors.reserve(n_chain); - std::vector samplers; - samplers.reserve(n_chain); - try { - for (int i = 0; i < n_chain; ++i) { - rngs.emplace_back(util::create_rng(random_seed, chain + i)); - cont_vectors.emplace_back(util::initialize( - model, init[i], rngs[i], init_radius, true, logger, init_writer)); - samplers.emplace_back(model, rngs[i]); - Eigen::VectorXd inv_metric = util::read_diag_inv_metric(init_inv_metric[i], - model.num_params_r(), logger); - util::validate_diag_inv_metric(inv_metric, logger); - - samplers[i].set_metric(inv_metric); - samplers[i].set_nominal_stepsize(stepsize); - samplers[i].set_stepsize_jitter(stepsize_jitter); - samplers[i].set_max_depth(max_depth); - - samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); - samplers[i].get_stepsize_adaptation().set_delta(delta); - samplers[i].get_stepsize_adaptation().set_gamma(gamma); - samplers[i].get_stepsize_adaptation().set_kappa(kappa); - samplers[i].get_stepsize_adaptation().set_t0(t0); - samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, window, - logger); - + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + if (n_chain == 0) { + return hmc_nuts_diag_e_adapt( + model, init[0], init_inv_metric[0], random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); + } else { + using sample_t = stan::mcmc::adapt_diag_e_nuts; + std::vector rngs; + rngs.reserve(n_chain); + std::vector> cont_vectors; + cont_vectors.reserve(n_chain); + std::vector samplers; + samplers.reserve(n_chain); + try { + for (int i = 0; i < n_chain; ++i) { + rngs.emplace_back(util::create_rng(random_seed, chain + i)); + cont_vectors.emplace_back(util::initialize( + model, init[i], rngs[i], init_radius, true, logger, init_writer)); + samplers.emplace_back(model, rngs[i]); + Eigen::VectorXd inv_metric = util::read_diag_inv_metric(init_inv_metric[i], + model.num_params_r(), logger); + util::validate_diag_inv_metric(inv_metric, logger); + + samplers[i].set_metric(inv_metric); + samplers[i].set_nominal_stepsize(stepsize); + samplers[i].set_stepsize_jitter(stepsize_jitter); + samplers[i].set_max_depth(max_depth); + + samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); + samplers[i].get_stepsize_adaptation().set_delta(delta); + samplers[i].get_stepsize_adaptation().set_gamma(gamma); + samplers[i].get_stepsize_adaptation().set_kappa(kappa); + samplers[i].get_stepsize_adaptation().set_t0(t0); + samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, window, + logger); + + } + } catch (const std::domain_error& e) { + return error_codes::CONFIG; } - } catch (const std::domain_error& e) { - return error_codes::CONFIG; - } - util::run_adaptive_sampler( - samplers, model, cont_vectors, num_warmup, num_samples, num_thin, refresh, - save_warmup, rngs, interrupt, logger, sample_writer, diagnostic_writer, n_chain); + util::run_adaptive_sampler( + samplers, model, cont_vectors, num_warmup, num_samples, num_thin, refresh, + save_warmup, rngs, interrupt, logger, sample_writer, diagnostic_writer, n_chain); - return error_codes::OK; + return error_codes::OK; + } } -template +template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, @@ -214,15 +220,23 @@ int hmc_nuts_diag_e_adapt( double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& init_writer, - std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - stan::io::dump dmp - = util::create_unit_e_diag_inv_metric(model.num_params_r()); - std::vector unit_e_metrics(n_chain, dmp); - return hmc_nuts_diag_e_adapt( - model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + if (n_chain == 0) { + return hmc_nuts_diag_e_adapt( + model, init[0], random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); + } else { + stan::io::dump dmp + = util::create_unit_e_diag_inv_metric(model.num_params_r()); + std::vector unit_e_metrics(n_chain, dmp); + return hmc_nuts_diag_e_adapt( + model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); + } } From 5055e218f879bdb6aabd027c67f101440f390b1b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 25 Mar 2021 00:17:25 +0000 Subject: [PATCH 15/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 106 +++++++++--------- .../util/create_unit_e_dense_inv_metric.hpp | 5 +- .../util/create_unit_e_diag_inv_metric.hpp | 5 +- src/stan/services/util/initialize.hpp | 7 +- .../services/util/run_adaptive_sampler.hpp | 4 +- src/test/unit/services/check_adaptation.hpp | 4 +- .../hmc_nuts_diag_e_adapt_parallel_test.cpp | 3 +- .../run_adaptive_sampler_parallel_test.cpp | 38 ++++--- 8 files changed, 93 insertions(+), 79 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 6f9b2776f3b..4f9aafac282 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -53,7 +53,8 @@ namespace sample { * @param[in,out] diagnostic_writer Writer for diagnostic information * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( Model& model, const InitContext& init, const InitMetricContext& init_inv_metric, unsigned int random_seed, @@ -132,7 +133,8 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] diagnostic_writer Writer for diagnostic information * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( Model& model, const InitContext& init, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, @@ -151,23 +153,26 @@ int hmc_nuts_diag_e_adapt( interrupt, logger, init_writer, sample_writer, diagnostic_writer); } -template +template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, - const std::vector& init_inv_metric, unsigned int random_seed, - unsigned int chain, double init_radius, int num_warmup, int num_samples, - int num_thin, bool save_warmup, int refresh, double stepsize, - double stepsize_jitter, int max_depth, double delta, double gamma, - double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, - unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& init_writer, - std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + const std::vector& init_inv_metric, + unsigned int random_seed, unsigned int chain, double init_radius, + int num_warmup, int num_samples, int num_thin, bool save_warmup, + int refresh, double stepsize, double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, double t0, + unsigned int init_buffer, unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, callbacks::logger& logger, + callbacks::writer& init_writer, std::vector& sample_writer, + std::vector& diagnostic_writer, size_t n_chain) { if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, init[0], init_inv_metric[0], random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); + model, init[0], init_inv_metric[0], random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer, sample_writer[0], + diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; std::vector rngs; @@ -182,8 +187,8 @@ int hmc_nuts_diag_e_adapt( cont_vectors.emplace_back(util::initialize( model, init[i], rngs[i], init_radius, true, logger, init_writer)); samplers.emplace_back(model, rngs[i]); - Eigen::VectorXd inv_metric = util::read_diag_inv_metric(init_inv_metric[i], - model.num_params_r(), logger); + Eigen::VectorXd inv_metric = util::read_diag_inv_metric( + init_inv_metric[i], model.num_params_r(), logger); util::validate_diag_inv_metric(inv_metric, logger); samplers[i].set_metric(inv_metric); @@ -196,51 +201,52 @@ int hmc_nuts_diag_e_adapt( samplers[i].get_stepsize_adaptation().set_gamma(gamma); samplers[i].get_stepsize_adaptation().set_kappa(kappa); samplers[i].get_stepsize_adaptation().set_t0(t0); - samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, window, - logger); - + samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, + window, logger); } } catch (const std::domain_error& e) { return error_codes::CONFIG; } - util::run_adaptive_sampler( - samplers, model, cont_vectors, num_warmup, num_samples, num_thin, refresh, - save_warmup, rngs, interrupt, logger, sample_writer, diagnostic_writer, n_chain); + util::run_adaptive_sampler(samplers, model, cont_vectors, num_warmup, + num_samples, num_thin, refresh, save_warmup, + rngs, interrupt, logger, sample_writer, + diagnostic_writer, n_chain); return error_codes::OK; } } -template +template int hmc_nuts_diag_e_adapt( - Model& model, const std::vector& init, unsigned int random_seed, - unsigned int chain, double init_radius, int num_warmup, int num_samples, - int num_thin, bool save_warmup, int refresh, double stepsize, - double stepsize_jitter, int max_depth, double delta, double gamma, - double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, - unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& init_writer, - std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - if (n_chain == 0) { - return hmc_nuts_diag_e_adapt( - model, init[0], random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); - } else { - stan::io::dump dmp - = util::create_unit_e_diag_inv_metric(model.num_params_r()); - std::vector unit_e_metrics(n_chain, dmp); - return hmc_nuts_diag_e_adapt( - model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); - } + Model& model, const std::vector& init, + unsigned int random_seed, unsigned int chain, double init_radius, + int num_warmup, int num_samples, int num_thin, bool save_warmup, + int refresh, double stepsize, double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, double t0, + unsigned int init_buffer, unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, callbacks::logger& logger, + callbacks::writer& init_writer, std::vector& sample_writer, + std::vector& diagnostic_writer, size_t n_chain) { + if (n_chain == 0) { + return hmc_nuts_diag_e_adapt( + model, init[0], random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); + } else { + stan::io::dump dmp + = util::create_unit_e_diag_inv_metric(model.num_params_r()); + std::vector unit_e_metrics(n_chain, dmp); + return hmc_nuts_diag_e_adapt( + model, init, unit_e_metrics, random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer, sample_writer, + diagnostic_writer, n_chain); + } } - - } // namespace sample } // namespace services } // namespace stan diff --git a/src/stan/services/util/create_unit_e_dense_inv_metric.hpp b/src/stan/services/util/create_unit_e_dense_inv_metric.hpp index 8d2a7bd60c6..ee9afc670a6 100644 --- a/src/stan/services/util/create_unit_e_dense_inv_metric.hpp +++ b/src/stan/services/util/create_unit_e_dense_inv_metric.hpp @@ -19,9 +19,8 @@ namespace util { inline stan::io::dump create_unit_e_dense_inv_metric(size_t num_params) { auto num_params_str = std::to_string(num_params); std::string dims("),.Dim=c(" + num_params_str + ", " + num_params_str + "))"); - Eigen::IOFormat - RFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ",", "", "", - "inv_metric <- structure(c(", dims); + Eigen::IOFormat RFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ",", + "", "", "inv_metric <- structure(c(", dims); std::stringstream txt; txt << Eigen::MatrixXd::Identity(num_params, num_params).format(RFmt); return stan::io::dump(txt); diff --git a/src/stan/services/util/create_unit_e_diag_inv_metric.hpp b/src/stan/services/util/create_unit_e_diag_inv_metric.hpp index a3800fe14eb..e14a80e3283 100644 --- a/src/stan/services/util/create_unit_e_diag_inv_metric.hpp +++ b/src/stan/services/util/create_unit_e_diag_inv_metric.hpp @@ -17,9 +17,8 @@ namespace util { */ inline stan::io::dump create_unit_e_diag_inv_metric(size_t num_params) { std::string dims("),.Dim=c(" + std::to_string(num_params) + "))"); - Eigen::IOFormat - RFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ",", "", "", - "inv_metric <- structure(c(", dims); + Eigen::IOFormat RFmt(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ",", + "", "", "inv_metric <- structure(c(", dims); std::stringstream txt; txt << Eigen::VectorXd::Ones(num_params).format(RFmt); return stan::io::dump(txt); diff --git a/src/stan/services/util/initialize.hpp b/src/stan/services/util/initialize.hpp index c871c49fbd5..696013531c9 100644 --- a/src/stan/services/util/initialize.hpp +++ b/src/stan/services/util/initialize.hpp @@ -65,9 +65,10 @@ namespace util { * std::domain_error) * @return valid unconstrained parameters for the model */ -template -std::vector initialize(Model& model, const InitContext& init, - RNG& rng, double init_radius, bool print_timing, +template +std::vector initialize(Model& model, const InitContext& init, RNG& rng, + double init_radius, bool print_timing, stan::callbacks::logger& logger, stan::callbacks::writer& init_writer) { std::vector unconstrained; diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 908116d281a..dc2105b290a 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -108,8 +108,8 @@ void run_adaptive_sampler(std::vector& samplers, Model& model, } tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, - &samplers, &model, &rngs, &interrupt, &logger, &sample_writers, &cont_vectors, + [num_warmup, num_samples, num_thin, refresh, save_warmup, &samplers, + &model, &rngs, &interrupt, &logger, &sample_writers, &cont_vectors, &diagnostic_writers](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { auto&& sampler = samplers[i]; diff --git a/src/test/unit/services/check_adaptation.hpp b/src/test/unit/services/check_adaptation.hpp index fb8fe3e3f04..af863ea8139 100644 --- a/src/test/unit/services/check_adaptation.hpp +++ b/src/test/unit/services/check_adaptation.hpp @@ -13,9 +13,7 @@ namespace stan { namespace test { namespace unit { -double stod(const std::string& val) { - return atof(val.c_str()); -} +double stod(const std::string& val) { return atof(val.c_str()); } void check_adaptation(const size_t& num_params, const std::vector& param_vals, diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp index 5e90c450566..055316c17e2 100644 --- a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp @@ -127,10 +127,9 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, parameter_checks) { EXPECT_EQ("lp__", diagnostic_names[0][0]); EXPECT_EQ("accept_stat__", diagnostic_names[0][1]); } - EXPECT_EQ(return_code, 0); + EXPECT_EQ(return_code, 0); } - TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, output_regression) { unsigned int random_seed = 0; unsigned int chain = 1; diff --git a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp index 55b710f20f3..5d483864b50 100644 --- a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp +++ b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp @@ -52,10 +52,12 @@ class ServicesUtil : public testing::Test { TEST_F(ServicesUtil, all_zero) { stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, + num_chains); EXPECT_EQ(0, interrupt.call_count()); - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) + << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -76,10 +78,12 @@ TEST_F(ServicesUtil, num_warmup_no_save) { num_warmup = 1000; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, + num_chains); EXPECT_EQ(num_warmup * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) + << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -101,10 +105,12 @@ TEST_F(ServicesUtil, num_warmup_save) { save_warmup = true; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ((num_warmup) * num_chains, interrupt.call_count()); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, + num_chains); + EXPECT_EQ((num_warmup)*num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) + << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -129,10 +135,12 @@ TEST_F(ServicesUtil, num_samples) { num_samples = 1000; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, + num_chains); EXPECT_EQ(num_samples * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) + << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -160,10 +168,12 @@ TEST_F(ServicesUtil, num_warmup_save_num_samples_num_thin) { num_thin = 10; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, + num_chains); EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; + EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) + << "Writes the elapsed time"; EXPECT_EQ(logger.call_count(), logger.call_count_info()) << "No other calls to logger"; @@ -193,10 +203,12 @@ TEST_F(ServicesUtil, num_warmup_num_samples_refresh) { refresh = 10; stan::services::util::run_adaptive_sampler( sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); + save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, + num_chains); EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); - EXPECT_EQ((num_warmup * num_chains + num_samples * num_chains) / refresh + (2 + 3 + 2) * num_chains, + EXPECT_EQ((num_warmup * num_chains + num_samples * num_chains) / refresh + + (2 + 3 + 2) * num_chains, logger.call_count()) << "Writes 1 to start warmup, 1 to start post-warmup, and " << "(num_warmup + num_samples) / refresh, then the elapsed time"; From 34114beac35fb4c431454a7af9261b689e526e4f Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 25 Mar 2021 12:52:36 -0400 Subject: [PATCH 16/47] use parallel loop around run_adaptive_sampler --- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 6f9b2776f3b..92538476900 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -203,9 +203,18 @@ int hmc_nuts_diag_e_adapt( } catch (const std::domain_error& e) { return error_codes::CONFIG; } - util::run_adaptive_sampler( - samplers, model, cont_vectors, num_warmup, num_samples, num_thin, refresh, - save_warmup, rngs, interrupt, logger, sample_writer, diagnostic_writer, n_chain); + tbb::parallel_for( + tbb::blocked_range(0, n_chain, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, + &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, + &diagnostic_writer](const tbb::blocked_range& r) { + for (size_t i = r.begin(); i != r.end(); ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, + save_warmup, rngs[i], interrupt, logger, sample_writer[i], diagnostic_writer[i]); + } + }, + tbb::simple_partitioner()); return error_codes::OK; } From 845878234be7ba55a771289739ec535e0d471b6c Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 25 Mar 2021 18:17:35 -0400 Subject: [PATCH 17/47] remove run_adaptive_sampler parallel version --- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 24 +- .../services/util/generate_transitions.hpp | 6 +- .../services/util/run_adaptive_sampler.hpp | 81 +------ .../run_adaptive_sampler_parallel_test.cpp | 220 ------------------ 4 files changed, 27 insertions(+), 304 deletions(-) delete mode 100644 src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 92538476900..f667ce51c1e 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -151,6 +151,22 @@ int hmc_nuts_diag_e_adapt( interrupt, logger, init_writer, sample_writer, diagnostic_writer); } +namespace internal { + + template + inline const auto& get_context(const std::shared_ptr& x) { + return *x; + } + + /** + * Specialization + */ + template + inline auto get_context(Context&& x) { + return std::forward(x); + } + +} template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, @@ -162,9 +178,10 @@ int hmc_nuts_diag_e_adapt( unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + using internal::get_context; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, init[0], init_inv_metric[0], random_seed, chain, init_radius, num_warmup, + model, get_context(init[0]), init_inv_metric[0], random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); @@ -211,7 +228,7 @@ int hmc_nuts_diag_e_adapt( for (size_t i = r.begin(); i != r.end(); ++i) { util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, - save_warmup, rngs[i], interrupt, logger, sample_writer[i], diagnostic_writer[i]); + save_warmup, rngs[i], interrupt, logger, sample_writer[i], diagnostic_writer[i], i + 1); } }, tbb::simple_partitioner()); @@ -230,9 +247,10 @@ int hmc_nuts_diag_e_adapt( unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + using internal::get_context; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, init[0], random_seed, chain, init_radius, num_warmup, + model, get_context(init[0]), random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index 8ad93706c6a..cbef5f1782e 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -44,7 +44,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, util::mcmc_writer& mcmc_writer, stan::mcmc::sample& init_s, Model& model, RNG& base_rng, callbacks::interrupt& callback, - callbacks::logger& logger, size_t n_chain = 0) { + callbacks::logger& logger, size_t chain_id = 0) { for (int m = 0; m < num_iterations; ++m) { callback(); @@ -52,8 +52,8 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, && (start + m + 1 == finish || m == 0 || (m + 1) % refresh == 0)) { int it_print_width = std::ceil(std::log10(static_cast(finish))); std::stringstream message; - if (n_chain > 0) { - message << "Chain [" << (n_chain + 1) << "]"; + if (chain_id != 0) { + message << "Chain [" << chain_id << "] "; } message << "Iteration: "; message << std::setw(it_print_width) << m + 1 + start << " / " << finish; diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 908116d281a..9b445eae02e 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -43,7 +43,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& sample_writer, - callbacks::writer& diagnostic_writer) { + callbacks::writer& diagnostic_writer, size_t chain_id = 0) { Eigen::Map cont_params(cont_vector.data(), cont_vector.size()); @@ -67,7 +67,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, auto start_warm = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_warmup, 0, num_warmup + num_samples, num_thin, refresh, save_warmup, true, writer, s, - model, rng, interrupt, logger); + model, rng, interrupt, logger, chain_id); auto end_warm = std::chrono::steady_clock::now(); double warm_delta_t = std::chrono::duration_cast( end_warm - start_warm) @@ -80,7 +80,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, auto start_sample = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_samples, num_warmup, num_warmup + num_samples, num_thin, refresh, true, - false, writer, s, model, rng, interrupt, logger); + false, writer, s, model, rng, interrupt, logger, chain_id); auto end_sample = std::chrono::steady_clock::now(); double sample_delta_t = std::chrono::duration_cast( end_sample - start_sample) @@ -89,81 +89,6 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, writer.write_timing(warm_delta_t, sample_delta_t); } -template -void run_adaptive_sampler(std::vector& samplers, Model& model, - std::vector>& cont_vectors, - int num_warmup, int num_samples, int num_thin, - int refresh, bool save_warmup, std::vector& rngs, - callbacks::interrupt& interrupt, - callbacks::logger& logger, - std::vector& sample_writers, - std::vector& diagnostic_writers, - size_t n_chain) { - if (n_chain == 0) { - run_adaptive_sampler(samplers[0], model, cont_vectors[0], num_warmup, - num_samples, num_thin, refresh, save_warmup, rngs[0], - interrupt, logger, sample_writers[0], - diagnostic_writers[0]); - } - tbb::parallel_for( - tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, - &samplers, &model, &rngs, &interrupt, &logger, &sample_writers, &cont_vectors, - &diagnostic_writers](const tbb::blocked_range& r) { - for (size_t i = r.begin(); i != r.end(); ++i) { - auto&& sampler = samplers[i]; - sampler.engage_adaptation(); - Eigen::Map cont_params(cont_vectors[i].data(), - cont_vectors[i].size()); - try { - sampler.z().q = cont_params; - sampler.init_stepsize(logger); - } catch (const std::exception& e) { - logger.info("Exception initializing step size."); - logger.info(e.what()); - return; - } - stan::mcmc::sample samp(cont_params, 0, 0); - auto&& sample_writer = sample_writers[i]; - auto writer = services::util::mcmc_writer( - sample_writer, diagnostic_writers[i], logger); - - // Headers - writer.write_sample_names(samp, sampler, model); - writer.write_diagnostic_names(samp, sampler, model); - - const auto start_warm = std::chrono::steady_clock::now(); - util::generate_transitions(sampler, num_warmup, 0, - num_warmup + num_samples, num_thin, - refresh, save_warmup, true, writer, samp, - model, rngs[i], interrupt, logger, i); - const auto end_warm = std::chrono::steady_clock::now(); - auto warm_delta - = std::chrono::duration_cast( - end_warm - start_warm) - .count() - / 1000.0; - sampler.disengage_adaptation(); - writer.write_adapt_finish(sampler); - sampler.write_sampler_state(sample_writer); - - const auto start_sample = std::chrono::steady_clock::now(); - util::generate_transitions(sampler, num_samples, num_warmup, - num_warmup + num_samples, num_thin, - refresh, true, false, writer, samp, model, - rngs[i], interrupt, logger, i); - const auto end_sample = std::chrono::steady_clock::now(); - auto sample_delta - = std::chrono::duration_cast( - end_sample - start_sample) - .count() - / 1000.0; - writer.write_timing(warm_delta, sample_delta); - } - }, - tbb::simple_partitioner()); -} } // namespace util } // namespace services diff --git a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp b/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp deleted file mode 100644 index 55b710f20f3..00000000000 --- a/src/test/unit/services/util/run_adaptive_sampler_parallel_test.cpp +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -auto&& blah = stan::math::init_threadpool_tbb(); - -static constexpr size_t num_chains = 5; - -class ServicesUtil : public testing::Test { - using model_t = stan::mcmc::adapt_unit_e_nuts; - - public: - ServicesUtil() - : model(context, 0, &model_log), - rng(num_chains), - cont_vector(num_chains, std::vector{0, 0}), - sampler(), - num_warmup(0), - num_samples(0), - num_thin(1), - refresh(0), - n_chain(num_chains), - save_warmup(false) { - rng.clear(); - for (int i = 0; i < num_chains; ++i) { - rng[i] = std::move(stan::services::util::create_rng(0, 1)); - sampler.push_back(model_t(model, rng[i])); - sample_writer.push_back(stan::test::unit::instrumented_writer{}); - diagnostic_writer.push_back(stan::test::unit::instrumented_writer{}); - } - } - - std::stringstream model_log; - stan::io::empty_var_context context; - stan_model model; - std::vector> cont_vector; - std::vector rng; - stan::test::unit::instrumented_interrupt interrupt; - std::vector sample_writer, - diagnostic_writer; - stan::test::unit::instrumented_logger logger; - std::vector sampler; - int num_warmup, num_samples, num_thin, refresh, n_chain; - bool save_warmup; -}; - -TEST_F(ServicesUtil, all_zero) { - stan::services::util::run_adaptive_sampler( - sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ(0, interrupt.call_count()); - - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; - EXPECT_EQ(logger.call_count(), logger.call_count_info()) - << "No other calls to logger"; - - EXPECT_EQ(8, sample_writer[0].call_count()); - EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; - EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) - << "adaptation info + elapsed time"; - EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - - EXPECT_EQ(6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) - << "header line"; - EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; -} - -TEST_F(ServicesUtil, num_warmup_no_save) { - num_warmup = 1000; - stan::services::util::run_adaptive_sampler( - sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ(num_warmup * num_chains, interrupt.call_count()); - - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; - EXPECT_EQ(logger.call_count(), logger.call_count_info()) - << "No other calls to logger"; - - EXPECT_EQ(8, sample_writer[0].call_count()); - EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; - EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) - << "adaptation info + elapsed time"; - EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - - EXPECT_EQ(6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) - << "header line"; - EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; -} - -TEST_F(ServicesUtil, num_warmup_save) { - num_warmup = 1000; - save_warmup = true; - stan::services::util::run_adaptive_sampler( - sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ((num_warmup) * num_chains, interrupt.call_count()); - - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; - EXPECT_EQ(logger.call_count(), logger.call_count_info()) - << "No other calls to logger"; - - EXPECT_EQ(num_warmup + 8, sample_writer[0].call_count()); - EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; - EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) - << "adaptation info + elapsed time"; - EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_warmup, sample_writer[0].call_count("vector_double")) - << "warmup draws"; - - EXPECT_EQ(num_warmup + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) - << "header line"; - EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_warmup, diagnostic_writer[0].call_count("vector_double")) - << "warmup draws"; -} - -TEST_F(ServicesUtil, num_samples) { - num_samples = 1000; - stan::services::util::run_adaptive_sampler( - sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ(num_samples * num_chains, interrupt.call_count()); - - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; - EXPECT_EQ(logger.call_count(), logger.call_count_info()) - << "No other calls to logger"; - - EXPECT_EQ(num_samples + 8, sample_writer[0].call_count()); - EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; - EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) - << "adaptation info + elapsed time"; - EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) - << "num_samples draws"; - - EXPECT_EQ(num_samples + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) - << "header line"; - EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) - << "num_samples draws"; -} - -TEST_F(ServicesUtil, num_warmup_save_num_samples_num_thin) { - num_warmup = 500; - save_warmup = true; - num_samples = 500; - num_thin = 10; - stan::services::util::run_adaptive_sampler( - sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); - - EXPECT_EQ((3 + 2) * num_chains, logger.call_count()) << "Writes the elapsed time"; - EXPECT_EQ(logger.call_count(), logger.call_count_info()) - << "No other calls to logger"; - - EXPECT_EQ((num_warmup + num_samples) / num_thin + 8, - sample_writer[0].call_count()); - EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; - EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ((num_warmup + num_samples) / num_thin, - sample_writer[0].call_count("vector_double")) - << "thinned warmup and draws"; - - EXPECT_EQ((num_warmup + num_samples) / num_thin + 6, - diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) - << "header line"; - EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ((num_warmup + num_samples) / num_thin, - diagnostic_writer[0].call_count("vector_double")) - << "thinned warmup and draws"; -} - -TEST_F(ServicesUtil, num_warmup_num_samples_refresh) { - num_warmup = 500; - num_samples = 500; - refresh = 10; - stan::services::util::run_adaptive_sampler( - sampler, model, cont_vector, num_warmup, num_samples, num_thin, refresh, - save_warmup, rng, interrupt, logger, sample_writer, diagnostic_writer, num_chains); - EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); - - EXPECT_EQ((num_warmup * num_chains + num_samples * num_chains) / refresh + (2 + 3 + 2) * num_chains, - logger.call_count()) - << "Writes 1 to start warmup, 1 to start post-warmup, and " - << "(num_warmup + num_samples) / refresh, then the elapsed time"; - EXPECT_EQ(logger.call_count(), logger.call_count_info()) - << "No other calls to logger"; - - EXPECT_EQ(num_samples + 8, sample_writer[0].call_count()); - EXPECT_EQ(1, sample_writer[0].call_count("vector_string")) << "header line"; - EXPECT_EQ(2 + 3, sample_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, sample_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_samples, sample_writer[0].call_count("vector_double")) - << "draws"; - - EXPECT_EQ(num_samples + 6, diagnostic_writer[0].call_count()); - EXPECT_EQ(1, diagnostic_writer[0].call_count("vector_string")) - << "header line"; - EXPECT_EQ(3, diagnostic_writer[0].call_count("string")) << "elapsed time"; - EXPECT_EQ(2, diagnostic_writer[0].call_count("empty")) << "blank lines"; - EXPECT_EQ(num_samples, diagnostic_writer[0].call_count("vector_double")) - << "draws"; -} From a2daea04283244a19824b2abded8950d3a8af514 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 25 Mar 2021 22:40:48 +0000 Subject: [PATCH 18/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 141 +++++++++--------- .../services/util/run_adaptive_sampler.hpp | 21 ++- 2 files changed, 83 insertions(+), 79 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index b2681b3ea75..af5ee5c68b0 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -19,25 +19,25 @@ namespace stan { namespace services { namespace sample { - namespace internal { - /** - * Specializtion to get a const reference to the underlying value in a - * shared_ptr. - */ - template - inline const auto& get_context(const std::shared_ptr& x) { - return *x; - } +namespace internal { +/** + * Specializtion to get a const reference to the underlying value in a + * shared_ptr. + */ +template +inline const auto& get_context(const std::shared_ptr& x) { + return *x; +} - /** - * Specialization to return back the input context - */ - template - inline auto get_context(Context&& x) { - return std::forward(x); - } +/** + * Specialization to return back the input context + */ +template +inline auto get_context(Context&& x) { + return std::forward(x); +} - } +} // namespace internal /** * Runs HMC with NUTS with adaptation using diagonal Euclidean metric @@ -174,25 +174,27 @@ int hmc_nuts_diag_e_adapt( interrupt, logger, init_writer, sample_writer, diagnostic_writer); } - -template +template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, - const std::vector& init_inv_metric, unsigned int random_seed, - unsigned int chain, double init_radius, int num_warmup, int num_samples, - int num_thin, bool save_warmup, int refresh, double stepsize, - double stepsize_jitter, int max_depth, double delta, double gamma, - double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, - unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& init_writer, - std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { + const std::vector& init_inv_metric, + unsigned int random_seed, unsigned int chain, double init_radius, + int num_warmup, int num_samples, int num_thin, bool save_warmup, + int refresh, double stepsize, double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, double t0, + unsigned int init_buffer, unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, callbacks::logger& logger, + callbacks::writer& init_writer, std::vector& sample_writer, + std::vector& diagnostic_writer, size_t n_chain) { using internal::get_context; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, get_context(init[0]), init_inv_metric[0], random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); + model, get_context(init[0]), init_inv_metric[0], random_seed, chain, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer, + sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; std::vector rngs; @@ -204,8 +206,9 @@ int hmc_nuts_diag_e_adapt( try { for (int i = 0; i < n_chain; ++i) { rngs.emplace_back(util::create_rng(random_seed, chain + i)); - cont_vectors.emplace_back(util::initialize( - model, get_context(init[i]), rngs[i], init_radius, true, logger, init_writer)); + cont_vectors.emplace_back(util::initialize(model, get_context(init[i]), + rngs[i], init_radius, true, + logger, init_writer)); samplers.emplace_back(model, rngs[i]); Eigen::VectorXd inv_metric = util::read_diag_inv_metric( init_inv_metric[i], model.num_params_r(), logger); @@ -229,16 +232,17 @@ int hmc_nuts_diag_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, - &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, + [num_warmup, num_samples, num_thin, refresh, save_warmup, &samplers, + &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { - for (size_t i = r.begin(); i != r.end(); ++i) { - util::run_adaptive_sampler( - samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, - save_warmup, rngs[i], interrupt, logger, sample_writer[i], diagnostic_writer[i], i + 1); - } - }, - tbb::simple_partitioner()); + for (size_t i = r.begin(); i != r.end(); ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, num_samples, + num_thin, refresh, save_warmup, rngs[i], interrupt, logger, + sample_writer[i], diagnostic_writer[i], i + 1); + } + }, + tbb::simple_partitioner()); return error_codes::OK; } @@ -247,31 +251,34 @@ int hmc_nuts_diag_e_adapt( template int hmc_nuts_diag_e_adapt( - Model& model, const std::vector& init, unsigned int random_seed, - unsigned int chain, double init_radius, int num_warmup, int num_samples, - int num_thin, bool save_warmup, int refresh, double stepsize, - double stepsize_jitter, int max_depth, double delta, double gamma, - double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, - unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& init_writer, - std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - using internal::get_context; - if (n_chain == 0) { - return hmc_nuts_diag_e_adapt( - model, get_context(init[0]), random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer[0], diagnostic_writer[0]); - } else { - stan::io::dump dmp - = util::create_unit_e_diag_inv_metric(model.num_params_r()); - std::vector unit_e_metrics(n_chain, dmp); - return hmc_nuts_diag_e_adapt( - model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); - } + Model& model, const std::vector& init, + unsigned int random_seed, unsigned int chain, double init_radius, + int num_warmup, int num_samples, int num_thin, bool save_warmup, + int refresh, double stepsize, double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, double t0, + unsigned int init_buffer, unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, callbacks::logger& logger, + callbacks::writer& init_writer, std::vector& sample_writer, + std::vector& diagnostic_writer, size_t n_chain) { + using internal::get_context; + if (n_chain == 0) { + return hmc_nuts_diag_e_adapt( + model, get_context(init[0]), random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer, sample_writer[0], + diagnostic_writer[0]); + } else { + stan::io::dump dmp + = util::create_unit_e_diag_inv_metric(model.num_params_r()); + std::vector unit_e_metrics(n_chain, dmp); + return hmc_nuts_diag_e_adapt( + model, init, unit_e_metrics, random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer, sample_writer, + diagnostic_writer, n_chain); + } } } // namespace sample diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 9b445eae02e..a9b9679772b 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -36,14 +36,12 @@ namespace util { * @param[in,out] diagnostic_writer writer for diagnostic information */ template -void run_adaptive_sampler(Sampler& sampler, Model& model, - std::vector& cont_vector, int num_warmup, - int num_samples, int num_thin, int refresh, - bool save_warmup, RNG& rng, - callbacks::interrupt& interrupt, - callbacks::logger& logger, - callbacks::writer& sample_writer, - callbacks::writer& diagnostic_writer, size_t chain_id = 0) { +void run_adaptive_sampler( + Sampler& sampler, Model& model, std::vector& cont_vector, + int num_warmup, int num_samples, int num_thin, int refresh, + bool save_warmup, RNG& rng, callbacks::interrupt& interrupt, + callbacks::logger& logger, callbacks::writer& sample_writer, + callbacks::writer& diagnostic_writer, size_t chain_id = 0) { Eigen::Map cont_params(cont_vector.data(), cont_vector.size()); @@ -78,9 +76,9 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, sampler.write_sampler_state(sample_writer); auto start_sample = std::chrono::steady_clock::now(); - util::generate_transitions(sampler, num_samples, num_warmup, - num_warmup + num_samples, num_thin, refresh, true, - false, writer, s, model, rng, interrupt, logger, chain_id); + util::generate_transitions( + sampler, num_samples, num_warmup, num_warmup + num_samples, num_thin, + refresh, true, false, writer, s, model, rng, interrupt, logger, chain_id); auto end_sample = std::chrono::steady_clock::now(); double sample_delta_t = std::chrono::duration_cast( end_sample - start_sample) @@ -89,7 +87,6 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, writer.write_timing(warm_delta_t, sample_delta_t); } - } // namespace util } // namespace services } // namespace stan From 427769ca36622903162e5472be992a3b4a0c6ae6 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 25 Mar 2021 18:42:58 -0400 Subject: [PATCH 19/47] update get_context to return back the input --- lib/stan_math | 2 +- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/stan_math b/lib/stan_math index a426eea0ec9..a2ff6df803f 160000 --- a/lib/stan_math +++ b/lib/stan_math @@ -1 +1 @@ -Subproject commit a426eea0ec9d9a7547061bc776a08e509d3406f3 +Subproject commit a2ff6df803f9a2c24cf43e1fc6eb449e6152b839 diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index af5ee5c68b0..f57ae885df4 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -33,7 +33,7 @@ inline const auto& get_context(const std::shared_ptr& x) { * Specialization to return back the input context */ template -inline auto get_context(Context&& x) { +inline decltype(auto) get_context(Context&& x) { return std::forward(x); } From df1542e1e5d0a44e52ab6b9bd993ed843bbe0708 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 30 Mar 2021 10:48:04 -0400 Subject: [PATCH 20/47] update with docs --- src/stan/callbacks/file_stream_writer.hpp | 25 ++-- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 141 ++++++++++++++---- .../hmc_nuts_diag_e_adapt_parallel_test.cpp | 14 +- 3 files changed, 138 insertions(+), 42 deletions(-) diff --git a/src/stan/callbacks/file_stream_writer.hpp b/src/stan/callbacks/file_stream_writer.hpp index e182321f831..d97fa530b2e 100644 --- a/src/stan/callbacks/file_stream_writer.hpp +++ b/src/stan/callbacks/file_stream_writer.hpp @@ -66,7 +66,11 @@ class file_stream_writer final : public writer { /** * Writes the comment_prefix to the stream followed by a newline. */ - void operator()() { *output_ << comment_prefix_ << std::endl; } + void operator()() { + std::stringstream streamer; + streamer << comment_prefix_ << std::endl; + *output_ << streamer; + } /** * Writes the comment_prefix then the message followed by a newline. @@ -74,7 +78,9 @@ class file_stream_writer final : public writer { * @param[in] message A string */ void operator()(const std::string& message) { - *output_ << comment_prefix_ << message << std::endl; + std::stringstream streamer; + streamer << comment_prefix_ << message << std::endl; + *output_ << streamer; } private: @@ -100,14 +106,15 @@ class file_stream_writer final : public writer { void write_vector(const std::vector& v) { if (v.empty()) return; - - typename std::vector::const_iterator last = v.end(); + using const_iter = typename std::vector::const_iterator; + const_iter last = v.end(); --last; - - for (typename std::vector::const_iterator it = v.begin(); it != last; - ++it) - *output_ << *it << ","; - *output_ << v.back() << std::endl; + std::stringstream streamer; + for (const_iter it = v.begin(); it != last; ++it) { + streamer << *it << ","; + } + streamer << v.back() << std::endl; + *output_ << streamer; } }; diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index f57ae885df4..dd08c962473 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -24,17 +24,26 @@ namespace internal { * Specializtion to get a const reference to the underlying value in a * shared_ptr. */ -template -inline const auto& get_context(const std::shared_ptr& x) { +template +inline const auto& get_underlying(const std::shared_ptr& x) { return *x; } /** - * Specialization to return back the input context + * Specializtion to get a const reference to the underlying value in a + * unique_ptr. + */ +template +inline const auto& get_underlying(const std::unique_ptr& x) { + return *x; +} + +/** + * Specialization to return back the input */ -template -inline decltype(auto) get_context(Context&& x) { - return std::forward(x); +template +inline const auto& get_underlying(T&& x) { + return std::forward(x); } } // namespace internal @@ -44,6 +53,11 @@ inline decltype(auto) get_context(Context&& x) { * with a pre-specified Euclidean metric. * * @tparam Model Model class + * @tparam InitContext A type derived from `stan::io::var_context` + * @tparam InitMetricContext A type derived from `stan::io::var_context` + * @tparam SamplerWriter A type derived from `stan::callbacks::writer` + * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` + * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) * @param[in] init var context for initialization * @param[in] init_inv_metric var context exposing an initial diagonal @@ -74,7 +88,7 @@ inline decltype(auto) get_context(Context&& x) { * @return error_codes::OK if successful */ template + typename InitWriter, typename SampleWriter, typename DiagnosticWriter> int hmc_nuts_diag_e_adapt( Model& model, const InitContext& init, const InitMetricContext& init_inv_metric, unsigned int random_seed, @@ -83,13 +97,13 @@ int hmc_nuts_diag_e_adapt( double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& init_writer, + callbacks::logger& logger, InitWriter& init_writer, SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { - using internal::get_context; + using internal::get_underlying; boost::ecuyer1988 rng = util::create_rng(random_seed, chain); std::vector cont_vector = util::initialize( - model, get_context(init), rng, init_radius, true, logger, init_writer); + model, get_underlying(init), rng, init_radius, true, logger, init_writer); Eigen::VectorXd inv_metric; try { @@ -155,7 +169,7 @@ int hmc_nuts_diag_e_adapt( * @return error_codes::OK if successful */ template + typename DiagnosticWriter, typename InitWriter> int hmc_nuts_diag_e_adapt( Model& model, const InitContext& init, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, @@ -163,19 +177,58 @@ int hmc_nuts_diag_e_adapt( double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& init_writer, + callbacks::logger& logger, InitWriter& init_writer, SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { - stan::io::dump dmp + stan::io::dump unit_e_metric = util::create_unit_e_diag_inv_metric(model.num_params_r()); return hmc_nuts_diag_e_adapt( - model, init, dmp, random_seed, chain, init_radius, num_warmup, + model, init, unit_e_metric, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, diagnostic_writer); } +/** + * Runs multiple chains of HMC with NUTS with adaptation using diagonal Euclidean metric with a pre-specified Euclidean metric. + * + * @tparam Model Model class + * @tparam InitContext A type derived from `stan::io::var_context` + * @tparam InitMetricContext A type derived from `stan::io::var_context` + * @tparam SamplerWriter A type derived from `stan::callbacks::writer` + * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` + * @tparam InitWriter A type derived from `stan::callbacks::writer` + * @param[in] model Input model to test (with data already instantiated) + * @param[in] init An std vector of init var contexts for initialization of each chain. + * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal + inverse Euclidean metric for each chain (must be positive definite) + * @param[in] random_seed random seed for the random number generator + * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_radius radius to initialize + * @param[in] num_warmup Number of warmup samples + * @param[in] num_samples Number of samples + * @param[in] num_thin Number to thin the samples + * @param[in] save_warmup Indicates whether to save the warmup iterations + * @param[in] refresh Controls the output + * @param[in] stepsize initial stepsize for discrete evolution + * @param[in] stepsize_jitter uniform random jitter of stepsize + * @param[in] max_depth Maximum tree depth + * @param[in] delta adaptation target acceptance statistic + * @param[in] gamma adaptation regularization scale + * @param[in] kappa adaptation relaxation exponent + * @param[in] t0 adaptation iteration offset + * @param[in] init_buffer width of initial fast adaptation interval + * @param[in] term_buffer width of final fast adaptation interval + * @param[in] window initial width of slow adaptation interval + * @param[in,out] interrupt Callback for interrupts + * @param[in,out] logger Logger for messages + * @param[in,out] init_writer std vector of Writer callbacks for unconstrained inits of each chain. + * @param[in,out] sample_writer std vector of Writers for draws of each chain. + * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. + * @param[in] n_chain The number of chains to run in parallel. `init`, `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. + * @return error_codes::OK if successful + */ template + typename InitWriter, typename SampleWriter, typename DiagnosticWriter> int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, const std::vector& init_inv_metric, @@ -185,15 +238,15 @@ int hmc_nuts_diag_e_adapt( double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, - callbacks::writer& init_writer, std::vector& sample_writer, + std::vector& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - using internal::get_context; + using internal::get_underlying; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, get_context(init[0]), init_inv_metric[0], random_seed, chain, + model, get_underlying(init[0]), init_inv_metric[0], random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, - init_buffer, term_buffer, window, interrupt, logger, init_writer, + init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; @@ -206,9 +259,9 @@ int hmc_nuts_diag_e_adapt( try { for (int i = 0; i < n_chain; ++i) { rngs.emplace_back(util::create_rng(random_seed, chain + i)); - cont_vectors.emplace_back(util::initialize(model, get_context(init[i]), + cont_vectors.emplace_back(util::initialize(model, get_underlying(init[i]), rngs[i], init_radius, true, - logger, init_writer)); + logger, init_writer[i])); samplers.emplace_back(model, rngs[i]); Eigen::VectorXd inv_metric = util::read_diag_inv_metric( init_inv_metric[i], model.num_params_r(), logger); @@ -248,7 +301,39 @@ int hmc_nuts_diag_e_adapt( } } -template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, @@ -258,20 +343,20 @@ int hmc_nuts_diag_e_adapt( double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, - callbacks::writer& init_writer, std::vector& sample_writer, + std::vector& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - using internal::get_context; + using internal::get_underlying; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, get_context(init[0]), random_seed, chain, init_radius, + model, get_underlying(init[0]), random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer, sample_writer[0], + term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { - stan::io::dump dmp + stan::io::dump unit_e_metric = util::create_unit_e_diag_inv_metric(model.num_params_r()); - std::vector unit_e_metrics(n_chain, dmp); + std::vector unit_e_metrics(n_chain, unit_e_metric); return hmc_nuts_diag_e_adapt( model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp index c6d30ef5fbf..9c6e253b108 100644 --- a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp @@ -12,6 +12,7 @@ class ServicesSampleHmcNutsDiagEAdaptPar : public testing::Test { public: ServicesSampleHmcNutsDiagEAdaptPar() : model(data_context, 0, &model_log) { for (int i = 0; i < num_chains; ++i) { + init.push_back(stan::test::unit::instrumented_writer{}); parameter.push_back(stan::test::unit::instrumented_writer{}); diagnostic.push_back(stan::test::unit::instrumented_writer{}); context.push_back(std::make_shared()); @@ -20,8 +21,9 @@ class ServicesSampleHmcNutsDiagEAdaptPar : public testing::Test { stan::io::empty_var_context data_context; std::stringstream model_log; stan::test::unit::instrumented_logger logger; - stan::test::unit::instrumented_writer init; - std::vector parameter, diagnostic; + std::vector init; + std::vector parameter; + std::vector diagnostic; std::vector> context; stan_model model; }; @@ -158,10 +160,12 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, output_regression) { delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init, parameter, diagnostic, num_chains); - std::vector init_values; - init_values = init.string_values(); + for (auto&& init_it : init) { + std::vector init_values; + init_values = init_it.string_values(); - EXPECT_EQ(0, init_values.size()); + EXPECT_EQ(0, init_values.size()); + } EXPECT_EQ(num_chains, logger.find_info("Elapsed Time:")); EXPECT_EQ(num_chains, logger.find_info("seconds (Warm-up)")); From ce2b7a1488f5c5fe89f1e5890a9c21f4eed3af0a Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 30 Mar 2021 16:27:30 -0400 Subject: [PATCH 21/47] update file streamer and adapt --- src/stan/callbacks/file_stream_writer.hpp | 6 +++--- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/stan/callbacks/file_stream_writer.hpp b/src/stan/callbacks/file_stream_writer.hpp index d97fa530b2e..84b9f060a54 100644 --- a/src/stan/callbacks/file_stream_writer.hpp +++ b/src/stan/callbacks/file_stream_writer.hpp @@ -69,7 +69,7 @@ class file_stream_writer final : public writer { void operator()() { std::stringstream streamer; streamer << comment_prefix_ << std::endl; - *output_ << streamer; + *output_ << streamer.str(); } /** @@ -80,7 +80,7 @@ class file_stream_writer final : public writer { void operator()(const std::string& message) { std::stringstream streamer; streamer << comment_prefix_ << message << std::endl; - *output_ << streamer; + *output_ << streamer.str(); } private: @@ -114,7 +114,7 @@ class file_stream_writer final : public writer { streamer << *it << ","; } streamer << v.back() << std::endl; - *output_ << streamer; + *output_ << streamer.str(); } }; diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index dd08c962473..3333ce41e8a 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -25,7 +25,7 @@ namespace internal { * shared_ptr. */ template -inline const auto& get_underlying(const std::shared_ptr& x) { +inline auto&& get_underlying(const std::shared_ptr& x) { return *x; } @@ -34,7 +34,7 @@ inline const auto& get_underlying(const std::shared_ptr& x) { * unique_ptr. */ template -inline const auto& get_underlying(const std::unique_ptr& x) { +inline auto&& get_underlying(const std::unique_ptr& x) { return *x; } @@ -42,7 +42,7 @@ inline const auto& get_underlying(const std::unique_ptr& x) { * Specialization to return back the input */ template -inline const auto& get_underlying(T&& x) { +inline auto&& get_underlying(T&& x) { return std::forward(x); } @@ -243,7 +243,7 @@ int hmc_nuts_diag_e_adapt( using internal::get_underlying; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, get_underlying(init[0]), init_inv_metric[0], random_seed, chain, + model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], @@ -264,7 +264,7 @@ int hmc_nuts_diag_e_adapt( logger, init_writer[i])); samplers.emplace_back(model, rngs[i]); Eigen::VectorXd inv_metric = util::read_diag_inv_metric( - init_inv_metric[i], model.num_params_r(), logger); + get_underlying(init_inv_metric[i]), model.num_params_r(), logger); util::validate_diag_inv_metric(inv_metric, logger); samplers[i].set_metric(inv_metric); From e2dfbafabe325075555ee021075250c8963fa78e Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 30 Mar 2021 16:47:43 -0400 Subject: [PATCH 22/47] update stan math --- lib/stan_math | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/stan_math b/lib/stan_math index a2ff6df803f..f390d823261 160000 --- a/lib/stan_math +++ b/lib/stan_math @@ -1 +1 @@ -Subproject commit a2ff6df803f9a2c24cf43e1fc6eb449e6152b839 +Subproject commit f390d823261266c2a0999eeaedcd5ac216f857b3 From fce973449b387bcf80fb8c137cadd7e5ef89cabf Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 30 Mar 2021 21:53:56 +0000 Subject: [PATCH 23/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/callbacks/file_stream_writer.hpp | 2 +- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 66 +++++++++++-------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/stan/callbacks/file_stream_writer.hpp b/src/stan/callbacks/file_stream_writer.hpp index 84b9f060a54..055f6436778 100644 --- a/src/stan/callbacks/file_stream_writer.hpp +++ b/src/stan/callbacks/file_stream_writer.hpp @@ -111,7 +111,7 @@ class file_stream_writer final : public writer { --last; std::stringstream streamer; for (const_iter it = v.begin(); it != last; ++it) { - streamer << *it << ","; + streamer << *it << ","; } streamer << v.back() << std::endl; *output_ << streamer.str(); diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 3333ce41e8a..d739e863f70 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -189,7 +189,8 @@ int hmc_nuts_diag_e_adapt( } /** - * Runs multiple chains of HMC with NUTS with adaptation using diagonal Euclidean metric with a pre-specified Euclidean metric. + * Runs multiple chains of HMC with NUTS with adaptation using diagonal + Euclidean metric with a pre-specified Euclidean metric. * * @tparam Model Model class * @tparam InitContext A type derived from `stan::io::var_context` @@ -198,9 +199,10 @@ int hmc_nuts_diag_e_adapt( * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) - * @param[in] init An std vector of init var contexts for initialization of each chain. - * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal - inverse Euclidean metric for each chain (must be positive definite) + * @param[in] init An std vector of init var contexts for initialization of each + chain. + * @param[in] init_inv_metric An std vector of var contexts exposing an initial + diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator * @param[in] chain chain id to advance the pseudo random number generator * @param[in] init_radius radius to initialize @@ -221,10 +223,14 @@ int hmc_nuts_diag_e_adapt( * @param[in] window initial width of slow adaptation interval * @param[in,out] interrupt Callback for interrupts * @param[in,out] logger Logger for messages - * @param[in,out] init_writer std vector of Writer callbacks for unconstrained inits of each chain. + * @param[in,out] init_writer std vector of Writer callbacks for unconstrained + inits of each chain. * @param[in,out] sample_writer std vector of Writers for draws of each chain. - * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. - * @param[in] n_chain The number of chains to run in parallel. `init`, `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. + * @param[in,out] diagnostic_writer std vector of Writers for diagnostic + information of each chain. + * @param[in] n_chain The number of chains to run in parallel. `init`, + `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must + be the same length as this value. * @return error_codes::OK if successful */ template & init_writer, std::vector& sample_writer, + std::vector& init_writer, + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { using internal::get_underlying; if (n_chain == 0) { return hmc_nuts_diag_e_adapt( - model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), random_seed, chain, - init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, - stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, - init_buffer, term_buffer, window, interrupt, logger, init_writer[0], - sample_writer[0], diagnostic_writer[0]); + model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), + random_seed, chain, init_radius, num_warmup, num_samples, num_thin, + save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, + gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, + init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; std::vector rngs; @@ -259,9 +266,9 @@ int hmc_nuts_diag_e_adapt( try { for (int i = 0; i < n_chain; ++i) { rngs.emplace_back(util::create_rng(random_seed, chain + i)); - cont_vectors.emplace_back(util::initialize(model, get_underlying(init[i]), - rngs[i], init_radius, true, - logger, init_writer[i])); + cont_vectors.emplace_back( + util::initialize(model, get_underlying(init[i]), rngs[i], + init_radius, true, logger, init_writer[i])); samplers.emplace_back(model, rngs[i]); Eigen::VectorXd inv_metric = util::read_diag_inv_metric( get_underlying(init_inv_metric[i]), model.num_params_r(), logger); @@ -302,11 +309,13 @@ int hmc_nuts_diag_e_adapt( } /** - * Runs multiple chains of HMC with NUTS with adaptation using diagonal Euclidean metric. + * Runs multiple chains of HMC with NUTS with adaptation using diagonal + * Euclidean metric. * * @tparam Model Model class * @param[in] model Input model to test (with data already instantiated) - * @param[in] init An std vector of init var contexts for initialization of each chain. + * @param[in] init An std vector of init var contexts for initialization of each + * chain. * @param[in] random_seed random seed for the random number generator * @param[in] chain chain id to advance the pseudo random number generator * @param[in] init_radius radius to initialize @@ -327,14 +336,18 @@ int hmc_nuts_diag_e_adapt( * @param[in] window initial width of slow adaptation interval * @param[in,out] interrupt Callback for interrupts * @param[in,out] logger Logger for messages - * @param[in,out] init_writer std vector of Writer callbacks for unconstrained inits of each chain. + * @param[in,out] init_writer std vector of Writer callbacks for unconstrained + * inits of each chain. * @param[in,out] sample_writer std vector of Writers for draws of each chain. - * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. - * @param[in] n_chain The number of chains to run in parallel. `init`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. + * @param[in,out] diagnostic_writer std vector of Writers for diagnostic + * information of each chain. + * @param[in] n_chain The number of chains to run in parallel. `init`, + * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same + * length as this value. * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, unsigned int random_seed, unsigned int chain, double init_radius, @@ -343,7 +356,8 @@ int hmc_nuts_diag_e_adapt( double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, - std::vector& init_writer, std::vector& sample_writer, + std::vector& init_writer, + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { using internal::get_underlying; if (n_chain == 0) { @@ -351,8 +365,8 @@ int hmc_nuts_diag_e_adapt( model, get_underlying(init[0]), random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], - diagnostic_writer[0]); + term_buffer, window, interrupt, logger, init_writer[0], + sample_writer[0], diagnostic_writer[0]); } else { stan::io::dump unit_e_metric = util::create_unit_e_diag_inv_metric(model.num_params_r()); From 059a1766a347cc0ce19601ecb636277b24d36dc9 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 31 Mar 2021 13:11:41 -0400 Subject: [PATCH 24/47] adds dense_e_adapt for parallel chains --- .../sample/hmc_nuts_dense_e_adapt.hpp | 149 ++++++++++++++- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 52 ++---- .../services/util/generate_transitions.hpp | 4 +- src/stan/services/util/get_underlying.hpp | 38 ++++ .../services/util/run_adaptive_sampler.hpp | 6 +- .../hmc_nuts_dense_e_adapt_parallel_test.cpp | 175 ++++++++++++++++++ 6 files changed, 379 insertions(+), 45 deletions(-) create mode 100644 src/stan/services/util/get_underlying.hpp create mode 100644 src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index cb644a346c6..2975e3c1af0 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace stan { @@ -66,7 +67,6 @@ int hmc_nuts_dense_e_adapt( callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer) { boost::ecuyer1988 rng = util::create_rng(random_seed, chain); - std::vector disc_vector; std::vector cont_vector = util::initialize( model, init, rng, init_radius, true, logger, init_writer); @@ -156,6 +156,153 @@ int hmc_nuts_dense_e_adapt( interrupt, logger, init_writer, sample_writer, diagnostic_writer); } +/** + * Runs multiple chains of HMC with NUTS with adaptation using diagonal Euclidean metric with a pre-specified Euclidean metric. + * + * @tparam Model Model class + * @tparam InitContext A type derived from `stan::io::var_context` + * @tparam InitMetricContext A type derived from `stan::io::var_context` + * @tparam SamplerWriter A type derived from `stan::callbacks::writer` + * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` + * @tparam InitWriter A type derived from `stan::callbacks::writer` + * @param[in] model Input model to test (with data already instantiated) + * @param[in] init An std vector of init var contexts for initialization of each chain. + * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal + inverse Euclidean metric for each chain (must be positive definite) + * @param[in] random_seed random seed for the random number generator + * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_radius radius to initialize + * @param[in] num_warmup Number of warmup samples + * @param[in] num_samples Number of samples + * @param[in] num_thin Number to thin the samples + * @param[in] save_warmup Indicates whether to save the warmup iterations + * @param[in] refresh Controls the output + * @param[in] stepsize initial stepsize for discrete evolution + * @param[in] stepsize_jitter uniform random jitter of stepsize + * @param[in] max_depth Maximum tree depth + * @param[in] delta adaptation target acceptance statistic + * @param[in] gamma adaptation regularization scale + * @param[in] kappa adaptation relaxation exponent + * @param[in] t0 adaptation iteration offset + * @param[in] init_buffer width of initial fast adaptation interval + * @param[in] term_buffer width of final fast adaptation interval + * @param[in] window initial width of slow adaptation interval + * @param[in,out] interrupt Callback for interrupts + * @param[in,out] logger Logger for messages + * @param[in,out] init_writer std vector of Writer callbacks for unconstrained inits of each chain. + * @param[in,out] sample_writer std vector of Writers for draws of each chain. + * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. + * @param[in] n_chain The number of chains to run in parallel. `init`, `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. + * @return error_codes::OK if successful + */ +template +int hmc_nuts_dense_e_adapt( + Model& model, const std::vector& init, + const std::vector& init_inv_metric, + unsigned int random_seed, unsigned int chain, double init_radius, + int num_warmup, int num_samples, int num_thin, bool save_warmup, + int refresh, double stepsize, double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, double t0, + unsigned int init_buffer, unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, callbacks::logger& logger, + std::vector& init_writer, std::vector& sample_writer, + std::vector& diagnostic_writer, size_t n_chain) { + using util::get_underlying; + if (n_chain == 1) { + return hmc_nuts_dense_e_adapt( + model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), random_seed, chain, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer[0], + sample_writer[0], diagnostic_writer[0]); + } else { + using sample_t = stan::mcmc::adapt_dense_e_nuts; + std::vector rngs; + rngs.reserve(n_chain); + std::vector> cont_vectors; + cont_vectors.reserve(n_chain); + std::vector samplers; + samplers.reserve(n_chain); + try { + for (int i = 0; i < n_chain; ++i) { + rngs.emplace_back(util::create_rng(random_seed, chain + i)); + cont_vectors.emplace_back(util::initialize(model, get_underlying(init[i]), + rngs[i], init_radius, true, + logger, init_writer[i])); + Eigen::MatrixXd inv_metric = util::read_dense_inv_metric( + get_underlying(init_inv_metric[i]), model.num_params_r(), logger); + util::validate_dense_inv_metric(inv_metric, logger); + + samplers.emplace_back(model, rngs[i]); + samplers[i].set_metric(inv_metric); + samplers[i].set_nominal_stepsize(stepsize); + samplers[i].set_stepsize_jitter(stepsize_jitter); + samplers[i].set_max_depth(max_depth); + + samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); + samplers[i].get_stepsize_adaptation().set_delta(delta); + samplers[i].get_stepsize_adaptation().set_gamma(gamma); + samplers[i].get_stepsize_adaptation().set_kappa(kappa); + samplers[i].get_stepsize_adaptation().set_t0(t0); + samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, + window, logger); + } + } catch (const std::domain_error& e) { + return error_codes::CONFIG; + } + tbb::parallel_for( + tbb::blocked_range(0, n_chain, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, &samplers, + &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, + &diagnostic_writer](const tbb::blocked_range& r) { + for (size_t i = r.begin(); i != r.end(); ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, num_samples, + num_thin, refresh, save_warmup, rngs[i], interrupt, logger, + sample_writer[i], diagnostic_writer[i], i + 1, n_chain); + } + }, + tbb::simple_partitioner()); + + return error_codes::OK; + } +} + +template +int hmc_nuts_dense_e_adapt( + Model& model, const std::vector& init, unsigned int random_seed, + unsigned int chain, double init_radius, int num_warmup, int num_samples, + int num_thin, bool save_warmup, int refresh, double stepsize, + double stepsize_jitter, int max_depth, double delta, double gamma, + double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, + unsigned int window, callbacks::interrupt& interrupt, + callbacks::logger& logger, std::vector& init_writer, + std::vector& sample_writer, + std::vector& diagnostic_writer, size_t n_chain = 1) { + using util::get_underlying; + if (n_chain == 1) { + return hmc_nuts_dense_e_adapt( + model, get_underlying(init[0]), random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], + diagnostic_writer[0]); + } else { + std::vector unit_e_metrics; + unit_e_metrics.reserve(n_chain); + for (size_t i = 0; i < n_chain; ++i) { + unit_e_metrics.emplace_back(util::create_unit_e_dense_inv_metric(model.num_params_r())); + } + return hmc_nuts_dense_e_adapt( + model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); + } +} + } // namespace sample } // namespace services } // namespace stan diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 3333ce41e8a..d7c32fdcc68 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -13,41 +13,13 @@ #include #include #include +#include #include namespace stan { namespace services { namespace sample { -namespace internal { -/** - * Specializtion to get a const reference to the underlying value in a - * shared_ptr. - */ -template -inline auto&& get_underlying(const std::shared_ptr& x) { - return *x; -} - -/** - * Specializtion to get a const reference to the underlying value in a - * unique_ptr. - */ -template -inline auto&& get_underlying(const std::unique_ptr& x) { - return *x; -} - -/** - * Specialization to return back the input - */ -template -inline auto&& get_underlying(T&& x) { - return std::forward(x); -} - -} // namespace internal - /** * Runs HMC with NUTS with adaptation using diagonal Euclidean metric * with a pre-specified Euclidean metric. @@ -99,7 +71,7 @@ int hmc_nuts_diag_e_adapt( unsigned int window, callbacks::interrupt& interrupt, callbacks::logger& logger, InitWriter& init_writer, SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { - using internal::get_underlying; + using util::get_underlying; boost::ecuyer1988 rng = util::create_rng(random_seed, chain); std::vector cont_vector = util::initialize( @@ -240,8 +212,8 @@ int hmc_nuts_diag_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - using internal::get_underlying; - if (n_chain == 0) { + using util::get_underlying; + if (n_chain == 1) { return hmc_nuts_diag_e_adapt( model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, @@ -285,14 +257,14 @@ int hmc_nuts_diag_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, &samplers, + [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1); + sample_writer[i], diagnostic_writer[i], i + 1, n_chain); } }, tbb::simple_partitioner()); @@ -345,8 +317,8 @@ int hmc_nuts_diag_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { - using internal::get_underlying; - if (n_chain == 0) { + using util::get_underlying; + if (n_chain == 1) { return hmc_nuts_diag_e_adapt( model, get_underlying(init[0]), random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, @@ -354,9 +326,11 @@ int hmc_nuts_diag_e_adapt( term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { - stan::io::dump unit_e_metric - = util::create_unit_e_diag_inv_metric(model.num_params_r()); - std::vector unit_e_metrics(n_chain, unit_e_metric); + std::vector unit_e_metrics; + unit_e_metrics.reserve(n_chain); + for (size_t i = 0; i < n_chain; ++i) { + unit_e_metrics.emplace_back(util::create_unit_e_diag_inv_metric(model.num_params_r())); + } return hmc_nuts_diag_e_adapt( model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index cbef5f1782e..6f82eaeb635 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -44,7 +44,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, util::mcmc_writer& mcmc_writer, stan::mcmc::sample& init_s, Model& model, RNG& base_rng, callbacks::interrupt& callback, - callbacks::logger& logger, size_t chain_id = 0) { + callbacks::logger& logger, size_t chain_id = 1, size_t n_chain = 1) { for (int m = 0; m < num_iterations; ++m) { callback(); @@ -52,7 +52,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, && (start + m + 1 == finish || m == 0 || (m + 1) % refresh == 0)) { int it_print_width = std::ceil(std::log10(static_cast(finish))); std::stringstream message; - if (chain_id != 0) { + if (n_chain != 1) { message << "Chain [" << chain_id << "] "; } message << "Iteration: "; diff --git a/src/stan/services/util/get_underlying.hpp b/src/stan/services/util/get_underlying.hpp new file mode 100644 index 00000000000..d3c53329b48 --- /dev/null +++ b/src/stan/services/util/get_underlying.hpp @@ -0,0 +1,38 @@ +#ifndef STAN_SERVICES_UTIL_GET_UNDERLYING_HPP +#define STAN_SERVICES_UTIL_GET_UNDERLYING_HPP + +#include +#include + +namespace stan { +namespace services { +namespace util { +/** + * Specializtion to get a const reference to the underlying value in a + * shared_ptr. + */ +template +inline auto&& get_underlying(const std::shared_ptr& x) { + return *x; +} + +/** + * Specializtion to get a const reference to the underlying value in a + * unique_ptr. + */ +template +inline auto&& get_underlying(const std::unique_ptr& x) { + return *x; +} + +/** + * Specialization to return back the input + */ +template +inline auto&& get_underlying(T&& x) { + return std::forward(x); +} + +}}} + +#endif diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index a9b9679772b..87aeb23d770 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -41,7 +41,7 @@ void run_adaptive_sampler( int num_warmup, int num_samples, int num_thin, int refresh, bool save_warmup, RNG& rng, callbacks::interrupt& interrupt, callbacks::logger& logger, callbacks::writer& sample_writer, - callbacks::writer& diagnostic_writer, size_t chain_id = 0) { + callbacks::writer& diagnostic_writer, size_t chain_id = 0, size_t n_chain = 1) { Eigen::Map cont_params(cont_vector.data(), cont_vector.size()); @@ -65,7 +65,7 @@ void run_adaptive_sampler( auto start_warm = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_warmup, 0, num_warmup + num_samples, num_thin, refresh, save_warmup, true, writer, s, - model, rng, interrupt, logger, chain_id); + model, rng, interrupt, logger, chain_id, n_chain); auto end_warm = std::chrono::steady_clock::now(); double warm_delta_t = std::chrono::duration_cast( end_warm - start_warm) @@ -78,7 +78,7 @@ void run_adaptive_sampler( auto start_sample = std::chrono::steady_clock::now(); util::generate_transitions( sampler, num_samples, num_warmup, num_warmup + num_samples, num_thin, - refresh, true, false, writer, s, model, rng, interrupt, logger, chain_id); + refresh, true, false, writer, s, model, rng, interrupt, logger, chain_id, n_chain); auto end_sample = std::chrono::steady_clock::now(); double sample_delta_t = std::chrono::duration_cast( end_sample - start_sample) diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp new file mode 100644 index 00000000000..7d6b9c45107 --- /dev/null +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include + +auto&& blah = stan::math::init_threadpool_tbb(); + +static constexpr size_t num_chains = 4; +class ServicesSampleHmcNutsDenseEAdaptPar : public testing::Test { + public: + ServicesSampleHmcNutsDenseEAdaptPar() : model(data_context, 0, &model_log) { + for (int i = 0; i < num_chains; ++i) { + init.push_back(stan::test::unit::instrumented_writer{}); + parameter.push_back(stan::test::unit::instrumented_writer{}); + diagnostic.push_back(stan::test::unit::instrumented_writer{}); + context.push_back(std::make_shared()); + } + } + stan::io::empty_var_context data_context; + std::stringstream model_log; + stan::test::unit::instrumented_logger logger; + std::vector init; + std::vector parameter; + std::vector diagnostic; + std::vector> context; + stan_model model; +}; + +TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, call_count) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 200; + int num_samples = 400; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 50; + unsigned int term_buffer = 50; + unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic, num_chains); + + EXPECT_EQ(0, return_code); + + int num_output_lines = (num_warmup + num_samples) / num_thin; + EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); + for (int i = 0; i < num_chains; ++i) { + EXPECT_EQ(1, parameter[i].call_count("vector_string")); + EXPECT_EQ(num_output_lines, parameter[i].call_count("vector_double")); + EXPECT_EQ(1, diagnostic[i].call_count("vector_string")); + EXPECT_EQ(num_output_lines, diagnostic[i].call_count("vector_double")); + } +} + +TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, parameter_checks) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 200; + int num_samples = 400; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 50; + unsigned int term_buffer = 50; + unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic, num_chains); + + for (size_t i = 0; i < num_chains; ++i) { + std::vector> parameter_names; + parameter_names = parameter[i].vector_string_values(); + std::vector> parameter_values; + parameter_values = parameter[i].vector_double_values(); + std::vector> diagnostic_names; + diagnostic_names = diagnostic[i].vector_string_values(); + std::vector> diagnostic_values; + diagnostic_values = diagnostic[i].vector_double_values(); + + // Expectations of parameter parameter names. + ASSERT_EQ(9, parameter_names[0].size()); + EXPECT_EQ("lp__", parameter_names[0][0]); + EXPECT_EQ("accept_stat__", parameter_names[0][1]); + EXPECT_EQ("stepsize__", parameter_names[0][2]); + EXPECT_EQ("treedepth__", parameter_names[0][3]); + EXPECT_EQ("n_leapfrog__", parameter_names[0][4]); + EXPECT_EQ("divergent__", parameter_names[0][5]); + EXPECT_EQ("energy__", parameter_names[0][6]); + EXPECT_EQ("x", parameter_names[0][7]); + EXPECT_EQ("y", parameter_names[0][8]); + + // Expect one name per parameter value. + EXPECT_EQ(parameter_names[0].size(), parameter_values[0].size()); + EXPECT_EQ(diagnostic_names[0].size(), diagnostic_values[0].size()); + + EXPECT_EQ((num_warmup + num_samples) / num_thin, parameter_values.size()); + + // Expect one call to set parameter names, and one set of output per + // iteration. + EXPECT_EQ("lp__", diagnostic_names[0][0]); + EXPECT_EQ("accept_stat__", diagnostic_names[0][1]); + } + EXPECT_EQ(return_code, 0); +} + +TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, output_regression) { + unsigned int random_seed = 0; + unsigned int chain = 1; + double init_radius = 0; + int num_warmup = 200; + int num_samples = 400; + int num_thin = 5; + bool save_warmup = true; + int refresh = 0; + double stepsize = 0.1; + double stepsize_jitter = 0; + int max_depth = 8; + double delta = .1; + double gamma = .1; + double kappa = .1; + double t0 = .1; + unsigned int init_buffer = 50; + unsigned int term_buffer = 50; + unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + + stan::services::sample::hmc_nuts_dense_e_adapt( + model, context, random_seed, chain, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init, parameter, diagnostic, num_chains); + + for (auto&& init_it : init) { + std::vector init_values; + init_values = init_it.string_values(); + + EXPECT_EQ(0, init_values.size()); + } + + EXPECT_EQ(num_chains, logger.find_info("Elapsed Time:")); + EXPECT_EQ(num_chains, logger.find_info("seconds (Warm-up)")); + EXPECT_EQ(num_chains, logger.find_info("seconds (Sampling)")); + EXPECT_EQ(num_chains, logger.find_info("seconds (Total)")); + EXPECT_EQ(0, logger.call_count_error()); +} From 147fba5fb93aa007ec42744a36d97cc84c291945 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 31 Mar 2021 17:35:00 +0000 Subject: [PATCH 25/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../sample/hmc_nuts_dense_e_adapt.hpp | 103 ++++++++++-------- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 8 +- .../services/util/generate_transitions.hpp | 3 +- src/stan/services/util/get_underlying.hpp | 4 +- .../services/util/run_adaptive_sampler.hpp | 22 ++-- 5 files changed, 80 insertions(+), 60 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 2975e3c1af0..57ef58565ff 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -157,7 +157,8 @@ int hmc_nuts_dense_e_adapt( } /** - * Runs multiple chains of HMC with NUTS with adaptation using diagonal Euclidean metric with a pre-specified Euclidean metric. + * Runs multiple chains of HMC with NUTS with adaptation using diagonal + Euclidean metric with a pre-specified Euclidean metric. * * @tparam Model Model class * @tparam InitContext A type derived from `stan::io::var_context` @@ -166,9 +167,10 @@ int hmc_nuts_dense_e_adapt( * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) - * @param[in] init An std vector of init var contexts for initialization of each chain. - * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal - inverse Euclidean metric for each chain (must be positive definite) + * @param[in] init An std vector of init var contexts for initialization of each + chain. + * @param[in] init_inv_metric An std vector of var contexts exposing an initial + diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator * @param[in] chain chain id to advance the pseudo random number generator * @param[in] init_radius radius to initialize @@ -189,10 +191,14 @@ int hmc_nuts_dense_e_adapt( * @param[in] window initial width of slow adaptation interval * @param[in,out] interrupt Callback for interrupts * @param[in,out] logger Logger for messages - * @param[in,out] init_writer std vector of Writer callbacks for unconstrained inits of each chain. + * @param[in,out] init_writer std vector of Writer callbacks for unconstrained + inits of each chain. * @param[in,out] sample_writer std vector of Writers for draws of each chain. - * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. - * @param[in] n_chain The number of chains to run in parallel. `init`, `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. + * @param[in,out] diagnostic_writer std vector of Writers for diagnostic + information of each chain. + * @param[in] n_chain The number of chains to run in parallel. `init`, + `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must + be the same length as this value. * @return error_codes::OK if successful */ template & init_writer, std::vector& sample_writer, + std::vector& init_writer, + std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain) { using util::get_underlying; if (n_chain == 1) { return hmc_nuts_dense_e_adapt( - model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), random_seed, chain, - init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, - stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, - init_buffer, term_buffer, window, interrupt, logger, init_writer[0], - sample_writer[0], diagnostic_writer[0]); + model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), + random_seed, chain, init_radius, num_warmup, num_samples, num_thin, + save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, + gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, + init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_dense_e_nuts; std::vector rngs; @@ -227,9 +234,9 @@ int hmc_nuts_dense_e_adapt( try { for (int i = 0; i < n_chain; ++i) { rngs.emplace_back(util::create_rng(random_seed, chain + i)); - cont_vectors.emplace_back(util::initialize(model, get_underlying(init[i]), - rngs[i], init_radius, true, - logger, init_writer[i])); + cont_vectors.emplace_back( + util::initialize(model, get_underlying(init[i]), rngs[i], + init_radius, true, logger, init_writer[i])); Eigen::MatrixXd inv_metric = util::read_dense_inv_metric( get_underlying(init_inv_metric[i]), model.num_params_r(), logger); util::validate_dense_inv_metric(inv_metric, logger); @@ -253,8 +260,9 @@ int hmc_nuts_dense_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, &samplers, - &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, + [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, + &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, + &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { util::run_adaptive_sampler( @@ -270,37 +278,40 @@ int hmc_nuts_dense_e_adapt( } template + typename SampleWriter, typename DiagnosticWriter> int hmc_nuts_dense_e_adapt( - Model& model, const std::vector& init, unsigned int random_seed, - unsigned int chain, double init_radius, int num_warmup, int num_samples, - int num_thin, bool save_warmup, int refresh, double stepsize, - double stepsize_jitter, int max_depth, double delta, double gamma, - double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, - unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, std::vector& init_writer, + Model& model, const std::vector& init, + unsigned int random_seed, unsigned int chain, double init_radius, + int num_warmup, int num_samples, int num_thin, bool save_warmup, + int refresh, double stepsize, double stepsize_jitter, int max_depth, + double delta, double gamma, double kappa, double t0, + unsigned int init_buffer, unsigned int term_buffer, unsigned int window, + callbacks::interrupt& interrupt, callbacks::logger& logger, + std::vector& init_writer, std::vector& sample_writer, std::vector& diagnostic_writer, size_t n_chain = 1) { - using util::get_underlying; - if (n_chain == 1) { - return hmc_nuts_dense_e_adapt( - model, get_underlying(init[0]), random_seed, chain, init_radius, - num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, - stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], - diagnostic_writer[0]); - } else { - std::vector unit_e_metrics; - unit_e_metrics.reserve(n_chain); - for (size_t i = 0; i < n_chain; ++i) { - unit_e_metrics.emplace_back(util::create_unit_e_dense_inv_metric(model.num_params_r())); - } - return hmc_nuts_dense_e_adapt( - model, init, unit_e_metrics, random_seed, chain, init_radius, num_warmup, - num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, - max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, - interrupt, logger, init_writer, sample_writer, diagnostic_writer, n_chain); - } + using util::get_underlying; + if (n_chain == 1) { + return hmc_nuts_dense_e_adapt( + model, get_underlying(init[0]), random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer[0], + sample_writer[0], diagnostic_writer[0]); + } else { + std::vector unit_e_metrics; + unit_e_metrics.reserve(n_chain); + for (size_t i = 0; i < n_chain; ++i) { + unit_e_metrics.emplace_back( + util::create_unit_e_dense_inv_metric(model.num_params_r())); + } + return hmc_nuts_dense_e_adapt( + model, init, unit_e_metrics, random_seed, chain, init_radius, + num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, + stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, + term_buffer, window, interrupt, logger, init_writer, sample_writer, + diagnostic_writer, n_chain); + } } } // namespace sample diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index cafc7859527..adcdc4cc7de 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -264,8 +264,9 @@ int hmc_nuts_diag_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, &samplers, - &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, + [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, + &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, + &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { util::run_adaptive_sampler( @@ -343,7 +344,8 @@ int hmc_nuts_diag_e_adapt( std::vector unit_e_metrics; unit_e_metrics.reserve(n_chain); for (size_t i = 0; i < n_chain; ++i) { - unit_e_metrics.emplace_back(util::create_unit_e_diag_inv_metric(model.num_params_r())); + unit_e_metrics.emplace_back( + util::create_unit_e_diag_inv_metric(model.num_params_r())); } return hmc_nuts_diag_e_adapt( model, init, unit_e_metrics, random_seed, chain, init_radius, diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index 6f82eaeb635..c5c04843930 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -44,7 +44,8 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, util::mcmc_writer& mcmc_writer, stan::mcmc::sample& init_s, Model& model, RNG& base_rng, callbacks::interrupt& callback, - callbacks::logger& logger, size_t chain_id = 1, size_t n_chain = 1) { + callbacks::logger& logger, size_t chain_id = 1, + size_t n_chain = 1) { for (int m = 0; m < num_iterations; ++m) { callback(); diff --git a/src/stan/services/util/get_underlying.hpp b/src/stan/services/util/get_underlying.hpp index d3c53329b48..80292d1be5f 100644 --- a/src/stan/services/util/get_underlying.hpp +++ b/src/stan/services/util/get_underlying.hpp @@ -33,6 +33,8 @@ inline auto&& get_underlying(T&& x) { return std::forward(x); } -}}} +} // namespace util +} // namespace services +} // namespace stan #endif diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 87aeb23d770..4fac05e3f5b 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -36,12 +36,15 @@ namespace util { * @param[in,out] diagnostic_writer writer for diagnostic information */ template -void run_adaptive_sampler( - Sampler& sampler, Model& model, std::vector& cont_vector, - int num_warmup, int num_samples, int num_thin, int refresh, - bool save_warmup, RNG& rng, callbacks::interrupt& interrupt, - callbacks::logger& logger, callbacks::writer& sample_writer, - callbacks::writer& diagnostic_writer, size_t chain_id = 0, size_t n_chain = 1) { +void run_adaptive_sampler(Sampler& sampler, Model& model, + std::vector& cont_vector, int num_warmup, + int num_samples, int num_thin, int refresh, + bool save_warmup, RNG& rng, + callbacks::interrupt& interrupt, + callbacks::logger& logger, + callbacks::writer& sample_writer, + callbacks::writer& diagnostic_writer, + size_t chain_id = 0, size_t n_chain = 1) { Eigen::Map cont_params(cont_vector.data(), cont_vector.size()); @@ -76,9 +79,10 @@ void run_adaptive_sampler( sampler.write_sampler_state(sample_writer); auto start_sample = std::chrono::steady_clock::now(); - util::generate_transitions( - sampler, num_samples, num_warmup, num_warmup + num_samples, num_thin, - refresh, true, false, writer, s, model, rng, interrupt, logger, chain_id, n_chain); + util::generate_transitions(sampler, num_samples, num_warmup, + num_warmup + num_samples, num_thin, refresh, true, + false, writer, s, model, rng, interrupt, logger, + chain_id, n_chain); auto end_sample = std::chrono::steady_clock::now(); double sample_delta_t = std::chrono::duration_cast( end_sample - start_sample) From 323adb97fd222e2645c8d0902c86514fec3f28d2 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 22 Apr 2021 13:55:22 -0400 Subject: [PATCH 26/47] update to reflect parallel chain design doc --- .../sample/hmc_nuts_dense_e_adapt.hpp | 86 +++++++++++++------ .../services/sample/hmc_nuts_diag_e_adapt.hpp | 50 +++++------ 2 files changed, 87 insertions(+), 49 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 57ef58565ff..97c546d7ab3 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -157,8 +157,8 @@ int hmc_nuts_dense_e_adapt( } /** - * Runs multiple chains of HMC with NUTS with adaptation using diagonal - Euclidean metric with a pre-specified Euclidean metric. + * Runs multiple chains of NUTS with adaptation using dense Euclidean metric + * with a pre-specified Euclidean metric. * * @tparam Model Model class * @tparam InitContext A type derived from `stan::io::var_context` @@ -172,7 +172,7 @@ int hmc_nuts_dense_e_adapt( * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator - * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -196,7 +196,7 @@ int hmc_nuts_dense_e_adapt( * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. - * @param[in] n_chain The number of chains to run in parallel. `init`, + * @param[in] num_chains The number of chains to run in parallel. `init`, `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. * @return error_codes::OK if successful @@ -206,7 +206,7 @@ template & init, const std::vector& init_inv_metric, - unsigned int random_seed, unsigned int chain, double init_radius, + unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, @@ -214,26 +214,26 @@ int hmc_nuts_dense_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t n_chain) { + std::vector& diagnostic_writer, size_t num_chains) { using util::get_underlying; - if (n_chain == 1) { + if (num_chains == 1) { return hmc_nuts_dense_e_adapt( model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), - random_seed, chain, init_radius, num_warmup, num_samples, num_thin, + random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_dense_e_nuts; std::vector rngs; - rngs.reserve(n_chain); + rngs.reserve(num_chains); std::vector> cont_vectors; - cont_vectors.reserve(n_chain); + cont_vectors.reserve(num_chains); std::vector samplers; - samplers.reserve(n_chain); + samplers.reserve(num_chains); try { - for (int i = 0; i < n_chain; ++i) { - rngs.emplace_back(util::create_rng(random_seed, chain + i)); + for (int i = 0; i < num_chains; ++i) { + rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); cont_vectors.emplace_back( util::initialize(model, get_underlying(init[i]), rngs[i], init_radius, true, logger, init_writer[i])); @@ -259,8 +259,8 @@ int hmc_nuts_dense_e_adapt( return error_codes::CONFIG; } tbb::parallel_for( - tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, + tbb::blocked_range(0, num_chains, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { @@ -268,7 +268,7 @@ int hmc_nuts_dense_e_adapt( util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, n_chain); + sample_writer[i], diagnostic_writer[i], i + 1, num_chains); } }, tbb::simple_partitioner()); @@ -277,11 +277,49 @@ int hmc_nuts_dense_e_adapt( } } +/** + * Runs multiple chains of NUTS with adaptation using dense Euclidean metric, + * with identity matrix as initial inv_metric. + * + * @tparam Model Model class + * @param[in] model Input model to test (with data already instantiated) + * @param[in] init An std vector of init var contexts for initialization of each + * chain. + * @param[in] random_seed random seed for the random number generator + * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` + * @param[in] init_radius radius to initialize + * @param[in] num_warmup Number of warmup samples + * @param[in] num_samples Number of samples + * @param[in] num_thin Number to thin the samples + * @param[in] save_warmup Indicates whether to save the warmup iterations + * @param[in] refresh Controls the output + * @param[in] stepsize initial stepsize for discrete evolution + * @param[in] stepsize_jitter uniform random jitter of stepsize + * @param[in] max_depth Maximum tree depth + * @param[in] delta adaptation target acceptance statistic + * @param[in] gamma adaptation regularization scale + * @param[in] kappa adaptation relaxation exponent + * @param[in] t0 adaptation iteration offset + * @param[in] init_buffer width of initial fast adaptation interval + * @param[in] term_buffer width of final fast adaptation interval + * @param[in] window initial width of slow adaptation interval + * @param[in,out] interrupt Callback for interrupts + * @param[in,out] logger Logger for messages + * @param[in,out] init_writer std vector of Writer callbacks for unconstrained + * inits of each chain. + * @param[in,out] sample_writer std vector of Writers for draws of each chain. + * @param[in,out] diagnostic_writer std vector of Writers for diagnostic + * information of each chain. + * @param[in] num_chains The number of chains to run in parallel. `init`, + * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same + * length as this value. + * @return error_codes::OK if successful + */ template int hmc_nuts_dense_e_adapt( Model& model, const std::vector& init, - unsigned int random_seed, unsigned int chain, double init_radius, + unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, @@ -289,28 +327,28 @@ int hmc_nuts_dense_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t n_chain = 1) { + std::vector& diagnostic_writer, size_t num_chains = 1) { using util::get_underlying; - if (n_chain == 1) { + if (num_chains == 1) { return hmc_nuts_dense_e_adapt( - model, get_underlying(init[0]), random_seed, chain, init_radius, + model, get_underlying(init[0]), random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { std::vector unit_e_metrics; - unit_e_metrics.reserve(n_chain); - for (size_t i = 0; i < n_chain; ++i) { + unit_e_metrics.reserve(num_chains); + for (size_t i = 0; i < num_chains; ++i) { unit_e_metrics.emplace_back( util::create_unit_e_dense_inv_metric(model.num_params_r())); } return hmc_nuts_dense_e_adapt( - model, init, unit_e_metrics, random_seed, chain, init_radius, + model, init, unit_e_metrics, random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, - diagnostic_writer, n_chain); + diagnostic_writer, num_chains); } } diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index adcdc4cc7de..ea0177e9618 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -162,7 +162,7 @@ int hmc_nuts_diag_e_adapt( /** * Runs multiple chains of HMC with NUTS with adaptation using diagonal - Euclidean metric with a pre-specified Euclidean metric. + * Euclidean metric with a pre-specified Euclidean metric. * * @tparam Model Model class * @tparam InitContext A type derived from `stan::io::var_context` @@ -176,7 +176,7 @@ int hmc_nuts_diag_e_adapt( * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator - * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -200,7 +200,7 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic information of each chain. - * @param[in] n_chain The number of chains to run in parallel. `init`, + * @param[in] num_chains The number of chains to run in parallel. `init`, `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same length as this value. * @return error_codes::OK if successful @@ -210,7 +210,7 @@ template & init, const std::vector& init_inv_metric, - unsigned int random_seed, unsigned int chain, double init_radius, + unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, @@ -218,26 +218,26 @@ int hmc_nuts_diag_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t n_chain) { + std::vector& diagnostic_writer, size_t num_chains) { using util::get_underlying; - if (n_chain == 1) { + if (num_chains == 1) { return hmc_nuts_diag_e_adapt( model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), - random_seed, chain, init_radius, num_warmup, num_samples, num_thin, + random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; std::vector rngs; - rngs.reserve(n_chain); + rngs.reserve(num_chains); std::vector> cont_vectors; - cont_vectors.reserve(n_chain); + cont_vectors.reserve(num_chains); std::vector samplers; - samplers.reserve(n_chain); + samplers.reserve(num_chains); try { - for (int i = 0; i < n_chain; ++i) { - rngs.emplace_back(util::create_rng(random_seed, chain + i)); + for (int i = 0; i < num_chains; ++i) { + rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); cont_vectors.emplace_back( util::initialize(model, get_underlying(init[i]), rngs[i], init_radius, true, logger, init_writer[i])); @@ -263,8 +263,8 @@ int hmc_nuts_diag_e_adapt( return error_codes::CONFIG; } tbb::parallel_for( - tbb::blocked_range(0, n_chain, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, n_chain, + tbb::blocked_range(0, num_chains, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { @@ -272,7 +272,7 @@ int hmc_nuts_diag_e_adapt( util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, n_chain); + sample_writer[i], diagnostic_writer[i], i + 1, num_chains); } }, tbb::simple_partitioner()); @@ -290,7 +290,7 @@ int hmc_nuts_diag_e_adapt( * @param[in] init An std vector of init var contexts for initialization of each * chain. * @param[in] random_seed random seed for the random number generator - * @param[in] chain chain id to advance the pseudo random number generator + * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -314,7 +314,7 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic * information of each chain. - * @param[in] n_chain The number of chains to run in parallel. `init`, + * @param[in] num_chains The number of chains to run in parallel. `init`, * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same * length as this value. * @return error_codes::OK if successful @@ -323,7 +323,7 @@ template int hmc_nuts_diag_e_adapt( Model& model, const std::vector& init, - unsigned int random_seed, unsigned int chain, double init_radius, + unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, @@ -331,28 +331,28 @@ int hmc_nuts_diag_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t n_chain) { + std::vector& diagnostic_writer, size_t num_chains) { using util::get_underlying; - if (n_chain == 1) { + if (num_chains == 1) { return hmc_nuts_diag_e_adapt( - model, get_underlying(init[0]), random_seed, chain, init_radius, + model, get_underlying(init[0]), random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { std::vector unit_e_metrics; - unit_e_metrics.reserve(n_chain); - for (size_t i = 0; i < n_chain; ++i) { + unit_e_metrics.reserve(num_chains); + for (size_t i = 0; i < num_chains; ++i) { unit_e_metrics.emplace_back( util::create_unit_e_diag_inv_metric(model.num_params_r())); } return hmc_nuts_diag_e_adapt( - model, init, unit_e_metrics, random_seed, chain, init_radius, + model, init, unit_e_metrics, random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, - diagnostic_writer, n_chain); + diagnostic_writer, num_chains); } } From 76214684b6f5611ffc656446928b59d882ae8eeb Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 22 Apr 2021 18:01:33 +0000 Subject: [PATCH 27/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../services/sample/hmc_nuts_dense_e_adapt.hpp | 16 ++++++++++------ .../services/sample/hmc_nuts_diag_e_adapt.hpp | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 97c546d7ab3..70f237a472c 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -172,7 +172,9 @@ int hmc_nuts_dense_e_adapt( * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator - * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` + * @param[in] init_chain_id first chain id. The pseudo random number generator + will advance by for each chain by an integer sequence from `init_chain_id` to + `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -219,10 +221,10 @@ int hmc_nuts_dense_e_adapt( if (num_chains == 1) { return hmc_nuts_dense_e_adapt( model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), - random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, - save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, - gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, - init_writer[0], sample_writer[0], diagnostic_writer[0]); + random_seed, init_chain_id, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_dense_e_nuts; std::vector rngs; @@ -286,7 +288,9 @@ int hmc_nuts_dense_e_adapt( * @param[in] init An std vector of init var contexts for initialization of each * chain. * @param[in] random_seed random seed for the random number generator - * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` + * @param[in] init_chain_id first chain id. The pseudo random number generator + * will advance by for each chain by an integer sequence from `init_chain_id` to + * `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index ea0177e9618..028759bfe58 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -176,7 +176,9 @@ int hmc_nuts_diag_e_adapt( * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator - * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` + * @param[in] init_chain_id first chain id. The pseudo random number generator + will advance by for each chain by an integer sequence from `init_chain_id` to + `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -223,10 +225,10 @@ int hmc_nuts_diag_e_adapt( if (num_chains == 1) { return hmc_nuts_diag_e_adapt( model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), - random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, - save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, - gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, - init_writer[0], sample_writer[0], diagnostic_writer[0]); + random_seed, init_chain_id, init_radius, num_warmup, num_samples, + num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, + delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, + logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; std::vector rngs; @@ -290,7 +292,9 @@ int hmc_nuts_diag_e_adapt( * @param[in] init An std vector of init var contexts for initialization of each * chain. * @param[in] random_seed random seed for the random number generator - * @param[in] init_chain_id first chain id. The pseudo random number generator will advance by for each chain by an integer sequence from `init_chain_id` to `num_chains` + * @param[in] init_chain_id first chain id. The pseudo random number generator + * will advance by for each chain by an integer sequence from `init_chain_id` to + * `num_chains` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples From 7146784ee7fc3086007d1d5e07bfb17865887686 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 12 May 2021 12:26:10 -0400 Subject: [PATCH 28/47] make changes so API matches up with design doc --- ...am_writer.hpp => unique_stream_writer.hpp} | 23 +++---- .../sample/hmc_nuts_dense_e_adapt.hpp | 35 +++++------ .../services/sample/hmc_nuts_diag_e_adapt.hpp | 60 +++++++++---------- src/stan/services/util/get_underlying.hpp | 40 ------------- ...test.cpp => unique_stream_writer_test.cpp} | 4 +- .../hmc_nuts_dense_e_adapt_parallel_test.cpp | 12 ++-- .../hmc_nuts_diag_e_adapt_parallel_test.cpp | 12 ++-- 7 files changed, 69 insertions(+), 117 deletions(-) rename src/stan/callbacks/{file_stream_writer.hpp => unique_stream_writer.hpp} (82%) delete mode 100644 src/stan/services/util/get_underlying.hpp rename src/test/unit/callbacks/{file_stream_writer_test.cpp => unique_stream_writer_test.cpp} (93%) diff --git a/src/stan/callbacks/file_stream_writer.hpp b/src/stan/callbacks/unique_stream_writer.hpp similarity index 82% rename from src/stan/callbacks/file_stream_writer.hpp rename to src/stan/callbacks/unique_stream_writer.hpp index 055f6436778..13b5d8f37e9 100644 --- a/src/stan/callbacks/file_stream_writer.hpp +++ b/src/stan/callbacks/unique_stream_writer.hpp @@ -1,5 +1,5 @@ -#ifndef STAN_CALLBACKS_FILE_STREAM_WRITER_HPP -#define STAN_CALLBACKS_FILE_STREAM_WRITER_HPP +#ifndef STAN_CALLBACKS_UNIQUE_STREAM_WRITER_HPP +#define STAN_CALLBACKS_UNIQUE_STREAM_WRITER_HPP #include #include @@ -10,32 +10,33 @@ namespace stan { namespace callbacks { /** - * file_stream_writer is an implementation - * of writer that writes to a file. + * unique_stream_writer is an implementation + * of writer that holds a unique pointer to the stream it is + * writing to. */ -class file_stream_writer final : public writer { +class unique_stream_writer final : public writer { public: /** - * Constructs a file stream writer with an output stream + * Constructs a unique stream writer with an output stream * and an optional prefix for comments. * * @param[in, out] A unique pointer to a type inheriting from `std::ostream` * @param[in] comment_prefix string to stream before each comment line. * Default is "". */ - explicit file_stream_writer(std::unique_ptr&& output, + explicit unique_stream_writer(std::unique_ptr&& output, const std::string& comment_prefix = "") : output_(std::move(output)), comment_prefix_(comment_prefix) {} - file_stream_writer(); - file_stream_writer(file_stream_writer& other) = delete; - file_stream_writer(file_stream_writer&& other) + unique_stream_writer(); + unique_stream_writer(unique_stream_writer& other) = delete; + unique_stream_writer(unique_stream_writer&& other) : output_(std::move(other.output_)), comment_prefix_(std::move(other.comment_prefix_)) {} /** * Virtual destructor */ - virtual ~file_stream_writer() {} + virtual ~unique_stream_writer() {} /** * Writes a set of names on a single line in csv format followed diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 70f237a472c..2b169a2a9d4 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include namespace stan { @@ -161,7 +160,7 @@ int hmc_nuts_dense_e_adapt( * with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContext A type derived from `stan::io::var_context` + * @tparam InitContextPtr A type derived from `stan::io::var_context` * @tparam InitMetricContext A type derived from `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` @@ -203,11 +202,11 @@ int hmc_nuts_dense_e_adapt( be the same length as this value. * @return error_codes::OK if successful */ -template int hmc_nuts_dense_e_adapt( - Model& model, const std::vector& init, - const std::vector& init_inv_metric, + Model& model, size_t num_chains, const std::vector& init, + const std::vector& init_inv_metric, unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, @@ -216,11 +215,10 @@ int hmc_nuts_dense_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t num_chains) { - using util::get_underlying; + std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_dense_e_adapt( - model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), + model, *init[0], *init_inv_metric[0], random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, @@ -237,10 +235,10 @@ int hmc_nuts_dense_e_adapt( for (int i = 0; i < num_chains; ++i) { rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); cont_vectors.emplace_back( - util::initialize(model, get_underlying(init[i]), rngs[i], + util::initialize(model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); Eigen::MatrixXd inv_metric = util::read_dense_inv_metric( - get_underlying(init_inv_metric[i]), model.num_params_r(), logger); + *init_inv_metric[i], model.num_params_r(), logger); util::validate_dense_inv_metric(inv_metric, logger); samplers.emplace_back(model, rngs[i]); @@ -319,10 +317,10 @@ int hmc_nuts_dense_e_adapt( * length as this value. * @return error_codes::OK if successful */ -template int hmc_nuts_dense_e_adapt( - Model& model, const std::vector& init, + Model& model, size_t num_chains, const std::vector& init, unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, @@ -331,28 +329,27 @@ int hmc_nuts_dense_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t num_chains = 1) { - using util::get_underlying; + std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_dense_e_adapt( - model, get_underlying(init[0]), random_seed, init_chain_id, init_radius, + model, *init[0], random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { - std::vector unit_e_metrics; + std::vector> unit_e_metrics; unit_e_metrics.reserve(num_chains); for (size_t i = 0; i < num_chains; ++i) { unit_e_metrics.emplace_back( - util::create_unit_e_dense_inv_metric(model.num_params_r())); + std::make_unique(util::create_unit_e_dense_inv_metric(model.num_params_r()))); } return hmc_nuts_dense_e_adapt( - model, init, unit_e_metrics, random_seed, init_chain_id, init_radius, + model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, - diagnostic_writer, num_chains); + diagnostic_writer); } } diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 028759bfe58..c2faeda5e17 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include namespace stan { @@ -25,7 +24,7 @@ namespace sample { * with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContext A type derived from `stan::io::var_context` + * @tparam InitContextPtr A type derived from `stan::io::var_context` * @tparam InitMetricContext A type derived from `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` @@ -59,23 +58,21 @@ namespace sample { * @param[in,out] diagnostic_writer Writer for diagnostic information * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( - Model& model, const InitContext& init, - const InitMetricContext& init_inv_metric, unsigned int random_seed, + Model& model, const stan::io::var_context& init, + const stan::io::var_context& init_inv_metric, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, InitWriter& init_writer, - SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { - using util::get_underlying; + callbacks::logger& logger, callbacks::writer& init_writer, + callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer) { boost::ecuyer1988 rng = util::create_rng(random_seed, chain); std::vector cont_vector = util::initialize( - model, get_underlying(init), rng, init_radius, true, logger, init_writer); + model, init, rng, init_radius, true, logger, init_writer); Eigen::VectorXd inv_metric; try { @@ -140,17 +137,16 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] diagnostic_writer Writer for diagnostic information * @return error_codes::OK if successful */ -template +template int hmc_nuts_diag_e_adapt( - Model& model, const InitContext& init, unsigned int random_seed, + Model& model, const stan::io::var_context& init, unsigned int random_seed, unsigned int chain, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, double delta, double gamma, double kappa, double t0, unsigned int init_buffer, unsigned int term_buffer, unsigned int window, callbacks::interrupt& interrupt, - callbacks::logger& logger, InitWriter& init_writer, - SampleWriter& sample_writer, DiagnosticWriter& diagnostic_writer) { + callbacks::logger& logger, callbacks::writer& init_writer, + callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer) { stan::io::dump unit_e_metric = util::create_unit_e_diag_inv_metric(model.num_params_r()); return hmc_nuts_diag_e_adapt( @@ -165,7 +161,7 @@ int hmc_nuts_diag_e_adapt( * Euclidean metric with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContext A type derived from `stan::io::var_context` + * @tparam InitContextPtr A type derived from `stan::io::var_context` * @tparam InitMetricContext A type derived from `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` @@ -207,11 +203,11 @@ int hmc_nuts_diag_e_adapt( be the same length as this value. * @return error_codes::OK if successful */ -template int hmc_nuts_diag_e_adapt( - Model& model, const std::vector& init, - const std::vector& init_inv_metric, + Model& model, size_t num_chains, const std::vector& init, + const std::vector& init_inv_metric, unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, @@ -220,11 +216,10 @@ int hmc_nuts_diag_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t num_chains) { - using util::get_underlying; + std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_diag_e_adapt( - model, get_underlying(init[0]), get_underlying(init_inv_metric[0]), + model, *init[0], *init_inv_metric[0], random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, @@ -241,11 +236,11 @@ int hmc_nuts_diag_e_adapt( for (int i = 0; i < num_chains; ++i) { rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); cont_vectors.emplace_back( - util::initialize(model, get_underlying(init[i]), rngs[i], + util::initialize(model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); samplers.emplace_back(model, rngs[i]); Eigen::VectorXd inv_metric = util::read_diag_inv_metric( - get_underlying(init_inv_metric[i]), model.num_params_r(), logger); + *init_inv_metric[i], model.num_params_r(), logger); util::validate_diag_inv_metric(inv_metric, logger); samplers[i].set_metric(inv_metric); @@ -323,10 +318,10 @@ int hmc_nuts_diag_e_adapt( * length as this value. * @return error_codes::OK if successful */ -template int hmc_nuts_diag_e_adapt( - Model& model, const std::vector& init, + Model& model, size_t num_chains, const std::vector& init, unsigned int random_seed, unsigned int init_chain_id, double init_radius, int num_warmup, int num_samples, int num_thin, bool save_warmup, int refresh, double stepsize, double stepsize_jitter, int max_depth, @@ -335,28 +330,27 @@ int hmc_nuts_diag_e_adapt( callbacks::interrupt& interrupt, callbacks::logger& logger, std::vector& init_writer, std::vector& sample_writer, - std::vector& diagnostic_writer, size_t num_chains) { - using util::get_underlying; + std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_diag_e_adapt( - model, get_underlying(init[0]), random_seed, init_chain_id, init_radius, + model, *init[0], random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } else { - std::vector unit_e_metrics; + std::vector> unit_e_metrics; unit_e_metrics.reserve(num_chains); for (size_t i = 0; i < num_chains; ++i) { unit_e_metrics.emplace_back( - util::create_unit_e_diag_inv_metric(model.num_params_r())); + std::make_unique(util::create_unit_e_diag_inv_metric(model.num_params_r()))); } return hmc_nuts_diag_e_adapt( - model, init, unit_e_metrics, random_seed, init_chain_id, init_radius, + model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, - diagnostic_writer, num_chains); + diagnostic_writer); } } diff --git a/src/stan/services/util/get_underlying.hpp b/src/stan/services/util/get_underlying.hpp deleted file mode 100644 index 80292d1be5f..00000000000 --- a/src/stan/services/util/get_underlying.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef STAN_SERVICES_UTIL_GET_UNDERLYING_HPP -#define STAN_SERVICES_UTIL_GET_UNDERLYING_HPP - -#include -#include - -namespace stan { -namespace services { -namespace util { -/** - * Specializtion to get a const reference to the underlying value in a - * shared_ptr. - */ -template -inline auto&& get_underlying(const std::shared_ptr& x) { - return *x; -} - -/** - * Specializtion to get a const reference to the underlying value in a - * unique_ptr. - */ -template -inline auto&& get_underlying(const std::unique_ptr& x) { - return *x; -} - -/** - * Specialization to return back the input - */ -template -inline auto&& get_underlying(T&& x) { - return std::forward(x); -} - -} // namespace util -} // namespace services -} // namespace stan - -#endif diff --git a/src/test/unit/callbacks/file_stream_writer_test.cpp b/src/test/unit/callbacks/unique_stream_writer_test.cpp similarity index 93% rename from src/test/unit/callbacks/file_stream_writer_test.cpp rename to src/test/unit/callbacks/unique_stream_writer_test.cpp index b3a64e4dcca..9556ba9c820 100644 --- a/src/test/unit/callbacks/file_stream_writer_test.cpp +++ b/src/test/unit/callbacks/unique_stream_writer_test.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include class StanInterfaceCallbacksStreamWriter : public ::testing::Test { public: @@ -13,7 +13,7 @@ class StanInterfaceCallbacksStreamWriter : public ::testing::Test { } void TearDown() {} - stan::callbacks::file_stream_writer writer; + stan::callbacks::unique_stream_writer writer; }; TEST_F(StanInterfaceCallbacksStreamWriter, double_vector) { diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp index 7d6b9c45107..dd635b4dd3f 100644 --- a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp @@ -51,10 +51,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, call_count) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( - model, context, random_seed, chain, init_radius, num_warmup, num_samples, + model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic, num_chains); + logger, init, parameter, diagnostic); EXPECT_EQ(0, return_code); @@ -91,10 +91,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, parameter_checks) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( - model, context, random_seed, chain, init_radius, num_warmup, num_samples, + model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic, num_chains); + logger, init, parameter, diagnostic); for (size_t i = 0; i < num_chains; ++i) { std::vector> parameter_names; @@ -155,10 +155,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, output_regression) { EXPECT_EQ(interrupt.call_count(), 0); stan::services::sample::hmc_nuts_dense_e_adapt( - model, context, random_seed, chain, init_radius, num_warmup, num_samples, + model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic, num_chains); + logger, init, parameter, diagnostic); for (auto&& init_it : init) { std::vector init_values; diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp index 9c6e253b108..34bfc13bc6c 100644 --- a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp @@ -51,10 +51,10 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, call_count) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( - model, context, random_seed, chain, init_radius, num_warmup, num_samples, + model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic, num_chains); + logger, init, parameter, diagnostic); EXPECT_EQ(0, return_code); @@ -91,10 +91,10 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, parameter_checks) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( - model, context, random_seed, chain, init_radius, num_warmup, num_samples, + model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic, num_chains); + logger, init, parameter, diagnostic); for (size_t i = 0; i < num_chains; ++i) { std::vector> parameter_names; @@ -155,10 +155,10 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, output_regression) { EXPECT_EQ(interrupt.call_count(), 0); stan::services::sample::hmc_nuts_diag_e_adapt( - model, context, random_seed, chain, init_radius, num_warmup, num_samples, + model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic, num_chains); + logger, init, parameter, diagnostic); for (auto&& init_it : init) { std::vector init_values; From e1e37a45004e16743a74c7cff0617684716eeef3 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 12 May 2021 16:26:42 +0000 Subject: [PATCH 29/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/callbacks/unique_stream_writer.hpp | 2 +- .../sample/hmc_nuts_dense_e_adapt.hpp | 40 +++++++++---------- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 40 +++++++++---------- .../hmc_nuts_dense_e_adapt_parallel_test.cpp | 24 +++++------ .../hmc_nuts_diag_e_adapt_parallel_test.cpp | 24 +++++------ 5 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/stan/callbacks/unique_stream_writer.hpp b/src/stan/callbacks/unique_stream_writer.hpp index 13b5d8f37e9..52e8488ec9a 100644 --- a/src/stan/callbacks/unique_stream_writer.hpp +++ b/src/stan/callbacks/unique_stream_writer.hpp @@ -25,7 +25,7 @@ class unique_stream_writer final : public writer { * Default is "". */ explicit unique_stream_writer(std::unique_ptr&& output, - const std::string& comment_prefix = "") + const std::string& comment_prefix = "") : output_(std::move(output)), comment_prefix_(comment_prefix) {} unique_stream_writer(); diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 2b169a2a9d4..bbc8f25fc55 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -218,11 +218,11 @@ int hmc_nuts_dense_e_adapt( std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_dense_e_adapt( - model, *init[0], *init_inv_metric[0], - random_seed, init_chain_id, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); + model, *init[0], *init_inv_metric[0], random_seed, init_chain_id, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer[0], + sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_dense_e_nuts; std::vector rngs; @@ -234,9 +234,9 @@ int hmc_nuts_dense_e_adapt( try { for (int i = 0; i < num_chains; ++i) { rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); - cont_vectors.emplace_back( - util::initialize(model, *init[i], rngs[i], - init_radius, true, logger, init_writer[i])); + cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], + init_radius, true, logger, + init_writer[i])); Eigen::MatrixXd inv_metric = util::read_dense_inv_metric( *init_inv_metric[i], model.num_params_r(), logger); util::validate_dense_inv_metric(inv_metric, logger); @@ -332,24 +332,24 @@ int hmc_nuts_dense_e_adapt( std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_dense_e_adapt( - model, *init[0], random_seed, init_chain_id, init_radius, - num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, - stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer[0], - sample_writer[0], diagnostic_writer[0]); + model, *init[0], random_seed, init_chain_id, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer[0], sample_writer[0], + diagnostic_writer[0]); } else { std::vector> unit_e_metrics; unit_e_metrics.reserve(num_chains); for (size_t i = 0; i < num_chains; ++i) { - unit_e_metrics.emplace_back( - std::make_unique(util::create_unit_e_dense_inv_metric(model.num_params_r()))); + unit_e_metrics.emplace_back(std::make_unique( + util::create_unit_e_dense_inv_metric(model.num_params_r()))); } return hmc_nuts_dense_e_adapt( - model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, init_radius, - num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, - stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer, sample_writer, - diagnostic_writer); + model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer, + sample_writer, diagnostic_writer); } } diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index c2faeda5e17..1c7271f2b6b 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -219,11 +219,11 @@ int hmc_nuts_diag_e_adapt( std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_diag_e_adapt( - model, *init[0], *init_inv_metric[0], - random_seed, init_chain_id, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); + model, *init[0], *init_inv_metric[0], random_seed, init_chain_id, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer[0], + sample_writer[0], diagnostic_writer[0]); } else { using sample_t = stan::mcmc::adapt_diag_e_nuts; std::vector rngs; @@ -235,9 +235,9 @@ int hmc_nuts_diag_e_adapt( try { for (int i = 0; i < num_chains; ++i) { rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); - cont_vectors.emplace_back( - util::initialize(model, *init[i], rngs[i], - init_radius, true, logger, init_writer[i])); + cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], + init_radius, true, logger, + init_writer[i])); samplers.emplace_back(model, rngs[i]); Eigen::VectorXd inv_metric = util::read_diag_inv_metric( *init_inv_metric[i], model.num_params_r(), logger); @@ -333,24 +333,24 @@ int hmc_nuts_diag_e_adapt( std::vector& diagnostic_writer) { if (num_chains == 1) { return hmc_nuts_diag_e_adapt( - model, *init[0], random_seed, init_chain_id, init_radius, - num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, - stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer[0], - sample_writer[0], diagnostic_writer[0]); + model, *init[0], random_seed, init_chain_id, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init_writer[0], sample_writer[0], + diagnostic_writer[0]); } else { std::vector> unit_e_metrics; unit_e_metrics.reserve(num_chains); for (size_t i = 0; i < num_chains; ++i) { - unit_e_metrics.emplace_back( - std::make_unique(util::create_unit_e_diag_inv_metric(model.num_params_r()))); + unit_e_metrics.emplace_back(std::make_unique( + util::create_unit_e_diag_inv_metric(model.num_params_r()))); } return hmc_nuts_diag_e_adapt( - model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, init_radius, - num_warmup, num_samples, num_thin, save_warmup, refresh, stepsize, - stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, - term_buffer, window, interrupt, logger, init_writer, sample_writer, - diagnostic_writer); + model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer, + sample_writer, diagnostic_writer); } } diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp index dd635b4dd3f..1f8d2a117b9 100644 --- a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_test.cpp @@ -51,10 +51,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, call_count) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( - model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic); + model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, parameter, diagnostic); EXPECT_EQ(0, return_code); @@ -91,10 +91,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, parameter_checks) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( - model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic); + model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, parameter, diagnostic); for (size_t i = 0; i < num_chains; ++i) { std::vector> parameter_names; @@ -155,10 +155,10 @@ TEST_F(ServicesSampleHmcNutsDenseEAdaptPar, output_regression) { EXPECT_EQ(interrupt.call_count(), 0); stan::services::sample::hmc_nuts_dense_e_adapt( - model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic); + model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, parameter, diagnostic); for (auto&& init_it : init) { std::vector init_values; diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp index 34bfc13bc6c..453b03adcdd 100644 --- a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_test.cpp @@ -51,10 +51,10 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, call_count) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( - model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic); + model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, parameter, diagnostic); EXPECT_EQ(0, return_code); @@ -91,10 +91,10 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, parameter_checks) { EXPECT_EQ(interrupt.call_count(), 0); int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( - model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic); + model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, parameter, diagnostic); for (size_t i = 0; i < num_chains; ++i) { std::vector> parameter_names; @@ -155,10 +155,10 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptPar, output_regression) { EXPECT_EQ(interrupt.call_count(), 0); stan::services::sample::hmc_nuts_diag_e_adapt( - model, num_chains, context, random_seed, chain, init_radius, num_warmup, num_samples, - num_thin, save_warmup, refresh, stepsize, stepsize_jitter, max_depth, - delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, - logger, init, parameter, diagnostic); + model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, parameter, diagnostic); for (auto&& init_it : init) { std::vector init_values; From ea9a55646b37f77c553d6278bb3ee05905115260 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 12 May 2021 12:29:22 -0400 Subject: [PATCH 30/47] update docs --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 8 ++++++-- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 2b169a2a9d4..53157920d58 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -160,8 +160,8 @@ int hmc_nuts_dense_e_adapt( * with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContextPtr A type derived from `stan::io::var_context` - * @tparam InitMetricContext A type derived from `stan::io::var_context` + * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitInvContextPtr A pointer with underlying type derived from `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` @@ -282,6 +282,10 @@ int hmc_nuts_dense_e_adapt( * with identity matrix as initial inv_metric. * * @tparam Model Model class + * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitWriter A type derived from `stan::callbacks::writer` + * @tparam SamplerWriter A type derived from `stan::callbacks::writer` + * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) * @param[in] init An std vector of init var contexts for initialization of each * chain. diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index c2faeda5e17..255b2955f4b 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -161,8 +161,8 @@ int hmc_nuts_diag_e_adapt( * Euclidean metric with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContextPtr A type derived from `stan::io::var_context` - * @tparam InitMetricContext A type derived from `stan::io::var_context` + * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitInvContextPtr A pointer with underlying type derived from `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` @@ -283,6 +283,10 @@ int hmc_nuts_diag_e_adapt( * Euclidean metric. * * @tparam Model Model class + * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam SamplerWriter A type derived from `stan::callbacks::writer` + * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` + * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) * @param[in] init An std vector of init var contexts for initialization of each * chain. From 57031ac46e70b70cdc99eaa66abb4da64eabd93d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Wed, 12 May 2021 16:30:21 +0000 Subject: [PATCH 31/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 9 ++++++--- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 4263858fc1c..85c61370028 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -160,8 +160,10 @@ int hmc_nuts_dense_e_adapt( * with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` - * @tparam InitInvContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitContextPtr A pointer with underlying type derived from + `stan::io::var_context` + * @tparam InitInvContextPtr A pointer with underlying type derived from + `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` @@ -282,7 +284,8 @@ int hmc_nuts_dense_e_adapt( * with identity matrix as initial inv_metric. * * @tparam Model Model class - * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitContextPtr A pointer with underlying type derived from + * `stan::io::var_context` * @tparam InitWriter A type derived from `stan::callbacks::writer` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index c7c05de521e..5509f6f9b69 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -161,8 +161,10 @@ int hmc_nuts_diag_e_adapt( * Euclidean metric with a pre-specified Euclidean metric. * * @tparam Model Model class - * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` - * @tparam InitInvContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitContextPtr A pointer with underlying type derived from + `stan::io::var_context` + * @tparam InitInvContextPtr A pointer with underlying type derived from + `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` @@ -283,7 +285,8 @@ int hmc_nuts_diag_e_adapt( * Euclidean metric. * * @tparam Model Model class - * @tparam InitContextPtr A pointer with underlying type derived from `stan::io::var_context` + * @tparam InitContextPtr A pointer with underlying type derived from + * `stan::io::var_context` * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` From bd76742eaee9277692938b70a472bc5d72f2e818 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 14 Jun 2021 22:47:26 -0400 Subject: [PATCH 32/47] update so tbb is only used when STAN_THREADS is defined --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 12 ++++++++++-- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 85c61370028..bd632612a4f 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -260,6 +260,7 @@ int hmc_nuts_dense_e_adapt( } catch (const std::domain_error& e) { return error_codes::CONFIG; } +#ifdef STAN_THREADS tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, @@ -273,8 +274,15 @@ int hmc_nuts_dense_e_adapt( sample_writer[i], diagnostic_writer[i], i + 1, num_chains); } }, - tbb::simple_partitioner()); - + tbb::affinity_partitioner()); +#else + for (size_t i = 0; i != num_chains; ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, num_samples, + num_thin, refresh, save_warmup, rngs[i], interrupt, logger, + sample_writer[i], diagnostic_writer[i], i + 1, num_chains); + } +#endif return error_codes::OK; } } diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 5509f6f9b69..0584eabfd5c 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -261,6 +261,7 @@ int hmc_nuts_diag_e_adapt( } catch (const std::domain_error& e) { return error_codes::CONFIG; } +#ifdef STAN_THREADS tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, @@ -274,8 +275,15 @@ int hmc_nuts_diag_e_adapt( sample_writer[i], diagnostic_writer[i], i + 1, num_chains); } }, - tbb::simple_partitioner()); - + tbb::affinity_partitioner()); +#else + for (size_t i = 0; i != num_chains; ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, num_samples, + num_thin, refresh, save_warmup, rngs[i], interrupt, logger, + sample_writer[i], diagnostic_writer[i], i + 1, num_chains); + } +#endif return error_codes::OK; } } From 851ba0125212fdd0c308b7e419f2a08dce0e83ed Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 14 Jun 2021 23:21:26 -0400 Subject: [PATCH 33/47] update to use simple partitioner --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 2 +- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index bd632612a4f..4002c088f5b 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -274,7 +274,7 @@ int hmc_nuts_dense_e_adapt( sample_writer[i], diagnostic_writer[i], i + 1, num_chains); } }, - tbb::affinity_partitioner()); + tbb::simple_partitioner()); #else for (size_t i = 0; i != num_chains; ++i) { util::run_adaptive_sampler( diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 0584eabfd5c..ac0cd1a0e76 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -275,7 +275,7 @@ int hmc_nuts_diag_e_adapt( sample_writer[i], diagnostic_writer[i], i + 1, num_chains); } }, - tbb::affinity_partitioner()); + tbb::simple_partitioner()); #else for (size_t i = 0; i != num_chains; ++i) { util::run_adaptive_sampler( From 429e7deb0e0de347de3e3200c0ecbc2878545f9a Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 14 Jun 2021 23:47:22 -0400 Subject: [PATCH 34/47] fix chain_id default so all is 1 --- src/stan/services/util/run_adaptive_sampler.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 4fac05e3f5b..b2683e3c0b1 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -44,7 +44,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, callbacks::logger& logger, callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer, - size_t chain_id = 0, size_t n_chain = 1) { + size_t chain_id = 1, size_t n_chain = 1) { Eigen::Map cont_params(cont_vector.data(), cont_vector.size()); From c66a2fdae9eb827f62e384a7b67b4cec23c06ee9 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 15 Jun 2021 11:18:32 +0000 Subject: [PATCH 35/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 4002c088f5b..9af72b8bc95 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -276,12 +276,12 @@ int hmc_nuts_dense_e_adapt( }, tbb::simple_partitioner()); #else - for (size_t i = 0; i != num_chains; ++i) { - util::run_adaptive_sampler( - samplers[i], model, cont_vectors[i], num_warmup, num_samples, - num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, num_chains); - } + for (size_t i = 0; i != num_chains; ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, num_samples, + num_thin, refresh, save_warmup, rngs[i], interrupt, logger, + sample_writer[i], diagnostic_writer[i], i + 1, num_chains); + } #endif return error_codes::OK; } From 724f8876a46b4e9060f8f7bbbd937a1087c1c7c1 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 28 Jun 2021 13:05:03 -0400 Subject: [PATCH 36/47] update create_rng() to follow the design doc --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 2 +- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 2 +- src/stan/services/util/create_rng.hpp | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 9af72b8bc95..3f71a36e0be 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -235,7 +235,7 @@ int hmc_nuts_dense_e_adapt( samplers.reserve(num_chains); try { for (int i = 0; i < num_chains; ++i) { - rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); + rngs.emplace_back(util::create_rng(random_seed, init_chain_id, i)); cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index ac0cd1a0e76..f435b9fea03 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -236,7 +236,7 @@ int hmc_nuts_diag_e_adapt( samplers.reserve(num_chains); try { for (int i = 0; i < num_chains; ++i) { - rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); + rngs.emplace_back(util::create_rng(random_seed, init_chain_id, i)); cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); diff --git a/src/stan/services/util/create_rng.hpp b/src/stan/services/util/create_rng.hpp index 9b32d4509c0..b80350bb3ba 100644 --- a/src/stan/services/util/create_rng.hpp +++ b/src/stan/services/util/create_rng.hpp @@ -19,14 +19,15 @@ namespace util { * duplicated. * * @param[in] seed the random seed - * @param[in] chain the chain id + * @param[in] init_chain_id the chain id + * @param[in] chain_num For multi-chain, the ch * @return a boost::ecuyer1988 instance */ -inline boost::ecuyer1988 create_rng(unsigned int seed, unsigned int chain) { +inline boost::ecuyer1988 create_rng(unsigned int seed, unsigned int init_chain_id, unsigned int chain_num = 0) { using boost::uintmax_t; - static uintmax_t DISCARD_STRIDE = static_cast(1) << 50; + constexpr static uintmax_t DISCARD_STRIDE = static_cast(1) << 50; boost::ecuyer1988 rng(seed); - rng.discard(DISCARD_STRIDE * chain); + rng.discard(DISCARD_STRIDE * (init_chain_id + chain_num)); return rng; } From 203d6f3aaf6e5e60030e6b15d5948fdc8bc693cf Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 28 Jun 2021 21:22:39 +0000 Subject: [PATCH 37/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/services/util/create_rng.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stan/services/util/create_rng.hpp b/src/stan/services/util/create_rng.hpp index b80350bb3ba..a3d87a68e63 100644 --- a/src/stan/services/util/create_rng.hpp +++ b/src/stan/services/util/create_rng.hpp @@ -23,7 +23,9 @@ namespace util { * @param[in] chain_num For multi-chain, the ch * @return a boost::ecuyer1988 instance */ -inline boost::ecuyer1988 create_rng(unsigned int seed, unsigned int init_chain_id, unsigned int chain_num = 0) { +inline boost::ecuyer1988 create_rng(unsigned int seed, + unsigned int init_chain_id, + unsigned int chain_num = 0) { using boost::uintmax_t; constexpr static uintmax_t DISCARD_STRIDE = static_cast(1) << 50; boost::ecuyer1988 rng(seed); From fa22037bf7c079fb96437a63ab822aaa98c9b7b5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Tue, 29 Jun 2021 14:45:00 -0400 Subject: [PATCH 38/47] adds template to unique_stream_writer to set the stream type, adds test for checking multi vs. single chain results --- src/stan/callbacks/unique_stream_writer.hpp | 6 +- .../good/optimization/rosenbrock.stan | 1 - .../callbacks/unique_stream_writer_test.cpp | 2 +- ..._nuts_diag_e_adapt_parallel_match_test.cpp | 136 ++++++++++++++++++ 4 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp diff --git a/src/stan/callbacks/unique_stream_writer.hpp b/src/stan/callbacks/unique_stream_writer.hpp index 52e8488ec9a..b576a1d77a5 100644 --- a/src/stan/callbacks/unique_stream_writer.hpp +++ b/src/stan/callbacks/unique_stream_writer.hpp @@ -13,7 +13,9 @@ namespace callbacks { * unique_stream_writer is an implementation * of writer that holds a unique pointer to the stream it is * writing to. + * @tparam Stream A type with with a valid `operator<<(std::string)` */ +template class unique_stream_writer final : public writer { public: /** @@ -24,7 +26,7 @@ class unique_stream_writer final : public writer { * @param[in] comment_prefix string to stream before each comment line. * Default is "". */ - explicit unique_stream_writer(std::unique_ptr&& output, + explicit unique_stream_writer(std::unique_ptr&& output, const std::string& comment_prefix = "") : output_(std::move(output)), comment_prefix_(comment_prefix) {} @@ -88,7 +90,7 @@ class unique_stream_writer final : public writer { /** * Output stream */ - std::unique_ptr output_; + std::unique_ptr output_; /** * Comment prefix to use when printing comments: strings and blank lines diff --git a/src/test/test-models/good/optimization/rosenbrock.stan b/src/test/test-models/good/optimization/rosenbrock.stan index db310524279..6cb7b8f8dec 100644 --- a/src/test/test-models/good/optimization/rosenbrock.stan +++ b/src/test/test-models/good/optimization/rosenbrock.stan @@ -5,4 +5,3 @@ parameters { model { target += -(pow(1 - x, 2) + 100 * pow(y - pow(x, 2), 2)); } - diff --git a/src/test/unit/callbacks/unique_stream_writer_test.cpp b/src/test/unit/callbacks/unique_stream_writer_test.cpp index 9556ba9c820..6fca0f1808f 100644 --- a/src/test/unit/callbacks/unique_stream_writer_test.cpp +++ b/src/test/unit/callbacks/unique_stream_writer_test.cpp @@ -13,7 +13,7 @@ class StanInterfaceCallbacksStreamWriter : public ::testing::Test { } void TearDown() {} - stan::callbacks::unique_stream_writer writer; + stan::callbacks::unique_stream_writer writer; }; TEST_F(StanInterfaceCallbacksStreamWriter, double_vector) { diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp new file mode 100644 index 00000000000..061401ea5e6 --- /dev/null +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +auto&& blah = stan::math::init_threadpool_tbb(); + +namespace stan { +namespace test { +/** + * Read a CSV into an Eigen matrix. + * @param in An input string stream holding the CSV + * @param rows Number of rows + * @param cols Number of columns. + */ +Eigen::MatrixXd read_stan_sample_csv(std::istringstream& in, int rows, int cols) { + std::string line; + int row = 0; + int col = 0; + Eigen::MatrixXd res = Eigen::MatrixXd(rows, cols); + while (std::getline(in, line)) { + if (line.find("#") != std::string::npos) { + continue; + } + const char* ptr = line.c_str(); + int len = line.length(); + col = 0; + + const char* start = ptr; + for (int i = 0; i < len; i++) { + if (ptr[i] == ',') { + res(row, col++) = atof(start); + start = ptr + i + 1; + } + } + res(row, col) = atof(start); + row++; + } + return res; +} +} // namespace test +} // namespace stan + +static constexpr size_t num_chains = 4; +class ServicesSampleHmcNutsDiagEAdaptParMatch : public testing::Test { + public: + ServicesSampleHmcNutsDiagEAdaptParMatch() + : model(std::make_unique( + data_context, 0, &model_log)) { + for (int i = 0; i < num_chains; ++i) { + init.push_back(stan::test::unit::instrumented_writer{}); + par_parameters.emplace_back(std::make_unique(), "#"); + seq_parameters.emplace_back(std::make_unique(), "#"); + diagnostic.push_back(stan::test::unit::instrumented_writer{}); + context.push_back(std::make_shared()); + } + } + stan::io::empty_var_context data_context; + std::stringstream model_log; + stan::test::unit::instrumented_logger logger; + std::vector init; + using str_writer = stan::callbacks::unique_stream_writer; + std::vector par_parameters; + std::vector seq_parameters; + std::vector diagnostic; + std::vector> context; + std::unique_ptr model; +}; + +TEST_F(ServicesSampleHmcNutsDiagEAdaptParMatch, single_multi_match) { + constexpr unsigned int random_seed = 0; + constexpr unsigned int chain = 0; + constexpr double init_radius = 0; + constexpr int num_warmup = 200; + constexpr int num_samples = 400; + constexpr int num_thin = 5; + constexpr bool save_warmup = true; + constexpr int refresh = 0; + constexpr double stepsize = 0.1; + constexpr double stepsize_jitter = 0; + constexpr int max_depth = 8; + constexpr double delta = .1; + constexpr double gamma = .1; + constexpr double kappa = .1; + constexpr double t0 = .1; + constexpr unsigned int init_buffer = 50; + constexpr unsigned int term_buffer = 50; + constexpr unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + int return_code = stan::services::sample::hmc_nuts_diag_e_adapt( + *model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, par_parameters, diagnostic); + + EXPECT_EQ(0, return_code); + + int num_output_lines = (num_warmup + num_samples) / num_thin; + EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); + for (int i = 0; i < num_chains; ++i) { + stan::test::unit::instrumented_writer seq_init; + stan::test::unit::instrumented_writer seq_diagnostic; + return_code = stan::services::sample::hmc_nuts_diag_e_adapt( + *model, *(context[i]), random_seed, i, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, seq_init, seq_parameters[i], seq_diagnostic); + EXPECT_EQ(0, return_code); + } + std::vector par_res; + for (int i = 0; i < num_chains; ++i) { + auto par_str = par_parameters[i].get_stream().str(); + auto sub_par_str = par_str.substr(par_str.find("Diagonal") - 1); + std::istringstream sub_par_stream(sub_par_str); + Eigen::MatrixXd par_mat = stan::test::read_stan_sample_csv(sub_par_stream, 80, 9); + par_res.push_back(par_mat); + } + std::vector seq_res; + for (int i = 0; i < num_chains; ++i) { + auto seq_str = seq_parameters[i].get_stream().str(); + auto sub_seq_str = seq_str.substr(seq_str.find("Diagonal") - 1); + std::istringstream sub_seq_stream(sub_seq_str); + Eigen::MatrixXd seq_mat = stan::test::read_stan_sample_csv(sub_seq_stream, 80, 9); + seq_res.push_back(seq_mat); + } + for (int i = 0; i < num_chains; ++i) { + Eigen::MatrixXd diff_res + = (par_res[i].array() - seq_res[i].array()).matrix(); + EXPECT_MATRIX_EQ(diff_res, Eigen::MatrixXd::Zero(80, 9)); + } +} From a115c82d37f022f9472561469cf4a02604f51e23 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Tue, 29 Jun 2021 18:51:50 +0000 Subject: [PATCH 39/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../hmc_nuts_diag_e_adapt_parallel_match_test.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp index 061401ea5e6..8f9274b7dac 100644 --- a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp @@ -17,7 +17,8 @@ namespace test { * @param rows Number of rows * @param cols Number of columns. */ -Eigen::MatrixXd read_stan_sample_csv(std::istringstream& in, int rows, int cols) { +Eigen::MatrixXd read_stan_sample_csv(std::istringstream& in, int rows, + int cols) { std::string line; int row = 0; int col = 0; @@ -50,7 +51,7 @@ class ServicesSampleHmcNutsDiagEAdaptParMatch : public testing::Test { public: ServicesSampleHmcNutsDiagEAdaptParMatch() : model(std::make_unique( - data_context, 0, &model_log)) { + data_context, 0, &model_log)) { for (int i = 0; i < num_chains; ++i) { init.push_back(stan::test::unit::instrumented_writer{}); par_parameters.emplace_back(std::make_unique(), "#"); @@ -117,7 +118,8 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptParMatch, single_multi_match) { auto par_str = par_parameters[i].get_stream().str(); auto sub_par_str = par_str.substr(par_str.find("Diagonal") - 1); std::istringstream sub_par_stream(sub_par_str); - Eigen::MatrixXd par_mat = stan::test::read_stan_sample_csv(sub_par_stream, 80, 9); + Eigen::MatrixXd par_mat + = stan::test::read_stan_sample_csv(sub_par_stream, 80, 9); par_res.push_back(par_mat); } std::vector seq_res; @@ -125,7 +127,8 @@ TEST_F(ServicesSampleHmcNutsDiagEAdaptParMatch, single_multi_match) { auto seq_str = seq_parameters[i].get_stream().str(); auto sub_seq_str = seq_str.substr(seq_str.find("Diagonal") - 1); std::istringstream sub_seq_stream(sub_seq_str); - Eigen::MatrixXd seq_mat = stan::test::read_stan_sample_csv(sub_seq_stream, 80, 9); + Eigen::MatrixXd seq_mat + = stan::test::read_stan_sample_csv(sub_seq_stream, 80, 9); seq_res.push_back(seq_mat); } for (int i = 0; i < num_chains; ++i) { From 51c447235600841cc2cf25a4188e7a844ae6a4ef Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 30 Jun 2021 17:24:22 -0400 Subject: [PATCH 40/47] update dense and diag adapt for math changes --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 9 --------- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 9 --------- 2 files changed, 18 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 3f71a36e0be..ce6485cefc6 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -260,7 +260,6 @@ int hmc_nuts_dense_e_adapt( } catch (const std::domain_error& e) { return error_codes::CONFIG; } -#ifdef STAN_THREADS tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, @@ -275,14 +274,6 @@ int hmc_nuts_dense_e_adapt( } }, tbb::simple_partitioner()); -#else - for (size_t i = 0; i != num_chains; ++i) { - util::run_adaptive_sampler( - samplers[i], model, cont_vectors[i], num_warmup, num_samples, - num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, num_chains); - } -#endif return error_codes::OK; } } diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index f435b9fea03..82c4b326a82 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -261,7 +261,6 @@ int hmc_nuts_diag_e_adapt( } catch (const std::domain_error& e) { return error_codes::CONFIG; } -#ifdef STAN_THREADS tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, @@ -276,14 +275,6 @@ int hmc_nuts_diag_e_adapt( } }, tbb::simple_partitioner()); -#else - for (size_t i = 0; i != num_chains; ++i) { - util::run_adaptive_sampler( - samplers[i], model, cont_vectors[i], num_warmup, num_samples, - num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, num_chains); - } -#endif return error_codes::OK; } } From 1ad42b4aae489be6ae1ed13b87d509d94fc09ae1 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 1 Jul 2021 17:07:25 -0400 Subject: [PATCH 41/47] cleanup docs and change printout of chain number to take the initial chain id into account --- .../services/util/run_adaptive_sampler.hpp | 3 + ...nuts_dense_e_adapt_parallel_match_test.cpp | 109 ++++++++++++++++++ ..._nuts_diag_e_adapt_parallel_match_test.cpp | 43 +------ src/test/unit/services/util.hpp | 45 ++++++++ 4 files changed, 163 insertions(+), 37 deletions(-) create mode 100644 src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp create mode 100644 src/test/unit/services/util.hpp diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index b2683e3c0b1..96221c8abf4 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -34,6 +34,9 @@ namespace util { * @param[in,out] logger logger for messages * @param[in,out] sample_writer writer for draws * @param[in,out] diagnostic_writer writer for diagnostic information + * @param[in] chain_id The id for a given chain. + * @param[in] n_chain The number of chains used in the program. This + * is used in generate transitions to print out the chain number. */ template void run_adaptive_sampler(Sampler& sampler, Model& model, diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp new file mode 100644 index 00000000000..3426afba375 --- /dev/null +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +auto&& blah = stan::math::init_threadpool_tbb(); + + +static constexpr size_t num_chains = 4; +class ServicesSampleHmcNutsDenseEAdaptParMatch : public testing::Test { + public: + ServicesSampleHmcNutsDenseEAdaptParMatch() + : model(std::make_unique( + data_context, 0, &model_log)) { + for (int i = 0; i < num_chains; ++i) { + init.push_back(stan::test::unit::instrumented_writer{}); + par_parameters.emplace_back(std::make_unique(), "#"); + seq_parameters.emplace_back(std::make_unique(), "#"); + diagnostic.push_back(stan::test::unit::instrumented_writer{}); + context.push_back(std::make_shared()); + } + } + stan::io::empty_var_context data_context; + std::stringstream model_log; + stan::test::unit::instrumented_logger logger; + std::vector init; + using str_writer = stan::callbacks::unique_stream_writer; + std::vector par_parameters; + std::vector seq_parameters; + std::vector diagnostic; + std::vector> context; + std::unique_ptr model; +}; + +/** + * This test checks that running multiple chains in one call + * with the same initial id is the same as running multiple calls + * with incrementing chain ids. + */ +TEST_F(ServicesSampleHmcNutsDenseEAdaptParMatch, single_multi_match) { + constexpr unsigned int random_seed = 0; + constexpr unsigned int chain = 0; + constexpr double init_radius = 0; + constexpr int num_warmup = 200; + constexpr int num_samples = 400; + constexpr int num_thin = 5; + constexpr bool save_warmup = true; + constexpr int refresh = 0; + constexpr double stepsize = 0.1; + constexpr double stepsize_jitter = 0; + constexpr int max_depth = 8; + constexpr double delta = .1; + constexpr double gamma = .1; + constexpr double kappa = .1; + constexpr double t0 = .1; + constexpr unsigned int init_buffer = 50; + constexpr unsigned int term_buffer = 50; + constexpr unsigned int window = 100; + stan::test::unit::instrumented_interrupt interrupt; + EXPECT_EQ(interrupt.call_count(), 0); + int return_code = stan::services::sample::hmc_nuts_dense_e_adapt( + *model, num_chains, context, random_seed, chain, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, init, par_parameters, diagnostic); + + EXPECT_EQ(0, return_code); + + int num_output_lines = (num_warmup + num_samples) / num_thin; + EXPECT_EQ((num_warmup + num_samples) * num_chains, interrupt.call_count()); + for (int i = 0; i < num_chains; ++i) { + stan::test::unit::instrumented_writer seq_init; + stan::test::unit::instrumented_writer seq_diagnostic; + return_code = stan::services::sample::hmc_nuts_dense_e_adapt( + *model, *(context[i]), random_seed, i, init_radius, num_warmup, + num_samples, num_thin, save_warmup, refresh, stepsize, stepsize_jitter, + max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, + interrupt, logger, seq_init, seq_parameters[i], seq_diagnostic); + EXPECT_EQ(0, return_code); + } + std::vector par_res; + for (int i = 0; i < num_chains; ++i) { + auto par_str = par_parameters[i].get_stream().str(); + auto sub_par_str = par_str.substr(par_str.find("Elements") - 1); + std::istringstream sub_par_stream(sub_par_str); + Eigen::MatrixXd par_mat + = stan::test::read_stan_sample_csv(sub_par_stream, 80, 9); + par_res.push_back(par_mat); + } + std::vector seq_res; + for (int i = 0; i < num_chains; ++i) { + auto seq_str = seq_parameters[i].get_stream().str(); + auto sub_seq_str = seq_str.substr(seq_str.find("Elements") - 1); + std::istringstream sub_seq_stream(sub_seq_str); + Eigen::MatrixXd seq_mat + = stan::test::read_stan_sample_csv(sub_seq_stream, 80, 9); + seq_res.push_back(seq_mat); + } + for (int i = 0; i < num_chains; ++i) { + Eigen::MatrixXd diff_res + = (par_res[i].array() - seq_res[i].array()).matrix(); + EXPECT_MATRIX_EQ(diff_res, Eigen::MatrixXd::Zero(80, 9)); + } +} diff --git a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp index 8f9274b7dac..c4167419cbf 100644 --- a/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_diag_e_adapt_parallel_match_test.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -9,43 +10,6 @@ auto&& blah = stan::math::init_threadpool_tbb(); -namespace stan { -namespace test { -/** - * Read a CSV into an Eigen matrix. - * @param in An input string stream holding the CSV - * @param rows Number of rows - * @param cols Number of columns. - */ -Eigen::MatrixXd read_stan_sample_csv(std::istringstream& in, int rows, - int cols) { - std::string line; - int row = 0; - int col = 0; - Eigen::MatrixXd res = Eigen::MatrixXd(rows, cols); - while (std::getline(in, line)) { - if (line.find("#") != std::string::npos) { - continue; - } - const char* ptr = line.c_str(); - int len = line.length(); - col = 0; - - const char* start = ptr; - for (int i = 0; i < len; i++) { - if (ptr[i] == ',') { - res(row, col++) = atof(start); - start = ptr + i + 1; - } - } - res(row, col) = atof(start); - row++; - } - return res; -} -} // namespace test -} // namespace stan - static constexpr size_t num_chains = 4; class ServicesSampleHmcNutsDiagEAdaptParMatch : public testing::Test { public: @@ -72,6 +36,11 @@ class ServicesSampleHmcNutsDiagEAdaptParMatch : public testing::Test { std::unique_ptr model; }; +/** + * This test checks that running multiple chains in one call + * with the same initial id is the same as running multiple calls + * with incrementing chain ids. + */ TEST_F(ServicesSampleHmcNutsDiagEAdaptParMatch, single_multi_match) { constexpr unsigned int random_seed = 0; constexpr unsigned int chain = 0; diff --git a/src/test/unit/services/util.hpp b/src/test/unit/services/util.hpp new file mode 100644 index 00000000000..f283fa6f49f --- /dev/null +++ b/src/test/unit/services/util.hpp @@ -0,0 +1,45 @@ +#ifndef STAN_SRC_TEST_UNIT_SERVICES_UTIL_HPP +#define STAN_SRC_TEST_UNIT_SERVICES_UTIL_HPP + +#include +#include +#include +#include + +namespace stan { +namespace test { +/** + * Read a CSV into an Eigen matrix. + * @param in An input string stream holding the CSV + * @param rows Number of rows + * @param cols Number of columns. + */ +Eigen::MatrixXd read_stan_sample_csv(std::istringstream& in, int rows, + int cols) { + std::string line; + int row = 0; + int col = 0; + Eigen::MatrixXd res = Eigen::MatrixXd(rows, cols); + while (std::getline(in, line)) { + if (line.find("#") != std::string::npos) { + continue; + } + const char* ptr = line.c_str(); + int len = line.length(); + col = 0; + + const char* start = ptr; + for (int i = 0; i < len; i++) { + if (ptr[i] == ',') { + res(row, col++) = atof(start); + start = ptr + i + 1; + } + } + res(row, col) = atof(start); + row++; + } + return res; +} +} // namespace test +} // namespace stan +#endif From c50cf1a57d890ca65b1351452868305645eadd1d Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 1 Jul 2021 21:12:41 +0000 Subject: [PATCH 42/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp index 3426afba375..901afbc6ab7 100644 --- a/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp +++ b/src/test/unit/services/sample/hmc_nuts_dense_e_adapt_parallel_match_test.cpp @@ -10,7 +10,6 @@ auto&& blah = stan::math::init_threadpool_tbb(); - static constexpr size_t num_chains = 4; class ServicesSampleHmcNutsDenseEAdaptParMatch : public testing::Test { public: From c09ca139647ab4f916579460df76039dd0a57ec0 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Fri, 2 Jul 2021 17:59:53 -0400 Subject: [PATCH 43/47] update printing logic --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 4 ++-- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index ce6485cefc6..26f53cf7f28 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -262,7 +262,7 @@ int hmc_nuts_dense_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, + [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, init_chain_id, &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { @@ -270,7 +270,7 @@ int hmc_nuts_dense_e_adapt( util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, num_chains); + sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, num_chains); } }, tbb::simple_partitioner()); diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 82c4b326a82..079f3b39f75 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -263,7 +263,7 @@ int hmc_nuts_diag_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, + [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, init_chain_id, &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { @@ -271,7 +271,7 @@ int hmc_nuts_diag_e_adapt( util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], i + 1, num_chains); + sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, num_chains); } }, tbb::simple_partitioner()); From 91d51e1eedef1fb88ff9c5ea3ab1bbf64b755a42 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Fri, 2 Jul 2021 22:05:21 +0000 Subject: [PATCH 44/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 9 +++++---- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 26f53cf7f28..2998959f17a 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -262,15 +262,16 @@ int hmc_nuts_dense_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, init_chain_id, - &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, - &cont_vectors, + [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, + init_chain_id, &samplers, &model, &rngs, &interrupt, &logger, + &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, num_chains); + sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, + num_chains); } }, tbb::simple_partitioner()); diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 079f3b39f75..d0a86e06dd7 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -263,15 +263,16 @@ int hmc_nuts_diag_e_adapt( } tbb::parallel_for( tbb::blocked_range(0, num_chains, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, init_chain_id, - &samplers, &model, &rngs, &interrupt, &logger, &sample_writer, - &cont_vectors, + [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, + init_chain_id, &samplers, &model, &rngs, &interrupt, &logger, + &sample_writer, &cont_vectors, &diagnostic_writer](const tbb::blocked_range& r) { for (size_t i = r.begin(); i != r.end(); ++i) { util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, num_chains); + sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, + num_chains); } }, tbb::simple_partitioner()); From 569df85af292509764cc951025b5510cd0defaa5 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 7 Jul 2021 10:34:19 -0400 Subject: [PATCH 45/47] update to remove +1 from chain number --- src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp | 2 +- src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 2998959f17a..02e68883efe 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -270,7 +270,7 @@ int hmc_nuts_dense_e_adapt( util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, + sample_writer[i], diagnostic_writer[i], init_chain_id + i, num_chains); } }, diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index d0a86e06dd7..befa064a631 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -271,7 +271,7 @@ int hmc_nuts_diag_e_adapt( util::run_adaptive_sampler( samplers[i], model, cont_vectors[i], num_warmup, num_samples, num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], init_chain_id + i + 1, + sample_writer[i], diagnostic_writer[i], init_chain_id + i, num_chains); } }, From 4f82e2447d4353052b31344f6aa084ca205ce1af Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 19 Jul 2021 15:53:23 -0400 Subject: [PATCH 46/47] Make sure to use num_chains instead of n_chain everywhere, fix docs, removes unneeded else branch --- .../sample/hmc_nuts_dense_e_adapt.hpp | 32 ++++++------- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 33 +++++++------ src/stan/services/util/create_rng.hpp | 47 +++++++++---------- .../services/util/generate_transitions.hpp | 6 ++- .../services/util/run_adaptive_sampler.hpp | 8 ++-- 5 files changed, 61 insertions(+), 65 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index 02e68883efe..a129a39e3b7 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -168,14 +168,17 @@ int hmc_nuts_dense_e_adapt( * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) + * @param[in] num_chains The number of chains to run in parallel. `init`, + * `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must + * be the same length as this value. * @param[in] init An std vector of init var contexts for initialization of each - chain. + * chain. * @param[in] init_inv_metric An std vector of var contexts exposing an initial - diagonal inverse Euclidean metric for each chain (must be positive definite) + * diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator * @param[in] init_chain_id first chain id. The pseudo random number generator - will advance by for each chain by an integer sequence from `init_chain_id` to - `num_chains` + * will advance by for each chain by an integer sequence from `init_chain_id` to + * `init_chain_id+num_chains-1` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -198,10 +201,7 @@ int hmc_nuts_dense_e_adapt( inits of each chain. * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic - information of each chain. - * @param[in] num_chains The number of chains to run in parallel. `init`, - `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must - be the same length as this value. + * information of each chain. * @return error_codes::OK if successful */ template ; std::vector rngs; rngs.reserve(num_chains); @@ -235,7 +235,7 @@ int hmc_nuts_dense_e_adapt( samplers.reserve(num_chains); try { for (int i = 0; i < num_chains; ++i) { - rngs.emplace_back(util::create_rng(random_seed, init_chain_id, i)); + rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); @@ -276,7 +276,6 @@ int hmc_nuts_dense_e_adapt( }, tbb::simple_partitioner()); return error_codes::OK; - } } /** @@ -290,12 +289,15 @@ int hmc_nuts_dense_e_adapt( * @tparam SamplerWriter A type derived from `stan::callbacks::writer` * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) + * @param[in] num_chains The number of chains to run in parallel. `init`, + * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same + * length as this value. * @param[in] init An std vector of init var contexts for initialization of each * chain. * @param[in] random_seed random seed for the random number generator * @param[in] init_chain_id first chain id. The pseudo random number generator * will advance by for each chain by an integer sequence from `init_chain_id` to - * `num_chains` + * `init_chain_id+num_chains-1` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -319,9 +321,6 @@ int hmc_nuts_dense_e_adapt( * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic * information of each chain. - * @param[in] num_chains The number of chains to run in parallel. `init`, - * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same - * length as this value. * @return error_codes::OK if successful */ template > unit_e_metrics; unit_e_metrics.reserve(num_chains); for (size_t i = 0; i < num_chains; ++i) { @@ -357,7 +356,6 @@ int hmc_nuts_dense_e_adapt( stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, diagnostic_writer); - } } } // namespace sample diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index befa064a631..203ad37ce89 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -169,14 +169,17 @@ int hmc_nuts_diag_e_adapt( * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) + * @param[in] num_chains The number of chains to run in parallel. `init`, + * `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must + * be the same length as this value. * @param[in] init An std vector of init var contexts for initialization of each - chain. + * chain. * @param[in] init_inv_metric An std vector of var contexts exposing an initial diagonal inverse Euclidean metric for each chain (must be positive definite) * @param[in] random_seed random seed for the random number generator * @param[in] init_chain_id first chain id. The pseudo random number generator - will advance by for each chain by an integer sequence from `init_chain_id` to - `num_chains` + * will advance for each chain by an integer sequence from `init_chain_id` to + * `init_chain_id + num_chains - 1` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -196,13 +199,10 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] interrupt Callback for interrupts * @param[in,out] logger Logger for messages * @param[in,out] init_writer std vector of Writer callbacks for unconstrained - inits of each chain. + * inits of each chain. * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic - information of each chain. - * @param[in] num_chains The number of chains to run in parallel. `init`, - `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must - be the same length as this value. + * information of each chain. * @return error_codes::OK if successful */ template ; std::vector rngs; rngs.reserve(num_chains); @@ -236,7 +236,7 @@ int hmc_nuts_diag_e_adapt( samplers.reserve(num_chains); try { for (int i = 0; i < num_chains; ++i) { - rngs.emplace_back(util::create_rng(random_seed, init_chain_id, i)); + rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); @@ -277,7 +277,7 @@ int hmc_nuts_diag_e_adapt( }, tbb::simple_partitioner()); return error_codes::OK; - } + } /** @@ -291,12 +291,15 @@ int hmc_nuts_diag_e_adapt( * @tparam DiagnosticWriter A type derived from `stan::callbacks::writer` * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) + * @param[in] num_chains The number of chains to run in parallel. `init`, + * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same + * length as this value. * @param[in] init An std vector of init var contexts for initialization of each * chain. * @param[in] random_seed random seed for the random number generator * @param[in] init_chain_id first chain id. The pseudo random number generator * will advance by for each chain by an integer sequence from `init_chain_id` to - * `num_chains` + * `init_chain_id+num_chains-1` * @param[in] init_radius radius to initialize * @param[in] num_warmup Number of warmup samples * @param[in] num_samples Number of samples @@ -320,9 +323,6 @@ int hmc_nuts_diag_e_adapt( * @param[in,out] sample_writer std vector of Writers for draws of each chain. * @param[in,out] diagnostic_writer std vector of Writers for diagnostic * information of each chain. - * @param[in] num_chains The number of chains to run in parallel. `init`, - * `init_writer`, `sample_writer`, and `diagnostic_writer` must be the same - * length as this value. * @return error_codes::OK if successful */ template > unit_e_metrics; unit_e_metrics.reserve(num_chains); for (size_t i = 0; i < num_chains; ++i) { @@ -358,7 +358,6 @@ int hmc_nuts_diag_e_adapt( stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, init_buffer, term_buffer, window, interrupt, logger, init_writer, sample_writer, diagnostic_writer); - } } } // namespace sample diff --git a/src/stan/services/util/create_rng.hpp b/src/stan/services/util/create_rng.hpp index a3d87a68e63..39f8e4ce9be 100644 --- a/src/stan/services/util/create_rng.hpp +++ b/src/stan/services/util/create_rng.hpp @@ -7,31 +7,28 @@ namespace stan { namespace services { namespace util { -/** - * Creates a pseudo random number generator from a random seed - * and a chain id by initializing the PRNG with the seed and - * then advancing past pow(2, 50) times the chain ID draws to - * ensure different chains sample from different segments of the - * pseudo random number sequence. - * - * Chain IDs should be kept to larger values than one to ensure - * that the draws used to initialized transformed data are not - * duplicated. - * - * @param[in] seed the random seed - * @param[in] init_chain_id the chain id - * @param[in] chain_num For multi-chain, the ch - * @return a boost::ecuyer1988 instance - */ -inline boost::ecuyer1988 create_rng(unsigned int seed, - unsigned int init_chain_id, - unsigned int chain_num = 0) { - using boost::uintmax_t; - constexpr static uintmax_t DISCARD_STRIDE = static_cast(1) << 50; - boost::ecuyer1988 rng(seed); - rng.discard(DISCARD_STRIDE * (init_chain_id + chain_num)); - return rng; -} + /** + * Creates a pseudo random number generator from a random seed + * and a chain id by initializing the PRNG with the seed and + * then advancing past pow(2, 50) times the chain ID draws to + * ensure different chains sample from different segments of the + * pseudo random number sequence. + * + * Chain IDs should be kept to larger values than one to ensure + * that the draws used to initialized transformed data are not + * duplicated. + * + * @param[in] seed the random seed + * @param[in] chain the chain id + * @return a boost::ecuyer1988 instance + */ + inline boost::ecuyer1988 create_rng(unsigned int seed, unsigned int chain) { + using boost::uintmax_t; + static constexpr uintmax_t DISCARD_STRIDE = static_cast(1) << 50; + boost::ecuyer1988 rng(seed); + rng.discard(DISCARD_STRIDE * chain); + return rng; + } } // namespace util } // namespace services diff --git a/src/stan/services/util/generate_transitions.hpp b/src/stan/services/util/generate_transitions.hpp index c5c04843930..5b1aa1a27dc 100644 --- a/src/stan/services/util/generate_transitions.hpp +++ b/src/stan/services/util/generate_transitions.hpp @@ -36,6 +36,8 @@ namespace util { * @param[in,out] base_rng random number generator * @param[in,out] callback interrupt callback called once an iteration * @param[in,out] logger logger for messages + * @param[in] num_chains The number of chains used in the program. This + * is used in generate transitions to print out the chain number. */ template void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, @@ -45,7 +47,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, stan::mcmc::sample& init_s, Model& model, RNG& base_rng, callbacks::interrupt& callback, callbacks::logger& logger, size_t chain_id = 1, - size_t n_chain = 1) { + size_t num_chains = 1) { for (int m = 0; m < num_iterations; ++m) { callback(); @@ -53,7 +55,7 @@ void generate_transitions(stan::mcmc::base_mcmc& sampler, int num_iterations, && (start + m + 1 == finish || m == 0 || (m + 1) % refresh == 0)) { int it_print_width = std::ceil(std::log10(static_cast(finish))); std::stringstream message; - if (n_chain != 1) { + if (num_chains != 1) { message << "Chain [" << chain_id << "] "; } message << "Iteration: "; diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index 96221c8abf4..ea0f3452225 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -35,7 +35,7 @@ namespace util { * @param[in,out] sample_writer writer for draws * @param[in,out] diagnostic_writer writer for diagnostic information * @param[in] chain_id The id for a given chain. - * @param[in] n_chain The number of chains used in the program. This + * @param[in] num_chains The number of chains used in the program. This * is used in generate transitions to print out the chain number. */ template @@ -47,7 +47,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, callbacks::logger& logger, callbacks::writer& sample_writer, callbacks::writer& diagnostic_writer, - size_t chain_id = 1, size_t n_chain = 1) { + size_t chain_id = 1, size_t num_chains = 1) { Eigen::Map cont_params(cont_vector.data(), cont_vector.size()); @@ -71,7 +71,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, auto start_warm = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_warmup, 0, num_warmup + num_samples, num_thin, refresh, save_warmup, true, writer, s, - model, rng, interrupt, logger, chain_id, n_chain); + model, rng, interrupt, logger, chain_id, num_chains); auto end_warm = std::chrono::steady_clock::now(); double warm_delta_t = std::chrono::duration_cast( end_warm - start_warm) @@ -85,7 +85,7 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, util::generate_transitions(sampler, num_samples, num_warmup, num_warmup + num_samples, num_thin, refresh, true, false, writer, s, model, rng, interrupt, logger, - chain_id, n_chain); + chain_id, num_chains); auto end_sample = std::chrono::steady_clock::now(); double sample_delta_t = std::chrono::duration_cast( end_sample - start_sample) From a11a48a3d02024301677e7a98071ae6f66287159 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 19 Jul 2021 20:34:05 +0000 Subject: [PATCH 47/47] [Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final) --- .../sample/hmc_nuts_dense_e_adapt.hpp | 120 ++++++++--------- .../services/sample/hmc_nuts_diag_e_adapt.hpp | 121 +++++++++--------- src/stan/services/util/create_rng.hpp | 44 +++---- .../services/util/run_adaptive_sampler.hpp | 3 +- 4 files changed, 144 insertions(+), 144 deletions(-) diff --git a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp index a129a39e3b7..2733cff1f40 100644 --- a/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_dense_e_adapt.hpp @@ -169,7 +169,8 @@ int hmc_nuts_dense_e_adapt( * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) * @param[in] num_chains The number of chains to run in parallel. `init`, - * `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must + * `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` + must * be the same length as this value. * @param[in] init An std vector of init var contexts for initialization of each * chain. @@ -226,56 +227,55 @@ int hmc_nuts_dense_e_adapt( init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } - using sample_t = stan::mcmc::adapt_dense_e_nuts; - std::vector rngs; - rngs.reserve(num_chains); - std::vector> cont_vectors; - cont_vectors.reserve(num_chains); - std::vector samplers; - samplers.reserve(num_chains); - try { - for (int i = 0; i < num_chains; ++i) { - rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); - cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], - init_radius, true, logger, - init_writer[i])); - Eigen::MatrixXd inv_metric = util::read_dense_inv_metric( - *init_inv_metric[i], model.num_params_r(), logger); - util::validate_dense_inv_metric(inv_metric, logger); + using sample_t = stan::mcmc::adapt_dense_e_nuts; + std::vector rngs; + rngs.reserve(num_chains); + std::vector> cont_vectors; + cont_vectors.reserve(num_chains); + std::vector samplers; + samplers.reserve(num_chains); + try { + for (int i = 0; i < num_chains; ++i) { + rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); + cont_vectors.emplace_back(util::initialize( + model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); + Eigen::MatrixXd inv_metric = util::read_dense_inv_metric( + *init_inv_metric[i], model.num_params_r(), logger); + util::validate_dense_inv_metric(inv_metric, logger); - samplers.emplace_back(model, rngs[i]); - samplers[i].set_metric(inv_metric); - samplers[i].set_nominal_stepsize(stepsize); - samplers[i].set_stepsize_jitter(stepsize_jitter); - samplers[i].set_max_depth(max_depth); + samplers.emplace_back(model, rngs[i]); + samplers[i].set_metric(inv_metric); + samplers[i].set_nominal_stepsize(stepsize); + samplers[i].set_stepsize_jitter(stepsize_jitter); + samplers[i].set_max_depth(max_depth); - samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); - samplers[i].get_stepsize_adaptation().set_delta(delta); - samplers[i].get_stepsize_adaptation().set_gamma(gamma); - samplers[i].get_stepsize_adaptation().set_kappa(kappa); - samplers[i].get_stepsize_adaptation().set_t0(t0); - samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, - window, logger); - } - } catch (const std::domain_error& e) { - return error_codes::CONFIG; + samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); + samplers[i].get_stepsize_adaptation().set_delta(delta); + samplers[i].get_stepsize_adaptation().set_gamma(gamma); + samplers[i].get_stepsize_adaptation().set_kappa(kappa); + samplers[i].get_stepsize_adaptation().set_t0(t0); + samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, + window, logger); } - tbb::parallel_for( - tbb::blocked_range(0, num_chains, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, - init_chain_id, &samplers, &model, &rngs, &interrupt, &logger, - &sample_writer, &cont_vectors, - &diagnostic_writer](const tbb::blocked_range& r) { - for (size_t i = r.begin(); i != r.end(); ++i) { - util::run_adaptive_sampler( - samplers[i], model, cont_vectors[i], num_warmup, num_samples, - num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], init_chain_id + i, - num_chains); - } - }, - tbb::simple_partitioner()); - return error_codes::OK; + } catch (const std::domain_error& e) { + return error_codes::CONFIG; + } + tbb::parallel_for(tbb::blocked_range(0, num_chains, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, + num_chains, init_chain_id, &samplers, &model, &rngs, + &interrupt, &logger, &sample_writer, &cont_vectors, + &diagnostic_writer](const tbb::blocked_range& r) { + for (size_t i = r.begin(); i != r.end(); ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, + num_samples, num_thin, refresh, save_warmup, + rngs[i], interrupt, logger, sample_writer[i], + diagnostic_writer[i], init_chain_id + i, + num_chains); + } + }, + tbb::simple_partitioner()); + return error_codes::OK; } /** @@ -344,18 +344,18 @@ int hmc_nuts_dense_e_adapt( interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } - std::vector> unit_e_metrics; - unit_e_metrics.reserve(num_chains); - for (size_t i = 0; i < num_chains; ++i) { - unit_e_metrics.emplace_back(std::make_unique( - util::create_unit_e_dense_inv_metric(model.num_params_r()))); - } - return hmc_nuts_dense_e_adapt( - model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, - init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, - stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, - init_buffer, term_buffer, window, interrupt, logger, init_writer, - sample_writer, diagnostic_writer); + std::vector> unit_e_metrics; + unit_e_metrics.reserve(num_chains); + for (size_t i = 0; i < num_chains; ++i) { + unit_e_metrics.emplace_back(std::make_unique( + util::create_unit_e_dense_inv_metric(model.num_params_r()))); + } + return hmc_nuts_dense_e_adapt( + model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer, + sample_writer, diagnostic_writer); } } // namespace sample diff --git a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp index 203ad37ce89..9689fa4a9a1 100644 --- a/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp +++ b/src/stan/services/sample/hmc_nuts_diag_e_adapt.hpp @@ -170,7 +170,8 @@ int hmc_nuts_diag_e_adapt( * @tparam InitWriter A type derived from `stan::callbacks::writer` * @param[in] model Input model to test (with data already instantiated) * @param[in] num_chains The number of chains to run in parallel. `init`, - * `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` must + * `init_inv_metric`, `init_writer`, `sample_writer`, and `diagnostic_writer` + must * be the same length as this value. * @param[in] init An std vector of init var contexts for initialization of each * chain. @@ -227,57 +228,55 @@ int hmc_nuts_diag_e_adapt( init_buffer, term_buffer, window, interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } - using sample_t = stan::mcmc::adapt_diag_e_nuts; - std::vector rngs; - rngs.reserve(num_chains); - std::vector> cont_vectors; - cont_vectors.reserve(num_chains); - std::vector samplers; - samplers.reserve(num_chains); - try { - for (int i = 0; i < num_chains; ++i) { - rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); - cont_vectors.emplace_back(util::initialize(model, *init[i], rngs[i], - init_radius, true, logger, - init_writer[i])); - samplers.emplace_back(model, rngs[i]); - Eigen::VectorXd inv_metric = util::read_diag_inv_metric( - *init_inv_metric[i], model.num_params_r(), logger); - util::validate_diag_inv_metric(inv_metric, logger); + using sample_t = stan::mcmc::adapt_diag_e_nuts; + std::vector rngs; + rngs.reserve(num_chains); + std::vector> cont_vectors; + cont_vectors.reserve(num_chains); + std::vector samplers; + samplers.reserve(num_chains); + try { + for (int i = 0; i < num_chains; ++i) { + rngs.emplace_back(util::create_rng(random_seed, init_chain_id + i)); + cont_vectors.emplace_back(util::initialize( + model, *init[i], rngs[i], init_radius, true, logger, init_writer[i])); + samplers.emplace_back(model, rngs[i]); + Eigen::VectorXd inv_metric = util::read_diag_inv_metric( + *init_inv_metric[i], model.num_params_r(), logger); + util::validate_diag_inv_metric(inv_metric, logger); - samplers[i].set_metric(inv_metric); - samplers[i].set_nominal_stepsize(stepsize); - samplers[i].set_stepsize_jitter(stepsize_jitter); - samplers[i].set_max_depth(max_depth); + samplers[i].set_metric(inv_metric); + samplers[i].set_nominal_stepsize(stepsize); + samplers[i].set_stepsize_jitter(stepsize_jitter); + samplers[i].set_max_depth(max_depth); - samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); - samplers[i].get_stepsize_adaptation().set_delta(delta); - samplers[i].get_stepsize_adaptation().set_gamma(gamma); - samplers[i].get_stepsize_adaptation().set_kappa(kappa); - samplers[i].get_stepsize_adaptation().set_t0(t0); - samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, - window, logger); - } - } catch (const std::domain_error& e) { - return error_codes::CONFIG; + samplers[i].get_stepsize_adaptation().set_mu(log(10 * stepsize)); + samplers[i].get_stepsize_adaptation().set_delta(delta); + samplers[i].get_stepsize_adaptation().set_gamma(gamma); + samplers[i].get_stepsize_adaptation().set_kappa(kappa); + samplers[i].get_stepsize_adaptation().set_t0(t0); + samplers[i].set_window_params(num_warmup, init_buffer, term_buffer, + window, logger); } - tbb::parallel_for( - tbb::blocked_range(0, num_chains, 1), - [num_warmup, num_samples, num_thin, refresh, save_warmup, num_chains, - init_chain_id, &samplers, &model, &rngs, &interrupt, &logger, - &sample_writer, &cont_vectors, - &diagnostic_writer](const tbb::blocked_range& r) { - for (size_t i = r.begin(); i != r.end(); ++i) { - util::run_adaptive_sampler( - samplers[i], model, cont_vectors[i], num_warmup, num_samples, - num_thin, refresh, save_warmup, rngs[i], interrupt, logger, - sample_writer[i], diagnostic_writer[i], init_chain_id + i, - num_chains); - } - }, - tbb::simple_partitioner()); - return error_codes::OK; - + } catch (const std::domain_error& e) { + return error_codes::CONFIG; + } + tbb::parallel_for(tbb::blocked_range(0, num_chains, 1), + [num_warmup, num_samples, num_thin, refresh, save_warmup, + num_chains, init_chain_id, &samplers, &model, &rngs, + &interrupt, &logger, &sample_writer, &cont_vectors, + &diagnostic_writer](const tbb::blocked_range& r) { + for (size_t i = r.begin(); i != r.end(); ++i) { + util::run_adaptive_sampler( + samplers[i], model, cont_vectors[i], num_warmup, + num_samples, num_thin, refresh, save_warmup, + rngs[i], interrupt, logger, sample_writer[i], + diagnostic_writer[i], init_chain_id + i, + num_chains); + } + }, + tbb::simple_partitioner()); + return error_codes::OK; } /** @@ -346,18 +345,18 @@ int hmc_nuts_diag_e_adapt( interrupt, logger, init_writer[0], sample_writer[0], diagnostic_writer[0]); } - std::vector> unit_e_metrics; - unit_e_metrics.reserve(num_chains); - for (size_t i = 0; i < num_chains; ++i) { - unit_e_metrics.emplace_back(std::make_unique( - util::create_unit_e_diag_inv_metric(model.num_params_r()))); - } - return hmc_nuts_diag_e_adapt( - model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, - init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, - stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, - init_buffer, term_buffer, window, interrupt, logger, init_writer, - sample_writer, diagnostic_writer); + std::vector> unit_e_metrics; + unit_e_metrics.reserve(num_chains); + for (size_t i = 0; i < num_chains; ++i) { + unit_e_metrics.emplace_back(std::make_unique( + util::create_unit_e_diag_inv_metric(model.num_params_r()))); + } + return hmc_nuts_diag_e_adapt( + model, num_chains, init, unit_e_metrics, random_seed, init_chain_id, + init_radius, num_warmup, num_samples, num_thin, save_warmup, refresh, + stepsize, stepsize_jitter, max_depth, delta, gamma, kappa, t0, + init_buffer, term_buffer, window, interrupt, logger, init_writer, + sample_writer, diagnostic_writer); } } // namespace sample diff --git a/src/stan/services/util/create_rng.hpp b/src/stan/services/util/create_rng.hpp index 39f8e4ce9be..d63d6c79f1b 100644 --- a/src/stan/services/util/create_rng.hpp +++ b/src/stan/services/util/create_rng.hpp @@ -7,28 +7,28 @@ namespace stan { namespace services { namespace util { - /** - * Creates a pseudo random number generator from a random seed - * and a chain id by initializing the PRNG with the seed and - * then advancing past pow(2, 50) times the chain ID draws to - * ensure different chains sample from different segments of the - * pseudo random number sequence. - * - * Chain IDs should be kept to larger values than one to ensure - * that the draws used to initialized transformed data are not - * duplicated. - * - * @param[in] seed the random seed - * @param[in] chain the chain id - * @return a boost::ecuyer1988 instance - */ - inline boost::ecuyer1988 create_rng(unsigned int seed, unsigned int chain) { - using boost::uintmax_t; - static constexpr uintmax_t DISCARD_STRIDE = static_cast(1) << 50; - boost::ecuyer1988 rng(seed); - rng.discard(DISCARD_STRIDE * chain); - return rng; - } +/** + * Creates a pseudo random number generator from a random seed + * and a chain id by initializing the PRNG with the seed and + * then advancing past pow(2, 50) times the chain ID draws to + * ensure different chains sample from different segments of the + * pseudo random number sequence. + * + * Chain IDs should be kept to larger values than one to ensure + * that the draws used to initialized transformed data are not + * duplicated. + * + * @param[in] seed the random seed + * @param[in] chain the chain id + * @return a boost::ecuyer1988 instance + */ +inline boost::ecuyer1988 create_rng(unsigned int seed, unsigned int chain) { + using boost::uintmax_t; + static constexpr uintmax_t DISCARD_STRIDE = static_cast(1) << 50; + boost::ecuyer1988 rng(seed); + rng.discard(DISCARD_STRIDE * chain); + return rng; +} } // namespace util } // namespace services diff --git a/src/stan/services/util/run_adaptive_sampler.hpp b/src/stan/services/util/run_adaptive_sampler.hpp index ea0f3452225..7115b138fc3 100644 --- a/src/stan/services/util/run_adaptive_sampler.hpp +++ b/src/stan/services/util/run_adaptive_sampler.hpp @@ -71,7 +71,8 @@ void run_adaptive_sampler(Sampler& sampler, Model& model, auto start_warm = std::chrono::steady_clock::now(); util::generate_transitions(sampler, num_warmup, 0, num_warmup + num_samples, num_thin, refresh, save_warmup, true, writer, s, - model, rng, interrupt, logger, chain_id, num_chains); + model, rng, interrupt, logger, chain_id, + num_chains); auto end_warm = std::chrono::steady_clock::now(); double warm_delta_t = std::chrono::duration_cast( end_warm - start_warm)