| // Copyright 2024 The IREE Authors |
| // |
| // Licensed under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| #ifndef IREE_COMPILER_DIALECT_LINALGEXT_UTILS_INDEXINGUTILS_H_ |
| #define IREE_COMPILER_DIALECT_LINALGEXT_UTILS_INDEXINGUTILS_H_ |
| |
| #include "mlir/IR/AffineMap.h" |
| |
| namespace mlir::iree_compiler::IREE::LinalgExt { |
| |
| /// Attention has the following shaped inputs: |
| /// |
| /// Q : B x M x K1 |
| /// K : B x K2 x K1 |
| /// V : B x K2 x N |
| /// res: B x M x N |
| /// |
| /// For the purposes of Tiling, Attention can be thought of: |
| /// |
| /// QKT = Q @ K.T |
| /// S = reduce QKT dim=2 keep_dims=True |
| /// att = S @ V |
| /// |
| /// By this defination, K1 and K2 can be seen as reduction dimensions and |
| /// B, M, N can be seen as parallel dimensions. |
| /// |
| /// Generally, K1 and N are really small (64/128), K2 and M are really large |
| /// (16k, 64k, 128k), and B is batch size and depends on input batch size. |
| /// |
| /// Tiling on parallel dimensions is trivial. |
| /// |
| /// Tiling on reduction dimensions on the other hand is much harder. |
| /// TileAndDecomposeAttention has an implementation to tile on K2 dimension |
| /// based on an online softmax technique proposed by Flash Attention V2 |
| /// (https://arxiv.org/abs/2307.08691). |
| /// |
| /// Tiling on K1 is generally not done because it's so small and is non-trivial. |
| class AttentionOpDetail { |
| public: |
| static FailureOr<AttentionOpDetail> get(AffineMap qMap, AffineMap kMap, |
| AffineMap vMap, AffineMap oMap); |
| |
| int64_t getDomainRank() const { return domainRank; } |
| ArrayRef<int64_t> getBatchDims() const { return batch; } |
| ArrayRef<int64_t> getMDims() const { return m; } |
| ArrayRef<int64_t> getK1Dims() const { return k1; } |
| ArrayRef<int64_t> getK2Dims() const { return k2; } |
| ArrayRef<int64_t> getNDims() const { return n; } |
| AffineMap getSMap() const; |
| |
| private: |
| void inferFromIndexingMaps(AffineMap qMap, AffineMap kMap, AffineMap vMap, |
| AffineMap oMap); |
| MLIRContext *getContext() const { return context; } |
| SmallVector<int64_t> batch; |
| SmallVector<int64_t> m; |
| SmallVector<int64_t> k1; |
| SmallVector<int64_t> k2; |
| SmallVector<int64_t> n; |
| MLIRContext *context; |
| int64_t domainRank; |
| }; |
| |
| }; // namespace mlir::iree_compiler::IREE::LinalgExt |
| |
| #endif // IREE_COMPILER_DIALECT_LINALGEXT_UTILS_INDEXINGUTILS_H_ |