Replies: 1 comment 3 replies
-
|
@efric this is what I understood from here
For case 1, these will also require "natural/canonical/unpacked form" right? (At the very least, what I can see from the LLVM lowerings is that for the matvec case, the operation would need to have the reduction dimension to be innermost. else if (isParallelIterator(iteratorTypes[0]) &&
isReductionIterator(iteratorTypes[1])) {
//
// One outer parallel, one inner reduction (matvec flavor)
//Regarding the PRs I worked on (which attempted to split the ChainToFMA pattern and make them fit into the "optimize", "flatten", "unroll", "lower" pattern. The "optimize" part here could be done I think for both of these, it essentially just establishes the invariant that all reduction dimensions are innermost. For both of these, we then can flatten them into 2-D and 1-D (for ChainToFMA since it is acting on matmat, then we flatten both operands to 2-D). For unrolling, we can call lowerParallel to unroll parallel dimensions (or something similar that ideally should be added to the ND legalization pass) And finally, the lowering for vector.contract would depend on whether it is a matmat (fma) or a matvec and the specific types (dot or fma + other ops). This is different from what you are proposing, but I would like to hear from @Groverkss as well. My understanding about this legalization pass is that we can also hard code lowerings before the 1-D unrolling as the legalization would have just some "unrollings" which are general and work for all backends. But anything that is backend specific should happen before this 1-D legalization. I'm still not sure about where that split is (backend specific vs general enough). |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This discussion proposes a set of vector lowering related changes motivated by the work on matvec improvements for Qwen MoE decode shapes. The proposal here is intentional about the codegen specific details, please see #24165 for the full context on this work.
Context
The proposed policy for matvec-like per thread vector lowering is (post vector distribute):
For full details, please see #24165. Below serves a short description for the semantics of chain dot and chain FMA.
Chain Dot:
In this strategy, we reduce within each row/source vector load with respect to a per thread vector e.g,
vector<4x8xf16>.Using
v_dot2as an example:There are no
v_dotinstructions that accept 32bit operands across any AMDGPU architecture, so when that is the case, we defer to the current lowering, which leverages chain FMA. This is still better than the generic lowering, which does packed mul across each row then v_add to sum the results.In short, the difference between dot and packed fma in the semantics is the following:
Compared to the dot chain, the instruction dependency is twice as long for packed fma (on f16). If packed instructions are available, then because we are retrieving data from different vector loads, we need
v_movsin preparation for thepk_fmas.Early testing results using
dotvsfmaon RDNA3 for Qwen MoE decode shapes (pre lowering config adjustments)However, I expect the benefits to span all architectures which support
v_dotHigh level design
vector.contract/vector.multi_reduction:Currently, we construct the lowering to chain FMA in
LLVMGPUVectorLoweringvia our ownContractToChainFMA. However, if we follow theVectorContractLowering::OuterProductstrategy, we will actually naturally lower to the same output following: chain emission into fma. The reason why this wasn't picked up even though we pickVectorContractLowering::OuterProductas our strategy is because post vector distribute, relevant ops such asvector.contractandvector.multi_reductionare in their expanded forms.This makes it unable to match the supported strategies in
VectorContractLowering::OuterProduct. However, if we were able to able to use its natural form while preserving vector distribution semantics:Then we can remove
ContractToChainFMAaltogether and depend on upstream for lowering to the chain FMA strategy followingVectorContractLowering::OuterProductnaturally.vector.contractloweringOnce the the contract is in the canonical shape, the decision should be made per contract
This is because
VectorContractLowering::Doteventually decomposes to a series of 1Dvector.reductionwhich we can then (next section) match to the dot chain.VectorContractLowering::OuterProducteventually to chain FMA naturally as mentioned above.The current upstream API selects one preferred strategy globally:
Which isn't enough to express the policy we'd like. The proposed extension is something to the liens of
And then in IREE we can express this directly as roughly
amdgpu.dotThis is the most straightforward implementation, we will just match 1D
vector.reduction <add>intoamdgpu.dotchain (of course, if only feasible in terms of vector length, architecture, type, etc).This can then run some time after
LLVMGPUVectorLowering, specifically in this blockseems reasonable.
cc some folks for feedback on reasonableness of this approach at a high level:
@Groverkss @amd-eochoalo @kuhar @krzysz00
Overall, this direction is more involved than adding a monolithic iree local
ContractToChainDotpattern, but I think it is better aligned with the more “composable, intentional” vector lowering direction that Erick and Kunwar has been working on. It also lets us reuse more upstream lowering infrastructure instead of adding another target specific contract lowering path in IREE. Step 1 should also be useful beyond the current matvec contracts as it reveals what may currently be hidden behind the distributed layout form and therefore deferred to generic lowering when it doesn't have to.Beta Was this translation helpful? Give feedback.
All reactions