Skip to content

Commit 4ee947b

Browse files
authored
Merge f410524 into 65aa640
2 parents 65aa640 + f410524 commit 4ee947b

File tree

9 files changed

+440
-180
lines changed

9 files changed

+440
-180
lines changed

library/cpp/disjoint_sets/disjoint_sets.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class TDisjointSets {
1616
size_t NumberOfSets;
1717

1818
public:
19+
TDisjointSets() = default;
20+
1921
TDisjointSets(size_t setCount)
2022
: Parents(setCount)
2123
, Ranks(setCount, 0)

ydb/library/yql/core/yql_cost_function.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct TJoinColumn {
4646
return RelName == other.RelName && AttributeName == other.AttributeName;
4747
}
4848

49-
struct HashFunction
49+
struct THashFunction
5050
{
5151
size_t operator()(const TJoinColumn& c) const
5252
{

ydb/library/yql/dq/opt/dq_opt_conflict_rules_collector.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class TConflictRulesCollector {
6868
ConflictRules_.emplace_back(
6969
SubtreeNodes_[child->LeftArg],
7070
SubtreeNodes_[child->RightArg]
71-
);
71+
);
7272
}
7373
};
7474

ydb/library/yql/dq/opt/dq_opt_dphyp_solver.h

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace NYql::NDq {
3333
* This class is templated by std::bitset with the largest number of joins we can process
3434
* or std::bitset<64>, which has a more efficient implementation of enumerating subsets of set.
3535
*/
36-
template <typename TNodeSet>
36+
template <typename TNodeSet, bool ProcessCycles>
3737
class TDPHypSolver {
3838
public:
3939
TDPHypSolver(
@@ -58,7 +58,7 @@ class TDPHypSolver {
5858

5959
void EnumerateCmpRec(const TNodeSet& s1, const TNodeSet& s2, const TNodeSet& x);
6060

61-
void EmitCsgCmp(const TNodeSet& s1, const TNodeSet& s2, const typename TJoinHypergraph<TNodeSet>::TEdge* csgCmpEdge);
61+
void EmitCsgCmp(const TNodeSet& s1, const TNodeSet& s2, const typename TJoinHypergraph<TNodeSet>::TEdge* csgCmpEdge, const typename TJoinHypergraph<TNodeSet>::TEdge* reversedCsgCmpEdge);
6262

6363
private:
6464
// Create an exclusion set that contains all the nodes of the graph that are smaller or equal to
@@ -113,7 +113,7 @@ class TDPHypSolver {
113113
/*
114114
* Count the number of items in the DP table of DPHyp
115115
*/
116-
template <typename TNodeSet> ui32 TDPHypSolver<TNodeSet>::CountCC(ui32 budget) {
116+
template <typename TNodeSet, bool ProcessCycles> ui32 TDPHypSolver<TNodeSet, ProcessCycles>::CountCC(ui32 budget) {
117117
TNodeSet allNodes;
118118
allNodes.set();
119119
ui32 cost = 0;
@@ -135,7 +135,7 @@ template <typename TNodeSet> ui32 TDPHypSolver<TNodeSet>::CountCC(ui32 budget) {
135135
/**
136136
* Recursively count the nuber of items in the DP table of DPccp
137137
*/
138-
template <typename TNodeSet> ui32 TDPHypSolver<TNodeSet>::CountCCRec(const TNodeSet& s, const TNodeSet& x, ui32 cost, ui32 budget) {
138+
template <typename TNodeSet, bool ProcessCycles> ui32 TDPHypSolver<TNodeSet, ProcessCycles>::CountCCRec(const TNodeSet& s, const TNodeSet& x, ui32 cost, ui32 budget) {
139139
TNodeSet neighs = Neighs(s, x);
140140

141141
if (neighs == TNodeSet{}) {
@@ -161,7 +161,7 @@ template <typename TNodeSet> ui32 TDPHypSolver<TNodeSet>::CountCCRec(const TNode
161161
return cost;
162162
}
163163

164-
template<typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::Neighs(TNodeSet s, TNodeSet x) {
164+
template<typename TNodeSet, bool ProcessCycles> TNodeSet TDPHypSolver<TNodeSet, ProcessCycles>::Neighs(TNodeSet s, TNodeSet x) {
165165
TNodeSet neighs{};
166166

167167
auto& nodes = Graph_.GetNodes();
@@ -190,11 +190,16 @@ template<typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::Neighs(TNodeSet s,
190190
}
191191

192192
template<>
193-
inline std::bitset<64> TDPHypSolver<std::bitset<64>>::NextBitset(const std::bitset<64>& prev, const std::bitset<64>& final) {
193+
inline std::bitset<64> TDPHypSolver<std::bitset<64>, false>::NextBitset(const std::bitset<64>& prev, const std::bitset<64>& final) {
194194
return std::bitset<64>((prev | ~final).to_ulong() + 1) & final;
195195
}
196196

197-
template<typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::NextBitset(const TNodeSet& prev, const TNodeSet& final) {
197+
template<>
198+
inline std::bitset<64> TDPHypSolver<std::bitset<64>, true>::NextBitset(const std::bitset<64>& prev, const std::bitset<64>& final) {
199+
return std::bitset<64>((prev | ~final).to_ulong() + 1) & final;
200+
}
201+
202+
template<typename TNodeSet, bool ProcessCycles> TNodeSet TDPHypSolver<TNodeSet, ProcessCycles>::NextBitset(const TNodeSet& prev, const TNodeSet& final) {
198203
if (prev == final) {
199204
return final;
200205
}
@@ -223,7 +228,7 @@ template<typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::NextBitset(const TN
223228
return res;
224229
}
225230

226-
template<typename TNodeSet> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypSolver<TNodeSet>::Solve(const TOptimizerHints& hints) {
231+
template<typename TNodeSet, bool ProcessCycles> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypSolver<TNodeSet, ProcessCycles>::Solve(const TOptimizerHints& hints) {
227232
for (auto& h : hints.CardinalityHints->Hints) {
228233
TNodeSet hintSet = Graph_.GetNodesByRelNames(h.JoinLabels);
229234
CardHintsTable_[hintSet] = &h;
@@ -270,7 +275,7 @@ template<typename TNodeSet> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypSo
270275
* First it emits CSGs that are created by adding neighbors of S to S
271276
* Then it recurses on the S fused with its neighbors.
272277
*/
273-
template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EnumerateCsgRec(const TNodeSet& s1, const TNodeSet& x) {
278+
template <typename TNodeSet, bool ProcessCycles> void TDPHypSolver<TNodeSet, ProcessCycles>::EnumerateCsgRec(const TNodeSet& s1, const TNodeSet& x) {
274279
TNodeSet neighs = Neighs(s1, x);
275280

276281
if (neighs == TNodeSet{}) {
@@ -313,7 +318,7 @@ template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EnumerateCsgRec(const
313318
* First it iterates through neighbors of the initial set S and emits pairs
314319
* (S,S2), where S2 is the neighbor of S. Then it recursively emits complement pairs
315320
*/
316-
template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EmitCsg(const TNodeSet& s1) {
321+
template <typename TNodeSet, bool ProcessCycles> void TDPHypSolver<TNodeSet, ProcessCycles>::EmitCsg(const TNodeSet& s1) {
317322
TNodeSet x = s1 | MakeBiMin(s1);
318323
TNodeSet neighs = Neighs(s1, x);
319324

@@ -326,8 +331,15 @@ template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EmitCsg(const TNodeSet
326331
TNodeSet s2{};
327332
s2[i] = 1;
328333

329-
if (auto* edge = Graph_.FindEdgeBetween(s1, s2)) {
330-
EmitCsgCmp(s1, s2, edge);
334+
if constexpr (ProcessCycles) {
335+
if (auto edge = Graph_.FindEdgeWithAllConditionsBetween(s1, s2)) {
336+
auto reversedEdge = edge->CreateReversed(-1);
337+
EmitCsgCmp(s1, s2, &edge.value(), &reversedEdge);
338+
}
339+
} else {
340+
if (auto* edge = Graph_.FindEdgeBetween(s1, s2)) {
341+
EmitCsgCmp(s1, s2, edge, &Graph_.GetEdge(edge->ReversedEdgeId));
342+
}
331343
}
332344

333345
EnumerateCmpRec(s1, s2, x | MakeB(neighs, GetLowestSetBit(s2)));
@@ -341,7 +353,7 @@ template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EmitCsg(const TNodeSet
341353
* that are obtained by adding S2's neighbors to itself
342354
* Then it recusrses into pairs (S1,S2+next)
343355
*/
344-
template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EnumerateCmpRec(const TNodeSet& s1, const TNodeSet& s2, const TNodeSet& x) {
356+
template <typename TNodeSet, bool ProcessCycles> void TDPHypSolver<TNodeSet, ProcessCycles>::EnumerateCmpRec(const TNodeSet& s1, const TNodeSet& s2, const TNodeSet& x) {
345357
TNodeSet neighs = Neighs(s2, x);
346358

347359
if (neighs == TNodeSet{}) {
@@ -355,8 +367,15 @@ template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EnumerateCmpRec(const
355367
next = NextBitset(prev, neighs);
356368

357369
if (DpTable_.contains(s2 | next)) {
358-
if (auto* edge = Graph_.FindEdgeBetween(s1, s2 | next)) {
359-
EmitCsgCmp(s1, s2 | next, edge);
370+
if constexpr (ProcessCycles) {
371+
if (auto edge = Graph_.FindEdgeWithAllConditionsBetween(s1, s2 | next)) {
372+
auto reversedEdge = edge->CreateReversed(-1);
373+
EmitCsgCmp(s1, s2 | next, &edge.value(), &reversedEdge);
374+
}
375+
} else {
376+
if (auto* edge = Graph_.FindEdgeBetween(s1, s2 | next)) {
377+
EmitCsgCmp(s1, s2 | next, edge, &Graph_.GetEdge(edge->ReversedEdgeId));
378+
}
360379
}
361380
}
362381

@@ -381,7 +400,7 @@ template <typename TNodeSet> void TDPHypSolver<TNodeSet>::EnumerateCmpRec(const
381400
}
382401
}
383402

384-
template <typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::MakeBiMin(const TNodeSet& s) {
403+
template <typename TNodeSet, bool ProcessCycles> TNodeSet TDPHypSolver<TNodeSet, ProcessCycles>::MakeBiMin(const TNodeSet& s) {
385404
TNodeSet res{};
386405

387406
for (size_t i = 0; i < NNodes_; i++) {
@@ -395,7 +414,7 @@ template <typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::MakeBiMin(const TN
395414
return res;
396415
}
397416

398-
template <typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::MakeB(const TNodeSet& s, size_t v) {
417+
template <typename TNodeSet, bool ProcessCycles> TNodeSet TDPHypSolver<TNodeSet, ProcessCycles>::MakeB(const TNodeSet& s, size_t v) {
399418
TNodeSet res{};
400419

401420
for (size_t i = 0; i < NNodes_; i++) {
@@ -407,7 +426,7 @@ template <typename TNodeSet> TNodeSet TDPHypSolver<TNodeSet>::MakeB(const TNodeS
407426
return res;
408427
}
409428

410-
template <typename TNodeSet> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypSolver<TNodeSet>::PickBestJoin(
429+
template <typename TNodeSet, bool ProcessCycles> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypSolver<TNodeSet, ProcessCycles>::PickBestJoin(
411430
const std::shared_ptr<IBaseOptimizerNode>& left,
412431
const std::shared_ptr<IBaseOptimizerNode>& right,
413432
EJoinKind joinKind,
@@ -434,7 +453,7 @@ template <typename TNodeSet> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypS
434453
for (auto joinAlgo : AllJoinAlgos) {
435454
if (ctx.IsJoinApplicable(left, right, joinConditions, leftJoinKeys, rightJoinKeys, joinAlgo, joinKind)){
436455
auto cost = ctx.ComputeJoinStats(*left->Stats, *right->Stats, leftJoinKeys, rightJoinKeys, joinAlgo, joinKind, maybeCardHint).Cost;
437-
if (cost < bestCost) {
456+
if (cost <= bestCost) {
438457
bestCost = cost;
439458
bestAlgo = joinAlgo;
440459
bestJoinIsReversed = false;
@@ -444,7 +463,7 @@ template <typename TNodeSet> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypS
444463
if (isCommutative) {
445464
if (ctx.IsJoinApplicable(right, left, reversedJoinConditions, rightJoinKeys, leftJoinKeys, joinAlgo, joinKind)){
446465
auto cost = ctx.ComputeJoinStats(*right->Stats, *left->Stats, rightJoinKeys, leftJoinKeys, joinAlgo, joinKind, maybeCardHint).Cost;
447-
if (cost < bestCost) {
466+
if (cost <= bestCost) {
448467
bestCost = cost;
449468
bestAlgo = joinAlgo;
450469
bestJoinIsReversed = true;
@@ -465,19 +484,23 @@ template <typename TNodeSet> std::shared_ptr<TJoinOptimizerNodeInternal> TDPHypS
465484
/*
466485
* Emit a single CSG + CMP pair
467486
*/
468-
template<typename TNodeSet> void TDPHypSolver<TNodeSet>::EmitCsgCmp(const TNodeSet& s1, const TNodeSet& s2, const typename TJoinHypergraph<TNodeSet>::TEdge* csgCmpEdge) {
487+
template<typename TNodeSet, bool ProcessCycles> void TDPHypSolver<TNodeSet, ProcessCycles>::EmitCsgCmp(
488+
const TNodeSet& s1,
489+
const TNodeSet& s2,
490+
const typename TJoinHypergraph<TNodeSet>::TEdge* csgCmpEdge,
491+
const typename TJoinHypergraph<TNodeSet>::TEdge* reversedCsgCmpEdge
492+
) {
469493
// Here we actually build the join and choose and compare the
470494
// new plan to what's in the dpTable, if it there
471495

472496
Y_ENSURE(DpTable_.contains(s1), "DP Table does not contain S1");
473497
Y_ENSURE(DpTable_.contains(s2), "DP Table does not conaint S2");
474498

475-
const auto* reversedEdge = &Graph_.GetEdge(csgCmpEdge->ReversedEdgeId);
476499
auto leftNodes = DpTable_[s1];
477500
auto rightNodes = DpTable_[s2];
478501

479502
if (csgCmpEdge->IsReversed) {
480-
std::swap(csgCmpEdge, reversedEdge);
503+
std::swap(csgCmpEdge, reversedCsgCmpEdge);
481504
std::swap(leftNodes, rightNodes);
482505
}
483506

@@ -494,7 +517,7 @@ template<typename TNodeSet> void TDPHypSolver<TNodeSet>::EmitCsgCmp(const TNodeS
494517
csgCmpEdge->RightAny,
495518
csgCmpEdge->IsCommutative,
496519
csgCmpEdge->JoinConditions,
497-
reversedEdge->JoinConditions,
520+
reversedCsgCmpEdge->JoinConditions,
498521
csgCmpEdge->LeftJoinKeys,
499522
csgCmpEdge->RightJoinKeys,
500523
Pctx_,
@@ -509,7 +532,7 @@ template<typename TNodeSet> void TDPHypSolver<TNodeSet>::EmitCsgCmp(const TNodeS
509532
#ifndef NDEBUG
510533
auto pair = std::make_pair(s1, s2);
511534
Y_ENSURE (!CheckTable_.contains(pair), "Check table already contains pair S1|S2");
512-
CheckTable_[ std::pair<TNodeSet,TNodeSet>(s1, s2) ] = true;
535+
CheckTable_[pair] = true;
513536
#endif
514537
}
515538

0 commit comments

Comments
 (0)