MCPcopy Create free account
hub / github.com/Oneflow-Inc/oneflow / ScheduleLoop

Method ScheduleLoop

oneflow/core/vm/virtual_machine.cpp:330–368  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

328} // namespace
329
330void VirtualMachine::ScheduleLoop(const std::function<void()>& Initializer) {
331 SyncVmModeGuard guard(SyncVmMode::kEnable);
332 Initializer();
333 MultiThreadScheduleCtx schedule_ctx{};
334 while (pending_notifier_.WaitAndClearNotifiedCnt() == kNotifierStatusSuccess) {
335 OF_PROFILER_RANGE_GUARD("VirtualMachine::ScheduleLoop");
336 auto start = std::chrono::steady_clock::now();
337 static constexpr int kWorkingMicroseconds = 1000;
338 // Every time this thread wakes up, engine_ is scheduled for about `kWorkingMicroseconds`.
339 // The cost of os thread switching is about 5-10 microseconds. Doing more scheduling in
340 // a single waiting up can reach higher performance.
341 do {
342 // Use SchedulerThreadUnsafeEmpty to avoid acquiring mutex lock.
343 // It's safe to use SchedulerThreadUnsafeEmpty here. pending_notifier_.notified_cnt_ will be
344 // greater than zero when inconsistency between
345 // engine_->pending_instruction_list.list_head_.list_head_.container_ and
346 // engine_->pending_instruction_list.list_head_.list_head_.size_ occured. hence the pending
347 // instructions
348 // will get handled in the next iteration.
349 // VirtualMachine::Receive may be less effiencient if the thread safe version
350 // `engine_->SchedulerEmpty()`
351 // used
352 // here, because VirtualMachine::ScheduleLoop is more likely to get the mutex lock.
353 do {
354 const size_t total_inserted = engine_->total_inserted_instruction_cnt();
355 const size_t total_erased = engine_->total_erased_instruction_cnt();
356 engine_->Schedule(schedule_ctx);
357 if (ThreadLocalEnvBool<ONEFLOW_VM_ENABLE_SCHEDULE_YIELD>()
358 && total_inserted == engine_->total_inserted_instruction_cnt()
359 && total_erased == engine_->total_erased_instruction_cnt()) { // nothing handled.
360 std::this_thread::yield();
361 }
362 } while (!engine_->SchedulerThreadUnsafeEmpty());
363 } while (MicrosecondsFrom(start) < kWorkingMicroseconds);
364 }
365 ScheduleUntilVMEmpty(engine_.Mutable(), schedule_ctx);
366 CHECK_JUST(CloseWorkerThreads());
367 scheduler_stopped_ = true;
368}
369
370intrusive::shared_ptr<vm::Dependence> VirtualMachine::FindOrCreateScheduleDependence(
371 Symbol<Stream> stream) {

Callers

nothing calls this directly

Calls 8

MicrosecondsFromFunction · 0.85
ScheduleUntilVMEmptyFunction · 0.85
ScheduleMethod · 0.45
MutableMethod · 0.45

Tested by

no test coverage detected