Skip to content

Commit 393a115

Browse files
committed
Avoid too many map look-ups
1 parent 08b58ed commit 393a115

File tree

6 files changed

+27
-12
lines changed

6 files changed

+27
-12
lines changed

highs/ipm/hipo/factorhighs/Analyse.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,8 @@ void Analyse::findTreeSplitting() {
12741274
std::vector<Int> head, next;
12751275
childrenLinkedList(sn_parent_, head, next);
12761276

1277+
is_in_tree_splitting_.assign(sn_count_, false);
1278+
12771279
// Divide the tree into single nodes and subtrees, such that each subtree has
12781280
// at most small_thresh operations overall. Group subtrees together, so that
12791281
// groups have 1-2% operations.
@@ -1282,6 +1284,7 @@ void Analyse::findTreeSplitting() {
12821284
if (subtree_ops[sn] > small_thresh) {
12831285
// sn is a single node
12841286
auto res_insert = tree_splitting_.insert({sn, {}});
1287+
is_in_tree_splitting_[sn] = true;
12851288
res_insert.first->second.type = NodeType::single;
12861289

12871290
// The children of this sn are either single nodes or head of subtrees.
@@ -1298,6 +1301,7 @@ void Analyse::findTreeSplitting() {
12981301
if (is_small) {
12991302
if (!current_nodedata) {
13001303
auto res_insert = tree_splitting_.insert({child, {}});
1304+
is_in_tree_splitting_[child] = true;
13011305
current_nodedata = &res_insert.first->second;
13021306
current_nodedata->type = NodeType::subtree;
13031307
current_ops = 0.0;
@@ -1316,6 +1320,7 @@ void Analyse::findTreeSplitting() {
13161320
} else if (sn_parent_[sn] == -1) {
13171321
// sn is small root: single task with whole subtree
13181322
auto res_insert = tree_splitting_.insert({sn, {}});
1323+
is_in_tree_splitting_[sn] = true;
13191324
res_insert.first->second.type = NodeType::subtree;
13201325
res_insert.first->second.group.push_back(sn);
13211326
res_insert.first->second.firstdesc.push_back(first_desc[sn]);
@@ -1457,6 +1462,7 @@ Int Analyse::run(Symbolic& S) {
14571462
S.consecutive_sums_ = std::move(consecutive_sums_);
14581463
S.clique_block_start_ = std::move(clique_block_start_);
14591464
S.tree_splitting_ = std::move(tree_splitting_);
1465+
S.is_in_tree_splitting_ = std::move(is_in_tree_splitting_);
14601466

14611467
#if HIPO_TIMING_LEVEL >= 1
14621468
data_.sumTime(kTimeAnalyse, clock_total.stop());

highs/ipm/hipo/factorhighs/Analyse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class Analyse {
7878
std::vector<std::vector<Int>> clique_block_start_{};
7979

8080
std::map<Int, NodeData> tree_splitting_;
81+
std::vector<bool> is_in_tree_splitting_;
8182

8283
// block size
8384
Int nb_{};

highs/ipm/hipo/factorhighs/FactorHiGHSSettings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const Int kMaxRefinementIter = 3;
5252
const double kRefinementTolerance = 1e-12;
5353

5454
// tree splitting
55-
const double kSmallSubtreesCoeff = 0.01; // 1%
55+
const double kSmallSubtreesCoeff = 0.001; // 0.1%
5656
const double kSpopsWeightSplitting = 30.0;
5757

5858
// metis

highs/ipm/hipo/factorhighs/Factorise.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -384,31 +384,32 @@ void Factorise::spawnNode(Int sn, const TaskGroupSpecial& tg, bool do_spawn) {
384384
// immediately. This avoids the overhead of spawning a task if a supernode has
385385
// a single child.
386386

387-
auto it = S_.treeSplitting().find(sn);
388-
389-
if (it == S_.treeSplitting().end()) {
387+
if (!S_.isInTreeSplitting(sn)) {
390388
// sn is head of small subtree, but not the first subtree in the group.
391389
// It will be processed in another task.
392390
return;
393391
}
394392

393+
// only search the map if sn is inside
394+
auto it = S_.treeSplitting().find(sn);
395+
395396
if (it->second.type == NodeType::single) {
396397
// sn is single node; spawn only that
397398

398-
auto lambda = [this, sn]() { processSupernode(sn, true); };
399+
auto f = [this, sn]() { processSupernode(sn, true); };
399400

400401
if (do_spawn)
401-
tg.spawn(std::move(lambda));
402+
tg.spawn(std::move(f));
402403
else
403-
lambda();
404+
f();
404405

405406
} else {
406407
// sn is head of the first subtree in a group of small subtrees; spawn all
407408
// of them
408409

409410
const NodeData* nd_ptr = &(it->second);
410411

411-
auto lambda = [this, nd_ptr]() {
412+
auto f = [this, nd_ptr]() {
412413
for (Int i = 0; i < nd_ptr->group.size(); ++i) {
413414
Int st_head = nd_ptr->group[i];
414415
Int start = nd_ptr->firstdesc[i];
@@ -420,18 +421,17 @@ void Factorise::spawnNode(Int sn, const TaskGroupSpecial& tg, bool do_spawn) {
420421
};
421422

422423
if (do_spawn)
423-
tg.spawn(std::move(lambda));
424+
tg.spawn(std::move(f));
424425
else
425-
lambda();
426+
f();
426427
}
427428
}
428429

429430
void Factorise::syncNode(Int sn, const TaskGroupSpecial& tg) {
430431
// If spawnNode(sn,tg) created a task, then sync it.
431432
// This happens only if sn is found in the treeSplitting data structure.
432433

433-
auto it = S_.treeSplitting().find(sn);
434-
if (it != S_.treeSplitting().end()) tg.sync();
434+
if (S_.isInTreeSplitting(sn)) tg.sync();
435435
}
436436

437437
bool Factorise::run(Numeric& num) {

highs/ipm/hipo/factorhighs/Symbolic.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ const std::vector<Int>& Symbolic::pivotSign() const { return pivot_sign_; }
5353
const std::map<Int, NodeData>& Symbolic::treeSplitting() const {
5454
return tree_splitting_;
5555
}
56+
bool Symbolic::isInTreeSplitting(Int sn) const {
57+
return is_in_tree_splitting_[sn];
58+
}
5659

5760
Int Symbolic::snRoots() const {
5861
Int roots = 0;

highs/ipm/hipo/factorhighs/Symbolic.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ class Symbolic {
114114
// data.firstdesc[i] <= j <= data.group[i].
115115
std::map<Int, NodeData> tree_splitting_;
116116

117+
// For each supernode, is_in_tree_splitting_[sn] is true if sn is found in the
118+
// tree_splitting_ data structure. Avoids too many lookups into the map.
119+
std::vector<bool> is_in_tree_splitting_;
120+
117121
friend class Analyse;
118122

119123
public:
@@ -149,6 +153,7 @@ class Symbolic {
149153
const std::vector<Int>& snStart() const;
150154
const std::vector<Int>& pivotSign() const;
151155
const std::map<Int, NodeData>& treeSplitting() const;
156+
bool isInTreeSplitting(Int sn) const;
152157

153158
void print(const Log& log, bool verbose = false) const;
154159
};

0 commit comments

Comments
 (0)