已合并
添加PCIE Through需求相关内部接口 #727
ren-botao创建于 11 天前
添加PCIE Through需求相关内部接口 #727
已合并
共 5 个文件变更+141-1
| @@ -24,6 +24,7 @@ struct OpConfigInfo { | |||
| 24 | isDeterministicOn_ = rhs.isDeterministicOn_; | 24 | isDeterministicOn_ = rhs.isDeterministicOn_; |
| 25 | isOpDumpEnable_ = rhs.isOpDumpEnable_; | 25 | isOpDumpEnable_ = rhs.isOpDumpEnable_; |
| 26 | deterministicLevel_ = rhs.deterministicLevel_; | 26 | deterministicLevel_ = rhs.deterministicLevel_; |
| 27 | + usePcieAddr = rhs.usePcieAddr; | ||
| 27 | } | 28 | } |
| 28 | OpConfigInfo& operator=(const OpConfigInfo& rhs) | 29 | OpConfigInfo& operator=(const OpConfigInfo& rhs) |
| 29 | { | 30 | { |
| @@ -33,6 +34,7 @@ struct OpConfigInfo { | |||
| 33 | isDeterministicOn_ = rhs.isDeterministicOn_; | 34 | isDeterministicOn_ = rhs.isDeterministicOn_; |
| 34 | isOpDumpEnable_ = rhs.isOpDumpEnable_; | 35 | isOpDumpEnable_ = rhs.isOpDumpEnable_; |
| 35 | deterministicLevel_ = rhs.deterministicLevel_; | 36 | deterministicLevel_ = rhs.deterministicLevel_; |
| 37 | + usePcieAddr = rhs.usePcieAddr; | ||
| 36 | } | 38 | } |
| 37 | return *this; | 39 | return *this; |
| 38 | } | 40 | } |
| @@ -42,7 +44,8 @@ struct OpConfigInfo { | |||
| 42 | bool isDeterministicOn_{false}; | 44 | bool isDeterministicOn_{false}; |
| 43 | bool isOpDumpEnable_{false}; | 45 | bool isOpDumpEnable_{false}; |
| 44 | uint8_t deterministicLevel_{0}; | 46 | uint8_t deterministicLevel_{0}; |
| 45 | - uint8_t reserved[5] = {0}; | 47 | + bool usePcieAddr{false}; |
| 48 | + uint8_t reserved[4] = {0}; | ||
| 46 | }; | 49 | }; |
| 47 | 50 | ||
| 48 | } // namespace op | 51 | } // namespace op |
| @@ -0,0 +1,29 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace op { | ||
| 17 | +namespace internal { | ||
| 18 | + | ||
| 19 | +// 全局只调一次(内部 std::call_once); | ||
| 20 | +aclnnStatus InitPcieThroughInfo(); | ||
| 21 | + | ||
| 22 | +bool IsPcieThroughEnabled(); | ||
| 23 | + | ||
| 24 | +bool IsTensorAddrInPcieRange(const void* const addr); | ||
| 25 | + | ||
| 26 | +} // namespace internal | ||
| 27 | +} // namespace op | ||
| 28 | + | ||
| 29 | + | ||
| @@ -22,6 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | + | ||
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | 28 | ||
| @@ -168,6 +169,7 @@ void ResetCacheThreadLocal() | |||
| 168 | tlsData->tensorLabelMap.clear(); | 169 | tlsData->tensorLabelMap.clear(); |
| 169 | tlsData->tensorLabelNum = 0; | 170 | tlsData->tensorLabelNum = 0; |
| 170 | tlsData->tensorLabelList.clear(); | 171 | tlsData->tensorLabelList.clear(); |
| 172 | + tlsData->threadLocalContext.opConfigInfo_.usePcieAddr = false; | ||
| 171 | } | 173 | } |
| 172 | 174 | ||
| 173 | void UnInitPTACacheThreadLocal() | 175 | void UnInitPTACacheThreadLocal() |
| @@ -189,6 +191,7 @@ void InitPTACacheThreadLocal() | |||
| 189 | tlsData->tensorLabelMap.clear(); | 191 | tlsData->tensorLabelMap.clear(); |
| 190 | tlsData->tensorLabelNum = 0; | 192 | tlsData->tensorLabelNum = 0; |
| 191 | tlsData->tensorLabelList.clear(); | 193 | tlsData->tensorLabelList.clear(); |
| 194 | + tlsData->threadLocalContext.opConfigInfo_.usePcieAddr = false; | ||
| 192 | } | 195 | } |
| 193 | 196 | ||
| 194 | void AddTensorAddrToCachedList(void* addr) | 197 | void AddTensorAddrToCachedList(void* addr) |
| @@ -202,6 +205,9 @@ void AddTensorAddrToCachedList(void* addr) | |||
| 202 | tlsCachedTensorList.at(tlsCachedTensorListSize) = addr; | 205 | tlsCachedTensorList.at(tlsCachedTensorListSize) = addr; |
| 203 | } | 206 | } |
| 204 | tlsCachedTensorListSize++; | 207 | tlsCachedTensorListSize++; |
| 208 | + if (op::internal::IsPcieThroughEnabled() && op::internal::IsTensorAddrInPcieRange(addr)) { | ||
| 209 | + tlsData->threadLocalContext.opConfigInfo_.usePcieAddr = true; | ||
| 210 | + } | ||
| 205 | } | 211 | } |
| 206 | 212 | ||
| 207 | void SetPTAHashKey(uint64_t hash) | 213 | void SetPTAHashKey(uint64_t hash) |
| @@ -237,6 +243,7 @@ void InitExecutorCacheThreadLocal() | |||
| 237 | tlsData->tensorLabelMap.clear(); | 243 | tlsData->tensorLabelMap.clear(); |
| 238 | tlsData->tensorLabelNum = 0; | 244 | tlsData->tensorLabelNum = 0; |
| 239 | tlsData->tensorLabelList.clear(); | 245 | tlsData->tensorLabelList.clear(); |
| 246 | + tlsData->threadLocalContext.opConfigInfo_.usePcieAddr = false; | ||
| 240 | } | 247 | } |
| 241 | 248 | ||
| 242 | static void AddAclTensorToCachedList(const aclTensor* tensor, OpCacheThreadLocalData* tlsData) | 249 | static void AddAclTensorToCachedList(const aclTensor* tensor, OpCacheThreadLocalData* tlsData) |
| @@ -267,6 +274,9 @@ static void AddAclTensorToCachedList(const aclTensor* tensor, OpCacheThreadLocal | |||
| 267 | } else { | 274 | } else { |
| 268 | tlsData->tensorLabelList.push_back(it->second); | 275 | tlsData->tensorLabelList.push_back(it->second); |
| 269 | } | 276 | } |
| 277 | + if (op::internal::IsPcieThroughEnabled() && op::internal::IsTensorAddrInPcieRange(tensor->GetStorageAddr())) { | ||
| 278 | + tlsData->threadLocalContext.opConfigInfo_.usePcieAddr = true; | ||
| 279 | + } | ||
| 270 | } | 280 | } |
| 271 | 281 | ||
| 272 | inline uint64_t Rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (ROTL_CONSTANT - r)); } | 282 | inline uint64_t Rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (ROTL_CONSTANT - r)); } |
| @@ -1253,6 +1263,10 @@ void OpExecCacheManager::DeleteCache1() | |||
| 1253 | 1263 | ||
| 1254 | OpExecCache* OpExecCacheManager::GetOpExecCache(uint64_t hash) | 1264 | OpExecCache* OpExecCacheManager::GetOpExecCache(uint64_t hash) |
| 1255 | { | 1265 | { |
| 1266 | + if (g_opCacheTlsData.threadLocalContext.opConfigInfo_.usePcieAddr) { | ||
| 1267 | + OP_LOGI("Skip cache get, current op has tensor using PCIe addr"); | ||
| 1268 | + return nullptr; | ||
| 1269 | + } | ||
| 1256 | std::lock_guard<std::mutex> guard(lock_); | 1270 | std::lock_guard<std::mutex> guard(lock_); |
| 1257 | auto it = cache_.find(hash); | 1271 | auto it = cache_.find(hash); |
| 1258 | if (it == cache_.end()) { | 1272 | if (it == cache_.end()) { |
| @@ -1267,6 +1281,10 @@ OpExecCache* OpExecCacheManager::GetOpExecCache(uint64_t hash) | |||
| 1267 | 1281 | ||
| 1268 | OpExecCache* OpExecCacheManager::GetOpExecCache(OpCacheKey& key) | 1282 | OpExecCache* OpExecCacheManager::GetOpExecCache(OpCacheKey& key) |
| 1269 | { | 1283 | { |
| 1284 | + if (g_opCacheTlsData.threadLocalContext.opConfigInfo_.usePcieAddr) { | ||
| 1285 | + OP_LOGI("Skip cache get, current op has tensor using PCIe addr"); | ||
| 1286 | + return nullptr; | ||
| 1287 | + } | ||
| 1270 | std::lock_guard<std::mutex> guard(lock_); | 1288 | std::lock_guard<std::mutex> guard(lock_); |
| 1271 | auto it = cache2_.find(key); | 1289 | auto it = cache2_.find(key); |
| 1272 | if (it == cache2_.end()) { | 1290 | if (it == cache2_.end()) { |
| @@ -1303,6 +1321,11 @@ size_t OpExecCacheManager::GetCacheSizeLimit() | |||
| 1303 | 1321 | ||
| 1304 | bool OpExecCacheManager::AddOpExecCache(OpExecCache* exec) | 1322 | bool OpExecCacheManager::AddOpExecCache(OpExecCache* exec) |
| 1305 | { | 1323 | { |
| 1324 | + if (g_opCacheTlsData.threadLocalContext.opConfigInfo_.usePcieAddr) { | ||
| 1325 | + OP_LOGI("Skip cache add, current op has tensor using PCIe addr"); | ||
| 1326 | + delete exec; | ||
| 1327 | + return false; | ||
| 1328 | + } | ||
| 1306 | if (!exec->IsOpCacheValid()) { | 1329 | if (!exec->IsOpCacheValid()) { |
| 1307 | delete exec; | 1330 | delete exec; |
| 1308 | return false; | 1331 | return false; |
| @@ -0,0 +1,83 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace op { | ||
| 25 | +namespace internal { | ||
| 26 | + | ||
| 27 | +namespace { | ||
| 28 | +// 与 rts 的 aclrtAddrRange 二进制布局一致,弱符号调用可直接用 PcieAddrRange* 接收 | ||
| 29 | +struct PcieAddrRange { | ||
| 30 | + void* startAddr{nullptr}; | ||
| 31 | + void* endAddr{nullptr}; | ||
| 32 | +}; | ||
| 33 | + | ||
| 34 | +bool g_pcieThroughEnabled{false}; | ||
| 35 | +std::vector<PcieAddrRange> g_pcieAddrRanges; | ||
| 36 | +std::once_flag g_pcieThroughOnceFlag; | ||
| 37 | +} // namespace | ||
| 38 | + | ||
| 39 | +aclnnStatus InitPcieThroughInfo() | ||
| 40 | +{ | ||
| 41 | + static aclnnStatus initRet = ACLNN_SUCCESS; | ||
| 42 | + std::call_once(g_pcieThroughOnceFlag, [&initRet]() { | ||
| 43 | + NpuArch npuArch = GetCurrentPlatformInfo().GetCurNpuArch(); | ||
| 44 | + OP_LOGI("NPU arch is %d", static_cast<int32_t>(npuArch)); | ||
| 45 | + | ||
| 46 | + int32_t deviceId = 0; | ||
| 47 | + auto aclRet = aclrtGetDevice(&deviceId); | ||
| 48 | + if (aclRet != ACL_SUCCESS) { | ||
| 49 | + OP_LOGE(ACLNN_ERR_RUNTIME_ERROR, "aclrtGetDevice failed, return %d", static_cast<int32_t>(aclRet)); | ||
| 50 | + initRet = ACLNN_ERR_RUNTIME_ERROR; | ||
| 51 | + return; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + // 遗留项:HD connect 判断(aclrtGetDeviceInfo 兼容性问题)与地址段获取(接口未提供)暂注释 | ||
| 55 | + | ||
| 56 | + // 框架阶段:赋初始值用于性能验证,真实地址段待弱符号接口接入后填充 | ||
| 57 | + // 选用 0x1~0x2 这种不存在的极小地址段,保证真实 tensor 地址不会命中 | ||
| 58 | + g_pcieAddrRanges.resize(1); | ||
| 59 | + g_pcieAddrRanges[0].startAddr = reinterpret_cast<void*>(0x1); | ||
| 60 | + g_pcieAddrRanges[0].endAddr = reinterpret_cast<void*>(0x2); | ||
| 61 | + g_pcieThroughEnabled = true; | ||
| 62 | + }); | ||
| 63 | + return initRet; | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +bool IsPcieThroughEnabled() { return g_pcieThroughEnabled; } | ||
| 67 | + | ||
| 68 | +bool IsTensorAddrInPcieRange(const void* const addr) | ||
| 69 | +{ | ||
| 70 | + uintptr_t addrVal = reinterpret_cast<uintptr_t>(addr); // NOLINT | ||
| 71 | + for (const auto& range : g_pcieAddrRanges) { | ||
| 72 | + uintptr_t start = reinterpret_cast<uintptr_t>(range.startAddr); // NOLINT | ||
| 73 | + uintptr_t end = reinterpret_cast<uintptr_t>(range.endAddr); // NOLINT | ||
| 74 | + if (addrVal >= start && addrVal <= end) { | ||
| 75 | + OP_LOGI("Tensor addr %p is in PCIe range, startAddr %p, endAddr %p", addr, range.startAddr, range.endAddr); | ||
| 76 | + return true; | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + return false; | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +} // namespace internal | ||
| 83 | +} // namespace op | ||
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | + | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | 31 | ||
| @@ -1029,6 +1030,7 @@ int64_t GetDeterministicLevelFromRt() | |||
| 1029 | void InitL2Phase1Context(const char* l2Name, [[maybe_unused]] aclOpExecutor** executor) | 1030 | void InitL2Phase1Context(const char* l2Name, [[maybe_unused]] aclOpExecutor** executor) |
| 1030 | { | 1031 | { |
| 1031 | InitAclnnDebugSwitch(); | 1032 | InitAclnnDebugSwitch(); |
| 1033 | + OP_CHECK_NO_RETURN(op::internal::InitPcieThroughInfo() == ACLNN_SUCCESS, OP_LOGW("InitPcieThroughInfo failed")); | ||
| 1032 | auto& opTlsCtx = op::internal::GetThreadLocalContext(); | 1034 | auto& opTlsCtx = op::internal::GetThreadLocalContext(); |
| 1033 | opTlsCtx.logInfo_.l2ApiName = l2Name; | 1035 | opTlsCtx.logInfo_.l2ApiName = l2Name; |
| 1034 | opTlsCtx.logInfo_.l2SequenceCounter = op::internal::OpGetLogSequence(); | 1036 | opTlsCtx.logInfo_.l2SequenceCounter = op::internal::OpGetLogSequence(); |