LCOV - code coverage report
Current view: top level - legacy/ascend950/unified_platform/pub_inc - rma_buffer_mgr.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 47.5 % 59 28
Test Date: 2026-08-04 10:52:23 Functions: 100.0 % 14 14

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #ifndef RMA_BUFFER_MGR_V2_H
      12              : #define RMA_BUFFER_MGR_V2_H
      13              : 
      14              : #include <map>
      15              : 
      16              : #include "hccl/base.h"
      17              : 
      18              : namespace Hccl {
      19              : template<typename KeyType, typename BufferType, template <typename...> class M = std::map, typename... MapArgs>
      20              : class RmaBufferMgr {
      21              : public:
      22              :     struct BufferWithRef {
      23              :         // BufferType可以是指针的类型
      24              :         BufferType buffer{};
      25              :         uint64_t ref{};  // 引用计数
      26              : 
      27            3 :         BufferWithRef(BufferType buf, u64 r) : buffer(buf), ref(r) {}
      28              :     };
      29              : 
      30              :     using AddrType = typename KeyType::AddrType;
      31              :     using SizeType = typename KeyType::SizeType;
      32              : 
      33              :     using MapType = M<KeyType, BufferWithRef, MapArgs...>;
      34              :     using Iterator = typename MapType::iterator;
      35              :     using ConstIterator = typename MapType::const_iterator;
      36              : 
      37              :     template<typename... BufferArgs>
      38            3 :     std::pair<Iterator, bool> AddToTree(const KeyType& key, BufferArgs&&... bufferArgs)
      39              :     {
      40            3 :         auto result = intervalTree_.emplace(
      41              :             std::piecewise_construct,
      42            3 :             std::forward_as_tuple(key),
      43            6 :             std::forward_as_tuple(BufferWithRef{ BufferType{ std::forward<BufferArgs>(bufferArgs)... }, 1 })
      44              :         );
      45            3 :         if (!result.second) {
      46            0 :             result.first->second.ref++;
      47              :             // 翻转
      48            0 :             if (result.first->second.ref == 0) {
      49            0 :                 HCCL_ERROR("Error: ref = 0, ref++ flipped");
      50            0 :                 throw std::logic_error("ref++ = 0, ref++ flipped");
      51              :             }
      52            0 :             else if(result.first->second.ref > 1) {
      53            0 :                 HCCL_INFO("Memory is already registered, just increase the reference count, "
      54              :                     "current memory reference count[%llu], %s.", result.first->second.ref, key.ToString().c_str());
      55              :             }
      56              :         }
      57              : 
      58            3 :         return result;
      59              :     }
      60              : 
      61              :     template<typename... BufferArgs>
      62              :     std::pair<Iterator, bool> AddWithoutCheck(const KeyType& key, BufferArgs&&... bufferArgs)
      63              :     {
      64              :         return AddToTree(key, std::forward<BufferArgs>(bufferArgs)...);
      65              :     }
      66              : 
      67              :     // 1.添加成功:输入key是表中某一最相近key的空集。 计数+1,返回添加成功的迭代器,及true
      68              :     // 2.添加已存在:输入key是表中某一最相近key的全集。 计数+1,返回添加该key的迭代器,及false
      69              :     // 3.添加失败:输入key是表中某一个最相近key的交集、子集、超集。返回空迭代器,及false
      70              :     template<typename... BufferArgs>
      71            3 :     std::pair<Iterator, bool> Add(const KeyType& key, BufferArgs&&... bufferArgs)
      72              :     {
      73            3 :         auto overlapResult = CheckOverlap(key);
      74            3 :         if (overlapResult.second) {
      75            0 :             HCCL_ERROR("Error: Buffer key overlaps with existing buffer key.");
      76            0 :             return std::make_pair(intervalTree_.end(), false);
      77              :         }
      78            3 :         return AddToTree(key, std::forward<BufferArgs>(bufferArgs)...);
      79              :     }
      80              : 
      81              :     // 1.查询成功:输入key是表中某一最相近key的子集、全集。 返回true,最相近key的bufferType
      82              :     // 2.查询失败:输入key是表中某一个最相近key的空集、交集。返回false,空bufferType
      83            4 :     std::pair<bool, BufferType> Find(const KeyType& key) const 
      84              :     {
      85            4 :         auto it = intervalTree_.lower_bound(key);
      86            4 :         if (it != intervalTree_.end() && (it->first == key || it->first.IsSuperset(key))) {
      87            4 :             return std::make_pair(true, it->second.buffer);
      88              :         }
      89              : 
      90            0 :         if (it != intervalTree_.begin()) {
      91            0 :             auto prevIt = std::prev(it);
      92            0 :             if (prevIt->first.IsSuperset(key)) {
      93            0 :                 return std::make_pair(true, prevIt->second.buffer);
      94              :             }
      95            0 :             if (it != intervalTree_.end()) {
      96            0 :                 HCCL_WARNING("Key[%s] not found. The near key is [%s] or [%s].",
      97              :                     key.ToString().c_str(), it->first.ToString().c_str(), prevIt->first.ToString().c_str());
      98              :             } else {
      99            0 :                 HCCL_WARNING("Key[%s] not found. The near key is [%s]",
     100              :                     key.ToString().c_str(), prevIt->first.ToString().c_str());
     101              :             }
     102              :         } else {
     103            0 :             if (it != intervalTree_.end()) {
     104            0 :                 HCCL_WARNING("Key[%s] not found. The near key is [%s]",
     105              :                     key.ToString().c_str(), it->first.ToString().c_str());
     106              :             } else {
     107            0 :                 HCCL_WARNING("Key[%s] not found. There is no key in table.",
     108              :                     key.ToString().c_str());            
     109              :             }
     110              :         }
     111              : 
     112            0 :         return std::make_pair(false, BufferType{}); // 未找到
     113              :     }
     114              : 
     115              :     // 1.删除成功:输入key是表中某一最相近key的全集。 计数-1且之后为0。  返回true
     116              :     // 2.删除引用数-1但未删除:输入key是表中某一最相近key的全集。 计数-1且之后大于0。 返回false
     117              :     // 3.删除失败:输入key是表中某一个最相近key的交集、子集、超集、空集。——抛出NOT_FOUND异常
     118            3 :     bool Del(const KeyType& key)
     119              :     {
     120            3 :         auto it = intervalTree_.find(key);
     121            3 :         if (it == intervalTree_.end()) {
     122            0 :             HCCL_ERROR("Error: Buffer key not found.");
     123            0 :             throw std::out_of_range("Del NOT_FOUND");
     124              :         }
     125              : 
     126            3 :         if (--(it->second.ref) == 0) {
     127            3 :             intervalTree_.erase(it);
     128            3 :             return true;
     129              :         }
     130              :         // 引用计数大于0,不删除
     131            0 :         HCCL_RUN_INFO("Memory reference count is larger than 0, (used by other RemoteRank), do not deregister memory."
     132              :              "current memory reference count[%llu], %s.", it->second.ref, key.ToString().c_str());
     133            0 :         return false;
     134              :     }
     135              : 
     136              :     bool IsInTree(const KeyType& key)
     137              :     {
     138              :         auto it = intervalTree_.find(key);
     139              :         if (it == intervalTree_.end()) {
     140              :             return false;
     141              :         }
     142              :         return true;
     143              :     }
     144              : 
     145            3 :     ConstIterator End()
     146              :     {
     147            3 :         return intervalTree_.end();
     148              :     }
     149              : 
     150              : private:
     151              :     MapType intervalTree_;
     152              : 
     153            3 :     std::pair<Iterator, bool> CheckOverlap(const KeyType& key)
     154              :     {
     155            3 :         auto it = intervalTree_.lower_bound(key);
     156            3 :         if (it != intervalTree_.end()) {
     157              :             // 情况1:addr_ == it->first.addr_ && size_ == it->first.size_
     158            0 :             if (it->first == key) {
     159            0 :                 return std::make_pair(it, false);
     160              :             }
     161              : 
     162              :             // 情况2:addr_ == it->first.addr_ && size_ < it->first.size_。it->first.IsSubset(key)非必须
     163              :             // 情况3:addr_ < it->first.addr_
     164            0 :             if (it->first.IsSuperset(key) || it->first.IsIntersect(key)) { 
     165            0 :                 return std::make_pair(it, true);
     166              :             }
     167              :         }
     168              : 
     169              :         // 剩下的是空集
     170            3 :         if (it != intervalTree_.begin()) {
     171            0 :             auto prevIt = std::prev(it);
     172              :             // 情况4:addr_ > prevIt->first.addr_
     173              :             // 情况5: 1) addr_ > prevIt->first.addr_的子集情况;
     174              :             // 2) addr_ == prevIt->first.addr_,size_ > prevIt->first.size
     175            0 :             if (prevIt->first.IsIntersect(key) || prevIt->first.IsSubset(key) || prevIt->first.IsSuperset(key)) {
     176            0 :                 return std::make_pair(prevIt, true);
     177              :             }
     178              : 
     179              :             // 6. 剩下的是空集
     180            0 :             return std::make_pair(prevIt, false);
     181              :         }
     182              : 
     183              :         // 剩下的是空集
     184            3 :         return std::make_pair(it, false);
     185              :     }
     186              : };
     187              : }
     188              : 
     189              : #endif
        

Generated by: LCOV version 2.0-1