From cef5a55ef6ee60148ff9148fcc70e288cc67950f Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 2 Mar 2026 14:44:06 -0500 Subject: [PATCH 1/5] Add timing information to standalone GQ --- src/stan/services/sample/standalone_gqs.hpp | 17 ++++++++++ src/stan/services/util/gq_writer.hpp | 34 +++++++++++++++++++ .../unit/services/util/gq_writer_test.cpp | 11 ++++++ 3 files changed, 62 insertions(+) diff --git a/src/stan/services/sample/standalone_gqs.hpp b/src/stan/services/sample/standalone_gqs.hpp index c792acd08f1..f7091be981d 100644 --- a/src/stan/services/sample/standalone_gqs.hpp +++ b/src/stan/services/sample/standalone_gqs.hpp @@ -67,6 +67,8 @@ int standalone_generate(const Model &model, const Eigen::MatrixXd &draws, std::vector unconstrained_params_r; std::vector row(draws.cols()); + auto start = std::chrono::steady_clock::now(); + try { for (size_t i = 0; i < draws.rows(); ++i) { Eigen::Map(&row[0], draws.cols()) = draws.row(i); @@ -85,6 +87,13 @@ int standalone_generate(const Model &model, const Eigen::MatrixXd &draws, logger.error(e.what()); return error_codes::SOFTWARE; } + auto end = std::chrono::steady_clock::now(); + double gq_delta_t + = std::chrono::duration_cast(end - start) + .count() + / 1000.0; + writer.write_timing(gq_delta_t); + return error_codes::OK; } @@ -161,6 +170,7 @@ int standalone_generate(const Model &model, const int num_chains, std::stringstream msg; for (size_t slice_idx = r.begin(); slice_idx != r.end(); ++slice_idx) { + auto start = std::chrono::steady_clock::now(); for (size_t i = 0; i < draws[slice_idx].rows(); ++i) { if (error_any) return; @@ -178,6 +188,13 @@ int standalone_generate(const Model &model, const int num_chains, writers[slice_idx].write_gq_values(model, rngs[slice_idx], unconstrained_params_r); } + auto end = std::chrono::steady_clock::now(); + double gq_delta_t + = std::chrono::duration_cast(end + - start) + .count() + / 1000.0; + writers[slice_idx].write_timing(gq_delta_t); } }, tbb::simple_partitioner()); diff --git a/src/stan/services/util/gq_writer.hpp b/src/stan/services/util/gq_writer.hpp index 5cb8e6eb78a..54d52358f69 100644 --- a/src/stan/services/util/gq_writer.hpp +++ b/src/stan/services/util/gq_writer.hpp @@ -16,6 +16,28 @@ namespace stan { namespace services { namespace util { +namespace internal { + +/** + * Internal method + * + * Logs timing information + * + * @param[in] deltaT time in seconds + */ +template +void write_timing(double deltaT, F writer) { + std::string title(" Elapsed Time: "); + writer(""); + + std::stringstream ss1; + ss1 << title << deltaT << " seconds (Generated Quantities)"; + writer(ss1.str()); + + writer(""); +} +} // namespace internal + /** * gq_writer writes out * @@ -128,6 +150,18 @@ class gq_writer { } sample_writer_(values); } + + /** + * Print timing information to all streams + * + * @param[in] deltaT time in seconds + */ + void write_timing(double deltaT) { + internal::write_timing( + deltaT, [this](const std::string& msg) { this->sample_writer_(msg); }); + internal::write_timing( + deltaT, [this](const std::string& msg) { this->logger_.info(msg); }); + } }; } // namespace util diff --git a/src/test/unit/services/util/gq_writer_test.cpp b/src/test/unit/services/util/gq_writer_test.cpp index 7b3017887ad..56b31085af0 100644 --- a/src/test/unit/services/util/gq_writer_test.cpp +++ b/src/test/unit/services/util/gq_writer_test.cpp @@ -46,6 +46,17 @@ TEST_F(ServicesUtilGQWriter, t2) { EXPECT_EQ(count_matches("nan", sample_ss.str()), 0); } +TEST_F(ServicesUtilGQWriter, timing) { + stan::callbacks::stream_writer sample_writer(sample_ss, "#"); + stan::callbacks::stream_logger logger(logger_ss, logger_ss, logger_ss, + logger_ss, logger_ss); + stan::services::util::gq_writer writer(sample_writer, logger, 2); + writer.write_timing(4.31); + // model test_gq.stan generates 4 values, 3 commas + EXPECT_EQ(count_matches("4.31 seconds", logger_ss.str()), 1); + EXPECT_EQ(count_matches("4.31 seconds", sample_ss.str()), 1) << sample_ss.str(); +} + TEST_F(ServicesUtilGQWriter, TestExceptions) { stan::callbacks::stream_writer sample_writer(sample_ss, ""); stan::callbacks::stream_logger logger(logger_ss, logger_ss, logger_ss, From c2b5aa860a771ae3a8f600cafb0a29bdc88b8024 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 2 Mar 2026 14:53:12 -0500 Subject: [PATCH 2/5] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/test/unit/services/util/gq_writer_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/unit/services/util/gq_writer_test.cpp b/src/test/unit/services/util/gq_writer_test.cpp index 56b31085af0..2a3bd7885eb 100644 --- a/src/test/unit/services/util/gq_writer_test.cpp +++ b/src/test/unit/services/util/gq_writer_test.cpp @@ -54,7 +54,8 @@ TEST_F(ServicesUtilGQWriter, timing) { writer.write_timing(4.31); // model test_gq.stan generates 4 values, 3 commas EXPECT_EQ(count_matches("4.31 seconds", logger_ss.str()), 1); - EXPECT_EQ(count_matches("4.31 seconds", sample_ss.str()), 1) << sample_ss.str(); + EXPECT_EQ(count_matches("4.31 seconds", sample_ss.str()), 1) + << sample_ss.str(); } TEST_F(ServicesUtilGQWriter, TestExceptions) { From 069f5923212ae4c4c86c35f3472d86c6a914db17 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 2 Mar 2026 15:24:43 -0500 Subject: [PATCH 3/5] Update standalone_gqs_test.cpp --- src/test/unit/services/sample/standalone_gqs_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/unit/services/sample/standalone_gqs_test.cpp b/src/test/unit/services/sample/standalone_gqs_test.cpp index da4bda0ca86..653b063e840 100644 --- a/src/test/unit/services/sample/standalone_gqs_test.cpp +++ b/src/test/unit/services/sample/standalone_gqs_test.cpp @@ -55,7 +55,7 @@ TEST_F(ServicesStandaloneGQ, genDraws_bernoulli) { EXPECT_EQ(return_code, stan::services::error_codes::OK); EXPECT_EQ(count_matches("mu", sample_ss.str()), 1); EXPECT_EQ(count_matches("y_rep", sample_ss.str()), 10); - EXPECT_EQ(count_matches("\n", sample_ss.str()), 1001); + EXPECT_EQ(count_matches("\n", sample_ss.str()), 1004); match_csv_columns(bern_csv.samples, sample_ss.str(), 1000, 1, 8); } From fac4726819ee6498275eac4443eec6e5c7db0031 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 2 Mar 2026 16:02:14 -0500 Subject: [PATCH 4/5] Update standalone_gqs_parallel_test.cpp --- src/test/unit/services/sample/standalone_gqs_parallel_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/unit/services/sample/standalone_gqs_parallel_test.cpp b/src/test/unit/services/sample/standalone_gqs_parallel_test.cpp index 3dbe943bb8e..60ab35ff391 100644 --- a/src/test/unit/services/sample/standalone_gqs_parallel_test.cpp +++ b/src/test/unit/services/sample/standalone_gqs_parallel_test.cpp @@ -74,7 +74,7 @@ TEST_F(ServicesStandaloneGQ, genDraws_bernoulli) { for (int i = 0; i < num_chains; i++) { EXPECT_EQ(count_matches("mu", sample_ss[i].str()), 1); EXPECT_EQ(count_matches("y_rep", sample_ss[i].str()), 10); - EXPECT_EQ(count_matches("\n", sample_ss[i].str()), 1001); + EXPECT_EQ(count_matches("\n", sample_ss[i].str()), 1004); match_csv_columns(bern_csv.samples, sample_ss[i].str(), 1000, 1, 8); } } From b564dbf650fb99d32421bd49ad982adb938cba22 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 2 Mar 2026 16:40:13 -0500 Subject: [PATCH 5/5] More test changes --- src/test/unit/services/sample/standalone_gqs_2390_test.cpp | 2 +- src/test/unit/services/sample/standalone_gqs_multidim_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/unit/services/sample/standalone_gqs_2390_test.cpp b/src/test/unit/services/sample/standalone_gqs_2390_test.cpp index 2cc6404b628..7b8e6ddfbb1 100644 --- a/src/test/unit/services/sample/standalone_gqs_2390_test.cpp +++ b/src/test/unit/services/sample/standalone_gqs_2390_test.cpp @@ -48,6 +48,6 @@ TEST_F(ServicesStandaloneGQ4, genDraws_gq_test_vec_len_1) { sample_writer); EXPECT_EQ(return_code, stan::services::error_codes::OK); EXPECT_EQ(count_matches("y_est", sample_ss.str()), 5); - EXPECT_EQ(count_matches("\n", sample_ss.str()), 1001); + EXPECT_EQ(count_matches("\n", sample_ss.str()), 1004); match_csv_columns(multidim_csv.samples, sample_ss.str(), 1000, 0, 6); } diff --git a/src/test/unit/services/sample/standalone_gqs_multidim_test.cpp b/src/test/unit/services/sample/standalone_gqs_multidim_test.cpp index e45b19ff249..a398d0dc7f7 100644 --- a/src/test/unit/services/sample/standalone_gqs_multidim_test.cpp +++ b/src/test/unit/services/sample/standalone_gqs_multidim_test.cpp @@ -55,6 +55,6 @@ TEST_F(ServicesStandaloneGQ2, genDraws_gq_test_multidim) { sample_writer); EXPECT_EQ(return_code, stan::services::error_codes::OK); EXPECT_EQ(count_matches("gq_ar_mat", sample_ss.str()), 120); - EXPECT_EQ(count_matches("\n", sample_ss.str()), 1001); + EXPECT_EQ(count_matches("\n", sample_ss.str()), 1004); match_csv_columns(multidim_csv.samples, sample_ss.str(), 1000, 120, 127); }