From fcb277db16686796040d2ee424078905943f8697 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Fri, 19 Jun 2026 10:03:50 -0400 Subject: [PATCH 1/3] Fix DDS_SCHEDULER build consistency and dtest -r reporting. Propagate scheduler define through :dds to fix Scheduler ODR/crash; use SolveAllBoards for parallel solve timing; clarify calc has no per-board data. Co-authored-by: Cursor --- library/src/BUILD.bazel | 10 +++++----- library/src/init.cpp | 3 --- library/tests/loop.cpp | 15 +-------------- library/tests/testcommon.cpp | 10 +++++++++- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/library/src/BUILD.bazel b/library/src/BUILD.bazel index 730bc3b7..f74cedaf 100644 --- a/library/src/BUILD.bazel +++ b/library/src/BUILD.bazel @@ -1,4 +1,4 @@ -load("//:CPPVARIABLES.bzl", "DDS_CPPOPTS", "DDS_LINKOPTS", "DDS_LOCAL_DEFINES") +load("//:CPPVARIABLES.bzl", "DDS_CPPOPTS", "DDS_LINKOPTS", "DDS_LOCAL_DEFINES", "DDS_SCHEDULER_DEFINE") load("@rules_cc//cc:defs.bzl", "cc_library") external_headers = [ @@ -29,7 +29,7 @@ cc_library( includes = ["."], copts = DDS_CPPOPTS, linkopts = DDS_LINKOPTS, - local_defines = DDS_LOCAL_DEFINES, + local_defines = DDS_LOCAL_DEFINES + DDS_SCHEDULER_DEFINE, visibility = ["//visibility:public"], include_prefix = "dds", deps = [ @@ -71,7 +71,7 @@ cc_library( includes = ["."], copts = DDS_CPPOPTS, linkopts = DDS_LINKOPTS, - local_defines = DDS_LOCAL_DEFINES, + local_defines = DDS_LOCAL_DEFINES + DDS_SCHEDULER_DEFINE, include_prefix = "dds", visibility = [ "//:__pkg__", # allow root package to wrap/export @@ -103,7 +103,7 @@ cc_library( includes = ["."], copts = DDS_CPPOPTS, linkopts = DDS_LINKOPTS, - local_defines = DDS_LOCAL_DEFINES, + local_defines = DDS_LOCAL_DEFINES + DDS_SCHEDULER_DEFINE, include_prefix = "dds", visibility = [ "//:__pkg__", @@ -128,7 +128,7 @@ cc_library( includes = ["."], copts = DDS_CPPOPTS, linkopts = DDS_LINKOPTS, - local_defines = DDS_LOCAL_DEFINES, + local_defines = DDS_LOCAL_DEFINES + DDS_SCHEDULER_DEFINE, include_prefix = "dds", visibility = [ "//:__pkg__", diff --git a/library/src/init.cpp b/library/src/init.cpp index 27243514..fc687bc9 100644 --- a/library/src/init.cpp +++ b/library/src/init.cpp @@ -157,9 +157,6 @@ int STDCALL SetThreading( void InitDebugFiles() { -#ifdef DDS_SCHEDULER - InitFileScheduler(); -#endif } diff --git a/library/tests/loop.cpp b/library/tests/loop.cpp index ecc6b4eb..5db5e3bf 100644 --- a/library/tests/loop.cpp +++ b/library/tests/loop.cpp @@ -68,20 +68,7 @@ void loop_solve( } else { - solvedbdp->no_of_boards = count; - ret = dtest_run_parallel(count, options.num_threads_, - [&](const int j) -> int { - FutureTricks fut; - const int res = SolveBoardPBN( - bop->deals[j], bop->target[j], bop->solutions[j], bop->mode[j], - &fut, 0); - if (res == RETURN_NO_FAULT) - { - solvedbdp->solved_board[j] = fut; - return RETURN_NO_FAULT; - } - return res; - }); + ret = SolveAllBoards(bop, solvedbdp); } if (ret != RETURN_NO_FAULT) { diff --git a/library/tests/testcommon.cpp b/library/tests/testcommon.cpp index 3853f383..efc36dec 100644 --- a/library/tests/testcommon.cpp +++ b/library/tests/testcommon.cpp @@ -153,7 +153,15 @@ int real_main([[maybe_unused]] int argc, [[maybe_unused]] char * argv[]) scheduler.GetBoardTimes(times); if (times.empty()) { - cout << "Per-board timing data not available. Rebuild with DDS_SCHEDULER enabled to collect per-board timings." << std::endl; + if (options.solver_ == Solver::DTEST_SOLVER_CALC) + { + cout << "Per-board timing data not available for calc (use -s solve -r)." + << std::endl; + } + else + { + cout << "Per-board timing data not available." << std::endl; + } } else { From ad84222fee02ada27477b4223da0380241574165 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Fri, 19 Jun 2026 10:34:30 -0400 Subject: [PATCH 2/3] Initialize scheduler timing state and gate EndBlockTimer aggregation. Zero hands[]/group[] timing fields in Reset() and skip group/per-hand stats unless populated by the GetNumber dispatcher path. Co-authored-by: Cursor --- library/src/system/scheduler.cpp | 35 +++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/library/src/system/scheduler.cpp b/library/src/system/scheduler.cpp index fffcb180..09ad1add 100644 --- a/library/src/system/scheduler.cpp +++ b/library/src/system/scheduler.cpp @@ -135,7 +135,24 @@ void Scheduler::ClearTiming() void Scheduler::Reset() { for (int b = 0; b < MAXNOOFBOARDS; b++) + { hands[b].next = -1; + hands[b].repeatNo = 0; + hands[b].depth = 0; + hands[b].strength = 0; + hands[b].fanout = 0; + hands[b].thread = 0; + hands[b].selectFlag = 0; + hands[b].time = 0; + } + + for (int g = 0; g < MAXNOOFBOARDS; g++) + { + group[g].head = -1; + group[g].actual = 0; + group[g].repeatNo = 0; + group[g].pred = 0; + } numGroups = 0; extraGroups = 0; @@ -266,6 +283,9 @@ void Scheduler::MakeGroups(const Boards& bds) group[numGroups].strain = strain; group[numGroups].hash = key; + group[numGroups].head = -1; + group[numGroups].actual = 0; + group[numGroups].repeatNo = 0; numGroups++; } else @@ -332,6 +352,9 @@ void Scheduler::FinetuneGroups() group[numGroups].strain = 5; group[numGroups].hash = extraGroups; + group[numGroups].head = -1; + group[numGroups].actual = 0; + group[numGroups].repeatNo = 0; numGroups++; extraGroups++; @@ -422,6 +445,9 @@ void Scheduler::FinetuneGroups() group[numGroups].strain = 5; group[numGroups].hash = extraGroups; + group[numGroups].head = -1; + group[numGroups].actual = 0; + group[numGroups].repeatNo = 0; numGroups++; extraGroups++; @@ -903,7 +929,7 @@ void Scheduler::EndBlockTimer() if (timeUser > blockMax) blockMax = timeUser; - if (hp->repeatNo == 0) + if (hp->repeatNo == 0 && timeUser > 0) { int bin = timeUser / 1000; timeHist[bin]++; @@ -916,8 +942,11 @@ void Scheduler::EndBlockTimer() for (int g = 0; g < numGroups; g++) { - int head = group[g].head; - int NTflag = (hands[head].strain == 4 ? 1 : 0); + const int head = group[g].head; + if (head < 0 || head >= numHands) + continue; + + const int NTflag = (hands[head].strain == 4 ? 1 : 0); TimeStat ts; From 90814283df15a1373d22d976cedd684018f99385 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Fri, 19 Jun 2026 12:08:50 -0400 Subject: [PATCH 3/3] Respect dtest thread limit in parallel solve while keeping per-board timing. Add worker_cap to solve_all_boards_n/pbn_n so loop_solve passes options.num_threads_ instead of always using hardware concurrency. Co-authored-by: Cursor --- library/src/solve_board.cpp | 102 ++++++++++++++++++------------------ library/src/solve_board.hpp | 10 ++++ library/tests/loop.cpp | 4 +- 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/library/src/solve_board.cpp b/library/src/solve_board.cpp index d57b8807..edd78abb 100644 --- a/library/src/solve_board.cpp +++ b/library/src/solve_board.cpp @@ -29,9 +29,41 @@ auto same_board( const unsigned index2) -> bool; +static auto boards_from_pbn( + BoardsPBN const& bop, + Boards& bo) -> int +{ + bo.no_of_boards = bop.no_of_boards; + if (bo.no_of_boards > MAXNOOFBOARDS) + return RETURN_TOO_MANY_BOARDS; + + for (int k = 0; k < bop.no_of_boards; k++) + { + bo.mode[k] = bop.mode[k]; + bo.solutions[k] = bop.solutions[k]; + bo.target[k] = bop.target[k]; + bo.deals[k].first = bop.deals[k].first; + bo.deals[k].trump = bop.deals[k].trump; + + for (int i = 0; i <= 2; i++) + { + bo.deals[k].currentTrickSuit[i] = bop.deals[k].currentTrickSuit[i]; + bo.deals[k].currentTrickRank[i] = bop.deals[k].currentTrickRank[i]; + } + + if (convert_from_pbn(bop.deals[k].remainCards, bo.deals[k].remainCards) + != RETURN_NO_FAULT) + return RETURN_PBN_FAULT; + } + + return RETURN_NO_FAULT; +} + + auto solve_all_boards_n( Boards const& bds, - SolvedBoards& solved) -> int + SolvedBoards& solved, + const int worker_cap) -> int { const int n = bds.no_of_boards; if (n > MAXNOOFBOARDS) @@ -44,7 +76,7 @@ auto solve_all_boards_n( START_BLOCK_TIMER; - const int err = parallel_all_boards_n(n, 0, + const int err = parallel_all_boards_n(n, worker_cap, [&](const int worker_id, const int bno) -> int { (void)worker_id; @@ -78,6 +110,19 @@ auto solve_all_boards_n( } +auto solve_all_boards_pbn_n( + BoardsPBN const& bop, + SolvedBoards& solved, + const int worker_cap) -> int +{ + Boards bo; + const int rc = boards_from_pbn(bop, bo); + if (rc != RETURN_NO_FAULT) + return rc; + return solve_all_boards_n(bo, solved, worker_cap); +} + + /* * Solve a single bridge Deal in PBN format. * @@ -121,32 +166,7 @@ int STDCALL SolveAllBoards( BoardsPBN const * bop, SolvedBoards * solvedp) { - Boards bo; - bo.no_of_boards = bop->no_of_boards; - if (bo.no_of_boards > MAXNOOFBOARDS) - return RETURN_TOO_MANY_BOARDS; - - for (int k = 0; k < bop->no_of_boards; k++) - { - bo.mode[k] = bop->mode[k]; - bo.solutions[k] = bop->solutions[k]; - bo.target[k] = bop->target[k]; - bo.deals[k].first = bop->deals[k].first; - bo.deals[k].trump = bop->deals[k].trump; - - for (int i = 0; i <= 2; i++) - { - bo.deals[k].currentTrickSuit[i] = bop->deals[k].currentTrickSuit[i]; - bo.deals[k].currentTrickRank[i] = bop->deals[k].currentTrickRank[i]; - } - - if (convert_from_pbn(bop->deals[k].remainCards, bo.deals[k].remainCards) - != 1) - return RETURN_PBN_FAULT; - } - - int res = solve_all_boards_n(bo, * solvedp); - return res; + return solve_all_boards_pbn_n(*bop, *solvedp, 0); } @@ -163,29 +183,9 @@ int STDCALL SolveAllBoardsSeq( SolvedBoards * solvedp) { Boards bo; - bo.no_of_boards = bop->no_of_boards; - if (bo.no_of_boards > MAXNOOFBOARDS) - return RETURN_TOO_MANY_BOARDS; - - for (int k = 0; k < bop->no_of_boards; k++) - { - bo.mode[k] = bop->mode[k]; - bo.solutions[k] = bop->solutions[k]; - bo.target[k] = bop->target[k]; - bo.deals[k].first = bop->deals[k].first; - bo.deals[k].trump = bop->deals[k].trump; - - for (int i = 0; i <= 2; i++) - { - bo.deals[k].currentTrickSuit[i] = bop->deals[k].currentTrickSuit[i]; - bo.deals[k].currentTrickRank[i] = bop->deals[k].currentTrickRank[i]; - } - - if (convert_from_pbn(bop->deals[k].remainCards, bo.deals[k].remainCards) - != 1) - return RETURN_PBN_FAULT; - } - + const int rc = boards_from_pbn(*bop, bo); + if (rc != RETURN_NO_FAULT) + return rc; return solve_all_boards_n_seq(bo, * solvedp); } diff --git a/library/src/solve_board.hpp b/library/src/solve_board.hpp index 2ce53185..400fe68a 100644 --- a/library/src/solve_board.hpp +++ b/library/src/solve_board.hpp @@ -14,6 +14,16 @@ #include +auto solve_all_boards_n( + Boards const& bds, + SolvedBoards& solved, + int worker_cap = 0) -> int; + +auto solve_all_boards_pbn_n( + BoardsPBN const& bop, + SolvedBoards& solved, + int worker_cap = 0) -> int; + auto solve_all_boards_n_seq( Boards const& bds, SolvedBoards& solved) -> int; diff --git a/library/tests/loop.cpp b/library/tests/loop.cpp index 5db5e3bf..8c564e03 100644 --- a/library/tests/loop.cpp +++ b/library/tests/loop.cpp @@ -20,6 +20,7 @@ #include "cst.hpp" #include "dtest_parallel.hpp" +#include using std::cout; using std::endl; @@ -68,7 +69,8 @@ void loop_solve( } else { - ret = SolveAllBoards(bop, solvedbdp); + ret = solve_all_boards_pbn_n(*bop, *solvedbdp, + dtest_effective_threads(options.num_threads_, count)); } if (ret != RETURN_NO_FAULT) {