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 : #include "aicpu_task_cache.h"
12 :
13 : #include <cstring>
14 :
15 : #include "aicpu_task_utils.h"
16 : #include "log.h"
17 :
18 : namespace hcomm {
19 :
20 71 : AicpuTaskCache::AicpuTaskCache(const uint64_t maxCacheBytes) : cacheBytes_(0), maxCacheBytes_(maxCacheBytes)
21 : {
22 71 : HCCL_RUN_INFO(
23 : "[AicpuTaskCache][AicpuTaskCache] create aicpu task cache at 0x%016llx: maxCacheBytes[%llu]", this,
24 : maxCacheBytes_);
25 71 : }
26 :
27 71 : AicpuTaskCache::~AicpuTaskCache()
28 : {
29 71 : const uint64_t entryCnt = cacheHashMap_.size();
30 83 : for (CacheHashMap::const_iterator constIter = cacheHashMap_.cbegin(); constIter != cacheHashMap_.cend();
31 12 : ++constIter) {
32 12 : AicpuTaskCacheEntry* entryPtr = constIter->second;
33 12 : if (UNLIKELY(entryPtr == nullptr)) {
34 0 : HCCL_ERROR("[AicpuTaskCache][~AicpuTaskCache] entryPtr is nullptr");
35 0 : continue;
36 : }
37 :
38 12 : delete entryPtr;
39 12 : entryPtr = nullptr;
40 : }
41 :
42 71 : HCCL_RUN_INFO(
43 : "[AicpuTaskCache][~AicpuTaskCache] release aicpu task cache at 0x%016llx: "
44 : "entryCnt[%zu], cacheBytes_[%llu]",
45 : this, entryCnt, cacheBytes_);
46 71 : }
47 :
48 32 : HcclResult AicpuTaskCache::FindEntry(const char* cacheTag, AicpuTaskCacheEntry** entryPtrPtr) const
49 : {
50 32 : CHK_PTRPTR_NULL(entryPtrPtr);
51 :
52 31 : bool reportCacheHit = false;
53 : {
54 31 : std::shared_lock<std::shared_timed_mutex> lock(cacheMtx_); // 读锁
55 62 : CacheHashMap::const_iterator constIter = cacheHashMap_.find(cacheTag);
56 31 : if (constIter != cacheHashMap_.cend()) {
57 22 : *entryPtrPtr = constIter->second;
58 22 : CHK_PTR_NULL(*entryPtrPtr);
59 22 : reportCacheHit = !cacheHitRunInfoPrinted_;
60 22 : HCCL_INFO("[AicpuTaskCache][FindEntry] find cache entry for cacheTag[%s]", cacheTag);
61 : } else {
62 9 : *entryPtrPtr = nullptr;
63 9 : HCCL_INFO("[AicpuTaskCache][FindEntry] not find cache entry for cacheTag[%s]", cacheTag);
64 : }
65 31 : }
66 :
67 31 : if (UNLIKELY(reportCacheHit)) {
68 7 : std::lock_guard<std::shared_timed_mutex> lock(cacheMtx_); // 写锁后二次确认
69 7 : if (!cacheHitRunInfoPrinted_) {
70 7 : cacheHitRunInfoPrinted_ = true;
71 7 : HCCL_RUN_INFO(
72 : "[AicpuTaskCacheManager][ReportCacheHitOnce] aicpu task cache hit for the first time in "
73 : "current process, cacheTag[%s]",
74 : cacheTag);
75 : }
76 7 : }
77 :
78 31 : return HCCL_SUCCESS;
79 : }
80 :
81 29 : HcclResult AicpuTaskCache::AddEntry(const char* cacheTag, AicpuTaskCacheEntry** entryPtrPtr)
82 : {
83 29 : std::lock_guard<std::shared_timed_mutex> lock(cacheMtx_); // 写锁
84 :
85 29 : CHK_PTRPTR_NULL(entryPtrPtr);
86 :
87 : // 检查cache容量
88 27 : if (cacheBytes_ >= maxCacheBytes_) {
89 4 : HCCL_INFO(
90 : "[AicpuTaskCache][AddEntry] cacheBytes[%llu] >= maxCacheBytes[%llu] -> aicpu task cache is full "
91 : "not add cache entry for cacheTag[%s]",
92 : cacheBytes_, maxCacheBytes_, cacheTag);
93 4 : *entryPtrPtr = nullptr;
94 4 : if (!cacheFullRunInfoPrinted_) {
95 3 : cacheFullRunInfoPrinted_ = true;
96 3 : HCCL_RUN_INFO(
97 : "[AicpuTaskCacheManager][ReportCacheFullOnce] aicpu task cache is full for the first time "
98 : "in current process, cacheTag[%s]",
99 : cacheTag);
100 : }
101 4 : return HCCL_SUCCESS;
102 : }
103 :
104 : // 打印cache容量
105 23 : HCCL_INFO(
106 : "[AicpuTaskCache][AddEntry] cacheBytes[%llu] (maxCacheBytes[%llu]) -> aicpu task cache not full", cacheBytes_,
107 : maxCacheBytes_);
108 :
109 46 : CacheHashMap::iterator iter = cacheHashMap_.find(cacheTag);
110 23 : CHK_PRT_RET(
111 : iter != cacheHashMap_.end(),
112 : HCCL_ERROR("[AicpuTaskCache][AddEntry] cache entry for cacheTag[%s] exists", cacheTag), HCCL_E_INTERNAL);
113 :
114 : // 初始化new cache entry
115 22 : AicpuTaskCacheEntry* newCacheEntryPtr = (new (std::nothrow) AicpuTaskCacheEntry());
116 22 : CHK_PTR_NULL(newCacheEntryPtr);
117 :
118 : // 添加到cache
119 22 : std::pair<CacheHashMap::iterator, bool> insertResult = cacheHashMap_.emplace(cacheTag, newCacheEntryPtr);
120 22 : if (UNLIKELY(!(insertResult.second))) {
121 0 : HCCL_ERROR("[AicpuTaskCache][AddEntry] fail to insert a new cache entry for cacheTag[%s]", cacheTag);
122 :
123 0 : delete newCacheEntryPtr;
124 0 : newCacheEntryPtr = nullptr;
125 :
126 0 : return HCCL_E_INTERNAL;
127 : } else {
128 22 : HCCL_INFO(
129 : "[AicpuTaskCache][AddEntry] add a new cache entry for cacheTag[%s] cacheHashMap_.size[%zu]", cacheTag,
130 : cacheHashMap_.size());
131 :
132 22 : iter = insertResult.first;
133 22 : *entryPtrPtr = iter->second;
134 22 : CHK_PTR_NULL(*entryPtrPtr);
135 : }
136 :
137 22 : return HCCL_SUCCESS;
138 29 : }
139 :
140 10 : HcclResult AicpuTaskCache::IncCacheBytes(const char* cacheTag, const uint64_t entryBytes)
141 : {
142 10 : std::lock_guard<std::shared_timed_mutex> lock(cacheMtx_); // 写锁
143 :
144 10 : cacheBytes_ += entryBytes;
145 10 : cacheBytes_ += strlen(cacheTag);
146 10 : cacheBytes_ += sizeof(AicpuTaskCacheEntry*);
147 :
148 10 : HCCL_INFO(
149 : "[AicpuTaskCache][IncCacheBytes] add entryBytes[%llu] + cacheTag[%zu] + AicpuTaskCacheEntry*[%llu] -> "
150 : "cacheBytes[%llu] (maxCacheBytes[%llu])",
151 : entryBytes, strlen(cacheTag), sizeof(AicpuTaskCacheEntry*), cacheBytes_, maxCacheBytes_);
152 :
153 10 : return HCCL_SUCCESS;
154 10 : }
155 :
156 119 : HcclResult AicpuTaskCache::ClearEntry(const char* cacheTag)
157 : {
158 119 : std::lock_guard<std::shared_timed_mutex> lock(cacheMtx_); // 写锁
159 :
160 238 : CacheHashMap::iterator iter = cacheHashMap_.find(cacheTag);
161 119 : if (iter != cacheHashMap_.end()) {
162 10 : HCCL_INFO("[AicpuTaskCache][ClearEntry] clear cache entry for cacheTag[%s]", cacheTag);
163 :
164 : // 获取entry bytes
165 10 : AicpuTaskCacheEntry* entryPtr = iter->second;
166 10 : CHK_PTR_NULL(entryPtr);
167 10 : const uint64_t entryBytes = entryPtr->GetEntryBytes();
168 :
169 : // 计算clear bytes
170 10 : const uint64_t clearBytes = entryBytes + strlen(cacheTag) + sizeof(AicpuTaskCacheEntry*);
171 :
172 : // 更新cache bytes
173 10 : if (cacheBytes_ > clearBytes) {
174 2 : cacheBytes_ -= clearBytes;
175 : } else {
176 8 : cacheBytes_ = 0;
177 : }
178 :
179 10 : HCCL_INFO(
180 : "[AicpuTaskCache][ClearEntry] dec entryBytes[%llu] + cacheTag[%zu] + AicpuTaskCacheEntry*[%llu] -> "
181 : "cacheBytes[%llu] (maxCacheBytes[%llu])",
182 : entryBytes, strlen(cacheTag), sizeof(AicpuTaskCacheEntry*), cacheBytes_, maxCacheBytes_);
183 :
184 : // 释放cache entry
185 10 : delete entryPtr;
186 10 : entryPtr = nullptr;
187 10 : iter->second = nullptr;
188 :
189 : // 释放cacheTag-entryPtr mapping
190 10 : cacheHashMap_.erase(iter);
191 : } else {
192 109 : HCCL_INFO("[AicpuTaskCache][ClearEntry] not find cache entry for cacheTag[%s]", cacheTag);
193 : }
194 :
195 119 : return HCCL_SUCCESS;
196 119 : }
197 :
198 : } // namespace hcomm
|