CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
192 lines
7.8 KiB
C++
192 lines
7.8 KiB
C++
// Copyright Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#pragma once
|
|
|
|
#include <rocRoller/CodeGen/Instruction.hpp>
|
|
#include <rocRoller/Context.hpp>
|
|
#include <rocRoller/GPUArchitecture/GPUInstructionInfo.hpp>
|
|
#include <rocRoller/Scheduling/Scheduling.hpp>
|
|
|
|
namespace rocRoller
|
|
{
|
|
namespace Scheduling
|
|
{
|
|
template <typename T>
|
|
using WaitQueueMap = std::unordered_map<GPUWaitQueue, T>;
|
|
|
|
using WaitQueueRegisters = std::array<Register::ValuePtr, Instruction::MaxExtraRegisters>;
|
|
|
|
using WaitCntQueues = WaitQueueMap<std::vector<WaitQueueRegisters>>;
|
|
|
|
/**
|
|
* @brief This struct is used to store the _unallocated_ state of the waitcnt queues.
|
|
*
|
|
*/
|
|
struct WaitcntState
|
|
{
|
|
public:
|
|
WaitcntState();
|
|
|
|
WaitcntState(WaitQueueMap<bool> const& needsWaitZero,
|
|
WaitQueueMap<GPUWaitQueueType> const& typeInQueue,
|
|
WaitCntQueues const& instruction_queues_with_alloc);
|
|
|
|
bool operator==(const WaitcntState& rhs) const = default;
|
|
|
|
/**
|
|
* @brief Returns true if this WaitcntState and the provided WaitcntState are safe
|
|
* to see at a label and a branch that goes to that label.
|
|
*
|
|
* @param labelState
|
|
*/
|
|
void assertSafeToBranchTo(const WaitcntState& labelState,
|
|
std::string const& label) const;
|
|
|
|
private:
|
|
// These members are duplicates of the waitcntobserver members, except we're storing a
|
|
// std::vector<Register::RegisterId> for the registers instead of
|
|
// std::array<Register::ValuePtr, Instruction::MaxDstRegisters>
|
|
// so that we don't maintain the allocations.
|
|
WaitQueueMap<std::vector<std::vector<Register::RegisterId>>> m_instructionQueues;
|
|
|
|
WaitQueueMap<bool> m_needsWaitZero;
|
|
WaitQueueMap<GPUWaitQueueType> m_typeInQueue;
|
|
};
|
|
|
|
class WaitcntObserver
|
|
{
|
|
public:
|
|
WaitcntObserver();
|
|
|
|
WaitcntObserver(ContextPtr context);
|
|
|
|
InstructionStatus peek(Instruction const& inst) const;
|
|
|
|
void modify(Instruction& inst) const;
|
|
|
|
/**
|
|
* This function handles updating the waitqueues and flags when an instruction is scheduled.
|
|
* 1. If there is a wait included in the instruction, apply it to the queues.
|
|
* 2. Add n copies of the instruction's registers to all the queues that it affects, where n is its waitcnt.
|
|
* 3. If the wait is zero, or the queue already has an instruction of a different type, set the m_needsWaitZero flag.
|
|
* 4. Set the instruction type flag for each queue the instruction affects.
|
|
**/
|
|
void observe(Instruction const& inst);
|
|
|
|
constexpr static bool required(GPUArchitectureTarget const& target);
|
|
|
|
private:
|
|
std::weak_ptr<Context> m_context;
|
|
|
|
WaitCntQueues m_instructionQueues;
|
|
|
|
// This member tracks a flag for each queue which indicates that a waitcnt 0 is needed.
|
|
WaitQueueMap<bool> m_needsWaitZero;
|
|
|
|
// This member tracks the instruction type that is currently in a given queue.
|
|
// If there are ever multiple instruction types in a queue, and a register intersection occurs,
|
|
// a waitcnt 0 is required.
|
|
WaitQueueMap<GPUWaitQueueType> m_typeInQueue;
|
|
|
|
std::string m_barrierOpcode;
|
|
|
|
bool m_includeExplanation;
|
|
bool m_displayState;
|
|
|
|
// This member tracks, for every label, what the waitcnt state was when that label was encountered.
|
|
std::unordered_map<std::string, WaitcntState> m_labelStates;
|
|
|
|
// This member tracks, for every label, what the waitcnt state is everywhere a branch instruction targets that label.
|
|
std::unordered_map<std::string, std::vector<WaitcntState>> m_branchStates;
|
|
|
|
/**
|
|
* This function updates the given wait queue by applying the given waitcnt.
|
|
**/
|
|
void applyWaitToQueue(int waitCnt, GPUWaitQueue queue);
|
|
|
|
/**
|
|
* Determines if there's a waitcount that's needed due to a barrier if the
|
|
* alwaysWaitZeroBeforeBarrier kernelOption is set.
|
|
*
|
|
* @param inst
|
|
* @param[out] explanation is an output parameter for an explanation of the wait count required.
|
|
* @return WaitCount
|
|
*/
|
|
WaitCount computeZeroBarrierWaitCount(Instruction const& inst,
|
|
std::string* explanation = nullptr) const;
|
|
|
|
/**
|
|
* Determines if there's a waitcount that's needed due to the instruction having a
|
|
* WaitCount::SyncQueue() wait attached.
|
|
*
|
|
* @param inst
|
|
* @param[out] explanation is an output parameter for an explanation of the wait count required.
|
|
* @return WaitCount
|
|
*/
|
|
WaitCount computeSyncQueueWaitCount(Instruction const& inst,
|
|
std::string* explanation = nullptr) const;
|
|
|
|
/**
|
|
* Determines if there's a waitcount that's needed due to a register dependency
|
|
* intersection.
|
|
*
|
|
* It searches backwards through each wait queue looking for registers that
|
|
* intersect with the new instruction.
|
|
* If an intersection is found a wait is inserted for the intersection location
|
|
* or 0 if the wait_zero flag is set for the queue.
|
|
*
|
|
* @param inst
|
|
* @param[out] explanation is an output parameter for an explanation of the wait count required.
|
|
* @return WaitCount
|
|
*/
|
|
WaitCount computeRegisterWaitCount(Instruction const& inst,
|
|
std::string* explanation = nullptr) const;
|
|
|
|
/**
|
|
* @brief This function determines if an instruction needs a wait count inserted before
|
|
* it and provides an explanation as to why it's needed.
|
|
*
|
|
* @param inst
|
|
* @param[out] explanation is an output parameter for an explanation of the wait count required.
|
|
* @return WaitCount
|
|
*/
|
|
WaitCount computeWaitCount(Instruction const& inst,
|
|
std::string* explanation = nullptr) const;
|
|
|
|
/**
|
|
* @brief Get a string representation of the state of the Wait Queues
|
|
*
|
|
* @return std::string
|
|
*/
|
|
std::string getWaitQueueState() const;
|
|
|
|
/**
|
|
* @brief Add the current waitcnt state to the label state tracker.
|
|
*
|
|
* @param label the currently encountered label.
|
|
*/
|
|
void addLabelState(std::string const& label);
|
|
|
|
/**
|
|
* @brief Add the current waitcnt state to the branch state tracker.
|
|
*
|
|
* @param label the label currently being branched to.
|
|
*/
|
|
void addBranchState(std::string const& label);
|
|
|
|
/**
|
|
* @brief Assert that all branch and label waitcnt states are consistent.
|
|
*
|
|
* This function checks that the waitcnt state at every branch to a label is the same
|
|
* as the waitcnt state when that label was encountered.
|
|
*/
|
|
void assertLabelConsistency();
|
|
};
|
|
|
|
static_assert(CObserverConst<WaitcntObserver>);
|
|
}
|
|
}
|
|
|
|
#include <rocRoller/Scheduling/Observers/WaitcntObserver_impl.hpp>
|