// // AttentionBufExecution.hpp // MNN // // Created by MNN on 2024/04/11. // Copyright © 2018, Alibaba Group Holding Limited // #ifdef MNN_SUPPORT_TRANSFORMER_FUSE #ifndef AttentionBufExecution_hpp #define AttentionBufExecution_hpp #include "backend/opencl/execution/image/CommonExecution.hpp" #include "core/OpCommonUtils.hpp" namespace MNN { namespace OpenCL { class KVCacheCLManager { public: KVCacheCLManager(Backend* backend, bool kv_cache); ~KVCacheCLManager() = default; void allocKVCache(const KVMeta* meta, int seqlen); bool reallocKVCache(const KVMeta* meta, int seqlen, bool isExecute = true); void setArgs(int numHead, int kvNumHead, int headDim) { mNumHead = numHead; mKvNumHead = kvNumHead; mHeadDim = headDim; } int pastKvLength() { return mPastLength; } void addKvLength(int seq_len) { mPastLength += seq_len; } int maxLength() { return mMaxLength; } int numHead() { return mNumHead; } const cl::Buffer* key() { return mPastKey.get(); } const cl::Buffer* value() { return mPastValue.get(); } // Called after allocKVCache completes reallocKVCache in resize phase. // onExecute checks this to avoid double-executing realloc/Remove. bool isReallocDone() const { return mReallocDone; } void clearReallocDone() { mReallocDone = false; } private: bool mKVCache; bool mReallocDone = false; const int mExpandChunk = 64; std::shared_ptr mPastKey, mPastValue; int mPastLength = 0, mMaxLength = 0, mNumHead = 0, mKvNumHead = 0, mHeadDim = 0; OpenCLBackend* mOpenCLBackend; int mByte = 4; }; class AttentionBufExecution : public CommonExecution { public: AttentionBufExecution(const MNN::Op* op, Backend* backend, bool outputC4); AttentionBufExecution(std::shared_ptr manager, const MNN::Op* op, Backend* backend); ErrorCode longPrefillResize(const std::vector& inputs, const std::vector& outputs); ErrorCode prefillResize(const std::vector& inputs, const std::vector& outputs); ErrorCode decodeResize(const std::vector& inputs, const std::vector& outputs); ErrorCode UpdateArgs(const std::vector& inputs, const std::vector& outputs); ErrorCode init(); int getExecuteTime(); virtual ~AttentionBufExecution() = default; virtual ErrorCode onResize(const std::vector& inputs, const std::vector& outputs) override; virtual ErrorCode onExecute(const std::vector& inputs, const std::vector& outputs) override; virtual bool onClone(Backend* bn, const Op* op, Execution** dst) override; private: bool mOutputC4 = false; float mAttnScale = 0.0f; KVMeta* mMeta; int getLocalSize(int size, int maxGroupSize); bool mIsDecode = false; void handleKVCache(const std::vector& inputs, const std::vector& outputs); int mPastKvSeqlen = 0; int mKvSeqlen = 0; int mKeyValueMaxlen = 0; int mDecodeTmpMaxlen = 0; uint32_t mMaxWorkGroupSize; OpenCLBackend* mOpenCLBackend; RecordUpdateInfo mRgUpdateInfo; RecordUpdateInfo mRgQUpdateInfo; RecordUpdateInfo mRgMUpdateInfo; RecordUpdateInfo mQkUpdateInfo; RecordUpdateInfo mSoftMaxUpdateInfo; RecordUpdateInfo mRgVUpdateInfo; RecordUpdateInfo mQkvUpdateInfo; int mGlobalWorkSizeQk0 = 0; size_t mQkGlobal_size[2]; size_t mQkPrefillGlobal_size[3]; std::vector mOpRecordUpdateInfo; std::shared_ptr mKVCacheCLManager; std::shared_ptr mTempQK, mTempSoftMax; private: int mAlignQ, mAlignKV, mAlignHDK, mAlignHDN; bool mLongPrefill = false; int mQseqSplitNum = 1; std::shared_ptr mTempQ, mTempK, mTempV, mTempMask, mTempQKV; bool mIsAddMask = false; bool mNeedKvCache = true; bool mHasMask = false; private: std::vector> mKernel_rearrange_vec; std::vector> mKernel_mask_vec; std::vector> mKernel_trans_vec; std::vector> mKernel_clip_vec; std::vector> mKernel_qk_vec; std::vector> mKernel_softmax_vec; std::vector> mKernel_qkv_vec; std::vector> mGwsQkVec; std::vector> mLwsQkVec; std::vector> mGwsSoftMaxVec; std::vector> mLwsSoftMaxVec; std::vector> mGwsQkvVec; std::vector> mLwsQkvVec; std::vector> mGwsRearrgVec; std::vector> mLwsRearrgVec; std::vector> mGwsMaskVec; std::vector> mLwsMaskVec; std::vector> mGwsTransVec; std::vector> mLwsTransVec; std::vector> mGwsClipVec; std::vector> mLwsClipVec; private: std::shared_ptr mKernel_rearrangeQ; std::shared_ptr mKernel_rearrangeV; std::shared_ptr mKernel_rearrangeMask; std::shared_ptr mKernel_rearrange; std::shared_ptr mKernel_qk; std::shared_ptr mKernel_softmax; std::shared_ptr mKernel_qkv; std::vector mGlobalWorkSizeQk; std::vector mLocalWorkSizeQk; std::vector mGlobalWorkSizeSoftMax; std::vector mLocalWorkSizeSoftMax; std::vector mGlobalWorkSizeQkv; std::vector mLocalWorkSizeQkv; std::vector mGlobalWorkSizeRearrgQ; std::vector mLocalWorkSizeRearrgQ; std::vector mGlobalWorkSizeRearrgV; std::vector mLocalWorkSizeRearrgV; std::vector mGlobalWorkSizeRearrg; std::vector mLocalWorkSizeRearrg; std::vector mGlobalWorkSizeRearrgM; std::vector mLocalWorkSizeRearrgM; }; } // namespace OpenCL } // namespace MNN #endif /* AttentionBufExecution_hpp */ #endif /* MNN_SUPPORT_TRANSFORMER_FUSE */