-
Notifications
You must be signed in to change notification settings - Fork 118
Improve parallelism by solving most difficult deals first #216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
6234595
b08925f
2d57e8d
f4ed912
f733867
fa2c84c
07a33cd
5e34528
6ead0ed
3ba0d7e
a64a032
b66a00c
4d033a3
1fa58a7
edb0865
d557f89
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,12 +8,15 @@ | |
| */ | ||
|
|
||
| #include "calc_tables.hpp" | ||
| #include <algorithm> | ||
| #include <numeric> | ||
| #include <vector> | ||
|
|
||
| #include <pbn.hpp> | ||
| #include <solve_board.hpp> | ||
| #include <api/solve_board.hpp> | ||
| #include <solver_if.hpp> | ||
| #include <system/deal_fanout.hpp> | ||
| #include <system/memory.hpp> | ||
| #include <system/parallel_boards.hpp> | ||
| #include <system/scheduler.hpp> | ||
|
|
@@ -23,11 +26,11 @@ | |
| extern Memory memory; | ||
| extern Scheduler scheduler; | ||
|
|
||
| // Legacy overload (creates temporary context) | ||
| auto calc_all_boards_n( | ||
| Boards * bop, | ||
| SolvedBoards * solvedp, | ||
| int max_threads = 0) -> int; | ||
| int max_threads = 0, | ||
| bool difficulty_sort = true) -> int; | ||
|
|
||
|
|
||
| auto calc_single_common_internal( | ||
|
|
@@ -110,7 +113,8 @@ auto calc_all_boards_n( | |
| auto calc_all_boards_n( | ||
| Boards * bop, | ||
| SolvedBoards * solvedp, | ||
| int max_threads) -> int | ||
| int max_threads, | ||
| bool difficulty_sort) -> int | ||
| { | ||
| const int n = bop->no_of_boards; | ||
| if (n > MAXNOOFBOARDS) | ||
|
|
@@ -137,11 +141,31 @@ auto calc_all_boards_n( | |
| else | ||
| { | ||
| std::vector<SolverContext> contexts(static_cast<unsigned>(nthreads)); | ||
|
|
||
| // Dispatch hardest boards first to shorten the parallel tail. This only | ||
| // helps across distinct deals (batch calc); for a single deal every board | ||
| // shares one fanout, so the sort is skipped (it would be a no-op anyway). | ||
| std::vector<int> order; | ||
| if (difficulty_sort) | ||
| { | ||
| std::vector<int> fanout(static_cast<unsigned>(n)); | ||
| for (int i = 0; i < n; i++) | ||
| fanout[static_cast<unsigned>(i)] = | ||
| dds::internal::deal_fanout(bop->deals[i]); | ||
| order.resize(static_cast<unsigned>(n)); | ||
| std::iota(order.begin(), order.end(), 0); | ||
| std::stable_sort(order.begin(), order.end(), | ||
| [&](const int a, const int b) { | ||
| return fanout[static_cast<unsigned>(a)] > fanout[static_cast<unsigned>(b)]; | ||
| }); | ||
| } | ||
|
|
||
| err = parallel_all_boards_n(n, nthreads, | ||
| [&](const int worker_id, const int bno) -> int { | ||
| return calc_single_common_internal( | ||
| contexts[static_cast<unsigned>(worker_id)], *bop, *solvedp, bno); | ||
| }); | ||
| }, | ||
| order.empty() ? nullptr : &order); | ||
| } | ||
|
|
||
| END_BLOCK_TIMER; | ||
|
|
@@ -192,7 +216,8 @@ int STDCALL CalcDDtableN( | |
| ind++; | ||
| } | ||
|
|
||
| int res = calc_all_boards_n(&bo, &solved, maxThreads); | ||
| // Single deal: all boards share one deal, so hardest-first sorting is a no-op. | ||
| int res = calc_all_boards_n(&bo, &solved, maxThreads, /*difficulty_sort=*/false); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. trivial Inline variable-name comment isn't necessary.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not? It seems useful to me. Were I writing the code I might have replaced it with a named constant, say DIFFICULTY_SORT_FALSE. |
||
| if (res != 1) | ||
| return res; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /* | ||
| DDS, a bridge double dummy solver. | ||
|
|
||
| Copyright (C) 2006-2014 by Bo Haglund / | ||
| 2014-2018 by Bo Haglund & Soren Hein. | ||
|
|
||
| See LICENSE and README. | ||
| */ | ||
|
|
||
| #include "deal_fanout.hpp" | ||
|
|
||
| #include <lookup_tables/lookup_tables.hpp> | ||
|
|
||
| namespace dds | ||
| { | ||
| namespace internal | ||
| { | ||
|
|
||
| auto deal_fanout(const Deal& dl) -> int | ||
| { | ||
| // The fanout for a given suit and a given player is the number | ||
| // of bit groups, so KT982 has 3 groups. In a given suit the | ||
| // maximum number over all four players is 13. | ||
| // A void counts as the sum of the other players' groups. | ||
|
|
||
| int fanout = 0; | ||
| int fanoutSuit, numVoids, c; | ||
|
|
||
| for (int h = 0; h < DDS_HANDS; h++) | ||
| { | ||
| fanoutSuit = 0; | ||
| numVoids = 0; | ||
| for (int s = 0; s < DDS_SUITS; s++) | ||
| { | ||
| c = static_cast<int>(dl.remainCards[h][s] >> 2); | ||
| fanoutSuit += group_data[c].last_group_ + 1; | ||
| if (c == 0) | ||
| numVoids++; | ||
| } | ||
| fanoutSuit += numVoids * fanoutSuit; | ||
| fanout += fanoutSuit; | ||
| } | ||
|
Comment on lines
+26
to
+42
|
||
|
|
||
| return fanout; | ||
| } | ||
|
|
||
| } // namespace internal | ||
| } // namespace dds | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #pragma once | ||
|
|
||
| #include <api/dll.h> | ||
|
|
||
| namespace dds | ||
| { | ||
| namespace internal | ||
| { | ||
|
|
||
| /** | ||
| * @brief Cheap structural difficulty estimate (cards only, trump-independent). | ||
| * | ||
| * Per hand, sum the number of card groups per suit, with a bonus for voids. | ||
| * Used to dispatch the most difficult deals first in parallel batch calculations. | ||
| */ | ||
| auto deal_fanout(const Deal& dl) -> int; | ||
|
|
||
| } // namespace internal | ||
| } // namespace dds |
Uh oh!
There was an error while loading. Please reload this page.