// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include namespace rocRoller { namespace Scheduling { static_assert(Component::Component); CooperativeScheduler::CooperativeScheduler(ContextPtr ctx, CostFunction cmp) : Scheduler{ctx} { m_cost = Component::Get(cmp, m_ctx); } bool CooperativeScheduler::Match(Argument arg) { return std::get<0>(arg) == SchedulerProcedure::Cooperative; } std::shared_ptr CooperativeScheduler::Build(Argument arg) { if(!Match(arg)) return nullptr; return std::make_shared(std::get<2>(arg), std::get<1>(arg)); } std::string CooperativeScheduler::name() const { return Name; } bool CooperativeScheduler::supportsAddingStreams() const { return true; } Generator CooperativeScheduler::operator()(std::vector>& seqs) { std::vector::iterator> iterators; if(seqs.empty()) co_return; size_t numSeqs = 0; size_t idx = 0; while(true) { co_yield handleNewNodes(seqs, iterators); numSeqs = seqs.size(); float currentCost = 0; bool lockedOut = false; if(iterators[idx] != seqs[idx].end()) { auto const& inst = *iterators[idx]; lockedOut = !m_lockstate.isSchedulable(inst, idx); currentCost = (*m_cost)(inst); } if(iterators[idx] == seqs[idx].end() || lockedOut || currentCost > 0) { size_t origIdx = idx; float minCost = std::numeric_limits::max(); int minCostIdx = -1; if(iterators[idx] != seqs[idx].end() && !lockedOut) { minCost = currentCost; minCostIdx = idx; } idx = (idx + 1) % numSeqs; while(idx != origIdx) { if(iterators[idx] != seqs[idx].end()) { auto const& inst = *iterators[idx]; lockedOut = !m_lockstate.isSchedulable(inst, idx); currentCost = (*m_cost)(inst); if(!lockedOut && currentCost < minCost) { minCost = currentCost; minCostIdx = idx; } } if(minCost == 0) break; idx = (idx + 1) % numSeqs; } if(minCostIdx == -1) break; idx = minCostIdx; } co_yield yieldFromStream(iterators[idx], idx); } } } }