| 1336 | |
| 1337 | template <class PropagatorStateType> |
| 1338 | void ExecutorState<PropagatorStateType>::ScheduleReady( |
| 1339 | TaggedNodeSeq* ready, TaggedNodeReadyQueue* inline_ready) { |
| 1340 | DCHECK(!ready->empty()); |
| 1341 | |
| 1342 | int64_t scheduled_nsec = 0; |
| 1343 | if (stats_collector_) { |
| 1344 | scheduled_nsec = nodestats::NowInNsec(); |
| 1345 | } |
| 1346 | |
| 1347 | { |
| 1348 | const TaggedNode* curr_expensive_node = nullptr; |
| 1349 | TaggedNodeSeq expensive_nodes; |
| 1350 | if (inline_ready == nullptr) { |
| 1351 | // Schedule to run all the ready ops in thread pool. |
| 1352 | for (auto& tagged_node : *ready) { |
| 1353 | RunTask([=]() { Process(tagged_node, scheduled_nsec); }); |
| 1354 | } |
| 1355 | } else { |
| 1356 | for (auto& tagged_node : *ready) { |
| 1357 | const NodeItem& item = *tagged_node.node_item; |
| 1358 | if (tagged_node.get_is_dead() || !kernel_stats_->IsExpensive(item)) { |
| 1359 | // Inline this inexpensive node. |
| 1360 | inline_ready->push_back(tagged_node); |
| 1361 | } else { |
| 1362 | if (curr_expensive_node) { |
| 1363 | // push_back expensive nodes, we will schdule them later. |
| 1364 | expensive_nodes.push_back(*curr_expensive_node); |
| 1365 | } |
| 1366 | curr_expensive_node = &tagged_node; |
| 1367 | } |
| 1368 | } |
| 1369 | } |
| 1370 | if (curr_expensive_node) { |
| 1371 | if (inline_ready->empty()) { |
| 1372 | inline_ready->push_back(*curr_expensive_node); |
| 1373 | } else { |
| 1374 | // There are inline nodes to run already. We dispatch this expensive |
| 1375 | // node to other thread. |
| 1376 | expensive_nodes.push_back(*curr_expensive_node); |
| 1377 | } |
| 1378 | } |
| 1379 | |
| 1380 | if (!expensive_nodes.empty()) { |
| 1381 | if (expensive_nodes.size() < kInlineScheduleReadyThreshold) { |
| 1382 | for (auto& tagged_node : expensive_nodes) { |
| 1383 | RunTask(std::bind(&ExecutorState::Process, this, tagged_node, |
| 1384 | scheduled_nsec)); |
| 1385 | } |
| 1386 | } else { |
| 1387 | // There are too many ready expensive nodes. Schedule them in child |
| 1388 | // threads. |
| 1389 | // TODO(fishx): Apply the same optimization to cheap ops as well since |
| 1390 | // executing lots of cheap ops in one thread can potentially be the |
| 1391 | // bottleneck as well. |
| 1392 | auto it = expensive_nodes.begin(); |
| 1393 | while (it < expensive_nodes.end()) { |
| 1394 | auto end = it; |
| 1395 | std::advance(end, kInlineScheduleReadyThreshold); |
nothing calls this directly
no test coverage detected