@@ -39,10 +39,19 @@ folly::Future<Status> MultiShortestPathExecutor::execute() {
39
39
})
40
40
.thenValue ([this ](auto && resp) {
41
41
UNUSED (resp);
42
- preLeftPaths_.swap (leftPaths_);
43
- preRightPaths_.swap (rightPaths_);
42
+ preRightPaths_ = rightPaths_;
43
+ // update history
44
+ for (auto & iter : leftPaths_) {
45
+ historyLeftPaths_[iter.first ].insert (std::make_move_iterator (iter.second .begin ()),
46
+ std::make_move_iterator (iter.second .end ()));
47
+ }
48
+ for (auto & iter : rightPaths_) {
49
+ historyRightPaths_[iter.first ].insert (std::make_move_iterator (iter.second .begin ()),
50
+ std::make_move_iterator (iter.second .end ()));
51
+ }
44
52
leftPaths_.clear ();
45
53
rightPaths_.clear ();
54
+
46
55
step_++;
47
56
DataSet ds;
48
57
ds.colNames = pathNode_->colNames ();
@@ -58,24 +67,40 @@ void MultiShortestPathExecutor::init() {
58
67
for (; rIter->valid (); rIter->next ()) {
59
68
auto & vid = rIter->getColumn (0 );
60
69
if (rightVids.emplace (vid).second ) {
61
- preRightPaths_[vid].push_back ({Path (Vertex (vid, {}), {})});
70
+ std::vector<Path> tmp ({Path (Vertex (vid, {}), {})});
71
+ historyRightPaths_[vid].emplace (vid, tmp);
72
+ preRightPaths_[vid].emplace (vid, std::move (tmp));
62
73
}
63
74
}
64
75
65
76
std::set<Value> leftVids;
66
77
for (; lIter->valid (); lIter->next ()) {
67
78
auto & vid = lIter->getColumn (0 );
79
+ std::vector<Path> tmp ({Path (Vertex (vid, {}), {})});
80
+ historyLeftPaths_[vid].emplace (vid, std::move (tmp));
68
81
leftVids.emplace (vid);
69
82
}
70
83
for (const auto & leftVid : leftVids) {
71
84
for (const auto & rightVid : rightVids) {
72
85
if (leftVid != rightVid) {
73
- terminationMap_.insert ({ leftVid, { rightVid, true }} );
86
+ terminationMap_.emplace ( leftVid, std::make_pair ( rightVid, true ) );
74
87
}
75
88
}
76
89
}
77
90
}
78
91
92
+ std::vector<Path> MultiShortestPathExecutor::createPaths (const std::vector<Path>& paths,
93
+ const Edge& edge) {
94
+ std::vector<Path> newPaths;
95
+ newPaths.reserve (paths.size ());
96
+ for (const auto & p : paths) {
97
+ Path path = p;
98
+ path.steps .emplace_back (Step (Vertex (edge.dst , {}), edge.type , edge.name , edge.ranking , {}));
99
+ newPaths.emplace_back (std::move (path));
100
+ }
101
+ return newPaths;
102
+ }
103
+
79
104
Status MultiShortestPathExecutor::buildPath (bool reverse) {
80
105
auto iter = reverse ? ectx_->getResult (pathNode_->rightInputVar ()).iter ()
81
106
: ectx_->getResult (pathNode_->leftInputVar ()).iter ();
@@ -96,10 +121,23 @@ Status MultiShortestPathExecutor::buildPath(bool reverse) {
96
121
Path path;
97
122
path.src = Vertex (src, {});
98
123
path.steps .emplace_back (Step (Vertex (dst, {}), edge.type , edge.name , edge.ranking , {}));
99
- currentPaths[dst].emplace_back (std::move (path));
124
+ auto foundDst = currentPaths.find (dst);
125
+ if (foundDst != currentPaths.end ()) {
126
+ auto foundSrc = foundDst->second .find (src);
127
+ if (foundSrc != foundDst->second .end ()) {
128
+ // same <src, dst>, different edge type or rank
129
+ foundSrc->second .emplace_back (std::move (path));
130
+ } else {
131
+ std::vector<Path> tmp ({std::move (path)});
132
+ foundDst->second .emplace (src, std::move (tmp));
133
+ }
134
+ } else {
135
+ std::vector<Path> tmp ({std::move (path)});
136
+ currentPaths[dst].emplace (src, std::move (tmp));
137
+ }
100
138
}
101
139
} else {
102
- auto & historyPaths = reverse ? preRightPaths_ : preLeftPaths_ ;
140
+ auto & historyPaths = reverse ? historyRightPaths_ : historyLeftPaths_ ;
103
141
for (; iter->valid (); iter->next ()) {
104
142
auto edgeVal = iter->getEdge ();
105
143
if (UNLIKELY (!edgeVal.isEdge ())) {
@@ -108,50 +146,93 @@ Status MultiShortestPathExecutor::buildPath(bool reverse) {
108
146
auto & edge = edgeVal.getEdge ();
109
147
auto & src = edge.src ;
110
148
auto & dst = edge.dst ;
111
- for (const auto & histPath : historyPaths[src]) {
112
- Path path = histPath;
113
- path.steps .emplace_back (Step (Vertex (dst, {}), edge.type , edge.name , edge.ranking , {}));
114
- if (path.hasDuplicateVertices ()) {
115
- continue ;
149
+ auto & prePaths = historyPaths[src];
150
+
151
+ auto foundHistDst = historyPaths.find (dst);
152
+ if (foundHistDst == historyPaths.end ()) {
153
+ // dst not in history
154
+ auto foundDst = currentPaths.find (dst);
155
+ if (foundDst == currentPaths.end ()) {
156
+ // dst not in current, new edge
157
+ for (const auto & prePath : prePaths) {
158
+ currentPaths[dst].emplace (prePath.first , createPaths (prePath.second , edge));
159
+ }
160
+ } else {
161
+ // dst in current
162
+ for (const auto & prePath : prePaths) {
163
+ auto newPaths = createPaths (prePath.second , edge);
164
+ auto foundSrc = foundDst->second .find (prePath.first );
165
+ if (foundSrc == foundDst->second .end ()) {
166
+ foundDst->second .emplace (prePath.first , std::move (newPaths));
167
+ } else {
168
+ foundSrc->second .insert (foundSrc->second .begin (),
169
+ std::make_move_iterator (newPaths.begin ()),
170
+ std::make_move_iterator (newPaths.end ()));
171
+ }
172
+ }
173
+ }
174
+ } else {
175
+ // dst in history
176
+ auto & historyDstPaths = foundHistDst->second ;
177
+ for (const auto & prePath : prePaths) {
178
+ if (historyDstPaths.find (prePath.first ) != historyDstPaths.end ()) {
179
+ // loop: a->b->c->a or a->b->c->b,
180
+ // filter out path that with duplicate vertex or have already been found before
181
+ continue ;
182
+ }
183
+ auto foundDst = currentPaths.find (dst);
184
+ if (foundDst == currentPaths.end ()) {
185
+ currentPaths[dst].emplace (prePath.first , createPaths (prePath.second , edge));
186
+ } else {
187
+ auto newPaths = createPaths (prePath.second , edge);
188
+ auto foundSrc = foundDst->second .find (prePath.first );
189
+ if (foundSrc == foundDst->second .end ()) {
190
+ foundDst->second .emplace (prePath.first , std::move (newPaths));
191
+ } else {
192
+ foundSrc->second .insert (foundSrc->second .begin (),
193
+ std::make_move_iterator (newPaths.begin ()),
194
+ std::make_move_iterator (newPaths.end ()));
195
+ }
196
+ }
116
197
}
117
- currentPaths[dst].emplace_back (std::move (path));
118
198
}
119
199
}
120
200
}
201
+
121
202
// set nextVid
122
203
const auto & nextVidVar = reverse ? pathNode_->rightVidVar () : pathNode_->leftVidVar ();
123
204
setNextStepVid (currentPaths, nextVidVar);
124
205
return Status::OK ();
125
206
}
126
207
127
- DataSet MultiShortestPathExecutor::doConjunct (Interims::iterator startIter,
128
- Interims::iterator endIter,
129
- bool oddStep) {
130
- auto & rightPaths = oddStep ? preRightPaths_ : rightPaths_;
131
- DataSet ds;
132
- for (; startIter != endIter; ++startIter) {
133
- auto found = rightPaths.find (startIter->first );
134
- if (found == rightPaths.end ()) {
135
- continue ;
136
- }
137
- for (const auto & lPath : startIter->second ) {
138
- const auto & srcVid = lPath.src .vid ;
139
- auto range = terminationMap_.equal_range (srcVid);
140
- for (const auto & rPath : found->second ) {
141
- const auto & dstVid = rPath.src .vid ;
142
- for (auto iter = range.first ; iter != range.second ; ++iter) {
143
- if (iter->second .first == dstVid) {
144
- auto forwardPath = lPath;
145
- auto backwardPath = rPath;
208
+ DataSet MultiShortestPathExecutor::doConjunct (
209
+ const std::vector<std::pair<Interims::iterator, Interims::iterator>>& iters) {
210
+ auto buildPaths =
211
+ [](const std::vector<Path>& leftPaths, const std::vector<Path>& rightPaths, DataSet& ds) {
212
+ for (const auto & leftPath : leftPaths) {
213
+ for (const auto & rightPath : rightPaths) {
214
+ auto forwardPath = leftPath;
215
+ auto backwardPath = rightPath;
146
216
backwardPath.reverse ();
147
217
forwardPath.append (std::move (backwardPath));
148
- if (forwardPath.hasDuplicateVertices ()) {
149
- continue ;
150
- }
151
218
Row row;
152
219
row.values .emplace_back (std::move (forwardPath));
153
220
ds.rows .emplace_back (std::move (row));
154
- iter->second .second = false ;
221
+ }
222
+ }
223
+ };
224
+
225
+ DataSet ds;
226
+ for (const auto & iter : iters) {
227
+ const auto & leftPaths = iter.first ->second ;
228
+ const auto & rightPaths = iter.second ->second ;
229
+ for (const auto & leftPath : leftPaths) {
230
+ auto range = terminationMap_.equal_range (leftPath.first );
231
+ for (const auto & rightPath : rightPaths) {
232
+ for (auto found = range.first ; found != range.second ; ++found) {
233
+ if (found->second .first == rightPath.first ) {
234
+ buildPaths (leftPath.second , rightPath.second , ds);
235
+ found->second .second = false ;
155
236
}
156
237
}
157
238
}
@@ -161,28 +242,51 @@ DataSet MultiShortestPathExecutor::doConjunct(Interims::iterator startIter,
161
242
}
162
243
163
244
folly::Future<bool > MultiShortestPathExecutor::conjunctPath (bool oddStep) {
164
- size_t batchSize = leftPaths_.size () / static_cast <size_t >(FLAGS_num_operator_threads);
245
+ auto & rightPaths = oddStep ? preRightPaths_ : rightPaths_;
246
+ size_t leftPathSize = leftPaths_.size ();
247
+ size_t rightPathSize = rightPaths.size ();
165
248
std::vector<folly::Future<DataSet>> futures;
166
- size_t i = 0 ;
249
+ std::vector<std::pair<Interims::iterator, Interims::iterator>> pathIters ;
167
250
168
- auto startIter = leftPaths_.begin ();
169
- for (auto leftIter = leftPaths_.begin (); leftIter != leftPaths_.end (); ++leftIter) {
170
- if (i++ == batchSize) {
171
- auto endIter = leftIter;
172
- endIter++;
173
- auto future = folly::via (runner (), [this , startIter, endIter, oddStep]() {
174
- return doConjunct (startIter, endIter, oddStep);
175
- });
176
- futures.emplace_back (std::move (future));
177
- i = 0 ;
178
- startIter = endIter;
251
+ size_t i = 0 ;
252
+ if (leftPathSize > rightPathSize) {
253
+ size_t batchSize = leftPathSize / static_cast <size_t >(FLAGS_num_operator_threads);
254
+ pathIters.reserve (batchSize);
255
+ for (auto leftIter = leftPaths_.begin (); leftIter != leftPaths_.end (); ++leftIter) {
256
+ auto rightIter = rightPaths.find (leftIter->first );
257
+ if (rightIter == rightPaths.end ()) {
258
+ continue ;
259
+ }
260
+ pathIters.emplace_back (leftIter, rightIter);
261
+ if (++i == batchSize) {
262
+ auto future = folly::via (
263
+ runner (), [this , iters = std::move (pathIters)]() { return doConjunct (iters); });
264
+ futures.emplace_back (std::move (future));
265
+ pathIters.reserve (batchSize);
266
+ i = 0 ;
267
+ }
268
+ }
269
+ } else {
270
+ size_t batchSize = rightPathSize / static_cast <size_t >(FLAGS_num_operator_threads);
271
+ pathIters.reserve (batchSize);
272
+ for (auto rightIter = rightPaths.begin (); rightIter != rightPaths.end (); ++rightIter) {
273
+ auto leftIter = leftPaths_.find (rightIter->first );
274
+ if (leftIter == leftPaths_.end ()) {
275
+ continue ;
276
+ }
277
+ pathIters.emplace_back (leftIter, rightIter);
278
+ if (++i == batchSize) {
279
+ auto future = folly::via (
280
+ runner (), [this , iters = std::move (pathIters)]() { return doConjunct (iters); });
281
+ futures.emplace_back (std::move (future));
282
+ pathIters.reserve (batchSize);
283
+ i = 0 ;
284
+ }
179
285
}
180
286
}
181
287
if (i != 0 ) {
182
- auto endIter = leftPaths_.end ();
183
- auto future = folly::via (runner (), [this , startIter, endIter, oddStep]() {
184
- return doConjunct (startIter, endIter, oddStep);
185
- });
288
+ auto future =
289
+ folly::via (runner (), [this , iters = std::move (pathIters)]() { return doConjunct (iters); });
186
290
futures.emplace_back (std::move (future));
187
291
}
188
292
0 commit comments