From 1dd0d96554ec4f0a935154895e4a07c66a3f5dea Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Mon, 26 May 2025 13:38:32 +0200 Subject: [PATCH 1/2] Synchronization algorithm no longer a boolean Currently, you can switch between a serial or parallel/distributed run. If we want to support additional synchronization algorithms, a boolean is not enough. This commit introduces an enum that allows specifying what is the synchronization algorithm that a user wants to use. Signed-off-by: Alessandro Pellegrini --- src/CMakeLists.txt | 2 +- src/ROOT-Sim.h | 12 ++++++- src/gvt/termination.c | 2 +- src/init.c | 31 ++++++++++++++----- src/lp/process.c | 2 +- src/parallel/{parallel.c => timewarp.c} | 0 test/CMakeLists.txt | 2 +- test/core/load.c | 27 ++++++++++++++-- test/gvt/termination.c | 4 +-- test/integration/correctness/serial.c | 2 +- .../correctness/{parallel.c => timewarp.c} | 2 +- test/integration/phold.c | 2 +- test/log/stats.c | 2 +- test/mock.c | 2 +- test/visibility/visibility_override.c | 2 +- 15 files changed, 71 insertions(+), 23 deletions(-) rename src/parallel/{parallel.c => timewarp.c} (100%) rename test/integration/correctness/{parallel.c => timewarp.c} (95%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6bb518d1..27f3d7d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,7 +22,7 @@ set(rscore_srcs mm/buddy/ckpt.c mm/buddy/multi.c mm/msg_allocator.c - parallel/parallel.c + parallel/timewarp.c serial/serial.c) if(MPI_FOUND) diff --git a/src/ROOT-Sim.h b/src/ROOT-Sim.h index 821ce46a..4c030291 100644 --- a/src/ROOT-Sim.h +++ b/src/ROOT-Sim.h @@ -103,6 +103,11 @@ enum log_level { LOG_SILENT //!< Emit no message during the simulation }; +enum synchronization_algorithm { + SERIAL = 1, //!< The simulation runs on the serial runtime + TIME_WARP, //!< The simulation runs using the optimistic Time Warp algorithm +}; + /// A set of configurable values used by other modules struct simulation_configuration { /// The number of LPs to be used in the simulation @@ -123,7 +128,12 @@ struct simulation_configuration { unsigned ckpt_interval; /// If set, worker threads are bound to physical cores bool core_binding; - /// If set, the simulation will run on the serial runtime + /// Specify what synchronization algorithm we are using + enum synchronization_algorithm synchronization; + /** + * @deprecated since 3.1.0 + * If set, the simulation will run on the serial runtime + */ bool serial; /// Function pointer to the dispatching function ProcessEvent_t dispatcher; diff --git a/src/gvt/termination.c b/src/gvt/termination.c index e4a6ed9b..58aed922 100644 --- a/src/gvt/termination.c +++ b/src/gvt/termination.c @@ -85,7 +85,7 @@ void termination_on_gvt(simtime_t current_gvt) */ void RootsimStop(void) { - if(global_config.serial) { + if(global_config.synchronization == SERIAL) { global_config.termination_time = -1.0; return; } diff --git a/src/init.c b/src/init.c index ec4a11af..783a03c7 100644 --- a/src/init.c +++ b/src/init.c @@ -54,14 +54,21 @@ static void print_config(void) else fprintf(stderr, "%lf\n", global_config.termination_time); - if(global_config.serial) { - fprintf(stderr, "Parallelism: sequential simulation\n"); - } else { + switch (global_config.synchronization) { + case SERIAL: + fprintf(stderr, "Parallelism: sequential simulation\n"); + break; + case TIME_WARP: + fprintf(stderr, "Parallelism: optimistic synchronization\n"); + break; + } + if (global_config.synchronization != SERIAL) { if(n_nodes > 1) fprintf(stderr, "Parallelism: %d MPI processes\n", n_nodes); else fprintf(stderr, "Parallelism: %u threads\n", global_config.n_threads); } + fprintf(stderr, "Thread-to-core binding: %s\n", global_config.core_binding ? "enabled" : "disabled"); fprintf(stderr, "GVT period: %u ms\n", global_config.gvt_period / 1000); @@ -69,7 +76,7 @@ static void print_config(void) if(global_config.ckpt_interval) { fprintf(stderr, "Checkpoint interval: %u events\n", global_config.ckpt_interval); } else { - if(!global_config.serial) + if(global_config.synchronization != SERIAL) fprintf(stderr, "Checkpoint interval: auto\n"); } @@ -108,9 +115,19 @@ int RootsimInit(const struct simulation_configuration *conf) return -1; } + if (global_config.serial) { + fprintf(stderr, "Using the deprecated `serial` configuration flag. Please swith to `.synchronization = SERIAL` instead\n"); + global_config.synchronization = SERIAL; + } + + if (unlikely(global_config.synchronization == 0)) { + fprintf(stderr, "No synchronization algorithm specified.\n"); + return -1; + } + log_init(global_config.logfile); - if (global_config.serial) + if (global_config.synchronization == SERIAL) global_config.n_threads = 1; else if (global_config.n_threads == 0) global_config.n_threads = thread_cores_count(); @@ -138,7 +155,7 @@ int RootsimRun(void) if(!configuration_done) return -1; - if(!global_config.serial) + if(global_config.synchronization == TIME_WARP) mpi_global_init(NULL, NULL); if(global_config.log_level < LOG_SILENT && !rid) { @@ -146,7 +163,7 @@ int RootsimRun(void) print_config(); } - if(global_config.serial) { + if(global_config.synchronization == SERIAL) { ret = serial_simulation(); } else { ret = parallel_simulation(); diff --git a/src/lp/process.c b/src/lp/process.c index 0d059127..f2d1cf8f 100644 --- a/src/lp/process.c +++ b/src/lp/process.c @@ -38,7 +38,7 @@ static __thread struct lp_msg *current_msg; void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp, unsigned event_type, const void *payload, unsigned payload_size) { - if(unlikely(global_config.serial)) { + if(unlikely(global_config.synchronization == SERIAL)) { ScheduleNewEvent_serial(receiver, timestamp, event_type, payload, payload_size); return; } diff --git a/src/parallel/parallel.c b/src/parallel/timewarp.c similarity index 100% rename from src/parallel/parallel.c rename to src/parallel/timewarp.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 84b6efd4..d1db9671 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -46,7 +46,7 @@ test_program_link_libraries(sync rscore) # Integration tests test_program(correctness_serial integration/correctness/serial.c integration/correctness/application.c integration/correctness/functions.c integration/correctness/output_256.c) test_program_link_libraries(correctness_serial rscore) -test_program(correctness_parallel integration/correctness/parallel.c integration/correctness/application.c integration/correctness/functions.c integration/correctness/output_256.c) +test_program(correctness_parallel integration/correctness/timewarp.c integration/correctness/application.c integration/correctness/functions.c integration/correctness/output_256.c) test_program_link_libraries(correctness_parallel rscore) test_program(phold integration/phold.c) test_program_link_libraries(phold rscore) diff --git a/test/core/load.c b/test/core/load.c index 4b75ec9b..962044e0 100644 --- a/test/core/load.c +++ b/test/core/load.c @@ -27,10 +27,24 @@ static struct simulation_configuration conf = { .committed = NULL, }; +static const struct simulation_configuration no_synchronization = { + .lps = 1, + .dispatcher = DummyProcessEvent, + .committed = DummyCanEnd, +}; + static const struct simulation_configuration valid_conf = { - .lps = 1, - .dispatcher = DummyProcessEvent, - .committed = DummyCanEnd, + .lps = 1, + .dispatcher = DummyProcessEvent, + .committed = DummyCanEnd, + .synchronization = TIME_WARP, +}; + +static const struct simulation_configuration deprecated_conf = { + .lps = 1, + .dispatcher = DummyProcessEvent, + .committed = DummyCanEnd, + .serial = true, }; static int run_rootsim(_unused void *_) @@ -62,6 +76,13 @@ int main(void) test_xf("CanEnd not set", init_rootsim, &conf); test_xf("Start simulation with no CanEnd", run_rootsim, NULL); + memcpy(&conf, &no_synchronization, sizeof(conf)); + test_xf("No synchronization algorithm", init_rootsim, &conf); + test_xf("Start simulation with no synchronization algorithm", run_rootsim, NULL); + + memcpy(&conf, &deprecated_conf, sizeof(conf)); + test("Legacy serial flag", init_rootsim, &conf); + memcpy(&conf, &valid_conf, sizeof(conf)); test("Initialization", init_rootsim, &conf); test("Dummy simulation", run_rootsim, NULL); diff --git a/test/gvt/termination.c b/test/gvt/termination.c index acae09fd..66613e8e 100644 --- a/test/gvt/termination.c +++ b/test/gvt/termination.c @@ -30,10 +30,10 @@ static bool DummyCanEnd(_unused lp_id_t lid, _unused const void *state) } static struct simulation_configuration serial_conf = { - .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .serial = true}; + .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .synchronization = SERIAL}; static struct simulation_configuration parallel_conf = { - .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .serial = false}; + .lps = 1, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, .synchronization = TIME_WARP}; static int force_termination_test(void *conf) { diff --git a/test/integration/correctness/serial.c b/test/integration/correctness/serial.c index 66a72209..1e79fa13 100644 --- a/test/integration/correctness/serial.c +++ b/test/integration/correctness/serial.c @@ -19,7 +19,7 @@ struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = false, - .serial = true, + .synchronization = SERIAL, .dispatcher = ProcessEvent, .committed = CanEnd, }; diff --git a/test/integration/correctness/parallel.c b/test/integration/correctness/timewarp.c similarity index 95% rename from test/integration/correctness/parallel.c rename to test/integration/correctness/timewarp.c index 1766aadd..adde2f7f 100644 --- a/test/integration/correctness/parallel.c +++ b/test/integration/correctness/timewarp.c @@ -19,7 +19,7 @@ struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = false, - .serial = false, + .synchronization = TIME_WARP, .dispatcher = ProcessEvent, .committed = CanEnd, }; diff --git a/test/integration/phold.c b/test/integration/phold.c index a5bbfaad..8b931329 100644 --- a/test/integration/phold.c +++ b/test/integration/phold.c @@ -106,7 +106,7 @@ struct simulation_configuration conf = { .stats_file = "phold", .ckpt_interval = 0, .core_binding = true, - .serial = false, + .synchronization = TIME_WARP, .dispatcher = ProcessEvent, .committed = CanEnd, }; diff --git a/test/log/stats.c b/test/log/stats.c index 3963db4e..ba98998a 100644 --- a/test/log/stats.c +++ b/test/log/stats.c @@ -39,7 +39,7 @@ static struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = true, - .serial = false, + .synchronization = SERIAL, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, }; diff --git a/test/mock.c b/test/mock.c index 239ada10..437464e4 100644 --- a/test/mock.c +++ b/test/mock.c @@ -1,5 +1,5 @@ /** -* @file test/framework/mock.c +* @file test/mock.c * * @brief Mocking module * diff --git a/test/visibility/visibility_override.c b/test/visibility/visibility_override.c index 7127acab..171d8595 100644 --- a/test/visibility/visibility_override.c +++ b/test/visibility/visibility_override.c @@ -1,5 +1,5 @@ /** - * @file test/tests/visibility/visibility_override.c + * @file test/visibility/visibility_override.c * * @brief Test: accessing a weak symbol that is overridden * From 989d08a3338d9e7ca159033d3588876efc2ded63 Mon Sep 17 00:00:00 2001 From: Alessandro Pellegrini Date: Wed, 25 Jun 2025 19:48:45 +0200 Subject: [PATCH 2/2] Realign statistics parsing test The test was expecting to find a parallel simulation configuration, but a sequential one was incorrectly configured. Signed-off-by: Alessandro Pellegrini --- test/log/rootsim_stats_test.py | 1 + test/log/stats.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/log/rootsim_stats_test.py b/test/log/rootsim_stats_test.py index 618fca46..79d3e6ee 100644 --- a/test/log/rootsim_stats_test.py +++ b/test/log/rootsim_stats_test.py @@ -99,6 +99,7 @@ def test_stats_file(base_name, expected): if float(match[i + 1]) == 0: sys.exit(1) elif expected_field != match[i + 1]: + print(f"Error in {base_name} at field {i + 1}: expected '{expected_field}', got '{match[i + 1]}'") sys.exit(1) diff --git a/test/log/stats.c b/test/log/stats.c index a496af16..7cd37b8c 100644 --- a/test/log/stats.c +++ b/test/log/stats.c @@ -39,7 +39,7 @@ static struct simulation_configuration conf = { .stats_file = NULL, .ckpt_interval = 0, .core_binding = true, - .synchronization = SERIAL, + .synchronization = TIME_WARP, .dispatcher = DummyProcessEvent, .committed = DummyCanEnd, };