| 1305 | } |
| 1306 | |
| 1307 | Status AddControlEdges(const PartitionOptions& opts, |
| 1308 | std::unordered_map<string, GraphDef>* partitions) { |
| 1309 | Status status; |
| 1310 | // TODO(yuanbyu): Very naive for now. To be improved. |
| 1311 | const int num_epochs = 100; |
| 1312 | const int prefetch = 6; |
| 1313 | |
| 1314 | for (auto& part : *partitions) { |
| 1315 | GraphDef* gdef = &part.second; |
| 1316 | std::vector<std::pair<const NodeDef*, int64>> start_times; |
| 1317 | std::unordered_map<const NodeDef*, int64> node_to_start_time; |
| 1318 | status = TopologicalSortNodesWithTimePriority(gdef, &start_times, |
| 1319 | &node_to_start_time); |
| 1320 | if (!status.ok()) { |
| 1321 | return status; |
| 1322 | } |
| 1323 | |
| 1324 | // Add a dummy node for every epoch, and add a control edge from the |
| 1325 | // "last" node in the preceding epoch to the dummy node. |
| 1326 | string device_name = gdef->node(0).device(); |
| 1327 | int64 makespan = start_times.back().second; |
| 1328 | int64 resolution = (makespan / num_epochs) + 1; |
| 1329 | |
| 1330 | int i = 0; |
| 1331 | int j = 0; |
| 1332 | std::vector<NodeDef*> dummys; |
| 1333 | while (i < num_epochs && static_cast<size_t>(j) < start_times.size()) { |
| 1334 | if (i * resolution > start_times[j].second) { |
| 1335 | j++; |
| 1336 | } else { |
| 1337 | NodeDef* dummy = AddControlTrigger(opts, gdef, device_name, i, |
| 1338 | i * resolution, &status); |
| 1339 | if (!status.ok()) { |
| 1340 | return status; |
| 1341 | } |
| 1342 | dummys.push_back(dummy); |
| 1343 | if (j > 0) { |
| 1344 | string src_name = start_times[j - 1].first->name(); |
| 1345 | AddInput(dummy, src_name, Graph::kControlSlot); |
| 1346 | } |
| 1347 | i++; |
| 1348 | } |
| 1349 | } |
| 1350 | |
| 1351 | // Finally, add the control edges to recvs. |
| 1352 | for (int n = 0; n < gdef->node_size(); ++n) { |
| 1353 | NodeDef* ndef = gdef->mutable_node(n); |
| 1354 | if (ndef->op() == "_Recv") { |
| 1355 | const int64 start_time = node_to_start_time[ndef]; |
| 1356 | const int recv_epoch = start_time / resolution; |
| 1357 | if (recv_epoch >= prefetch) { |
| 1358 | NodeDef* dummy = dummys[recv_epoch - prefetch]; |
| 1359 | AddInput(ndef, dummy->name(), Graph::kControlSlot); |
| 1360 | } |
| 1361 | } |
| 1362 | } |
| 1363 | } |
| 1364 | return Status::OK(); |
no test coverage detected