已合并
添加PCIE Through需求相关内部接口 #727
ren-botao创建于 11 天前
添加PCIE Through需求相关内部接口 #727
已合并
ren-botao创建于 11 天前
5 个文件变更+141-1
Minclude/nnopbase/opdev/op_config.h+4-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 op51} // namespace op
Asrc/nnopbase/common/inc/op_feature_internal.h+29-0
@@ -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+#ifndef OP_API_OP_API_COMMON_INC_OP_FEATURE_INTERNAL_H_
12+#define OP_API_OP_API_COMMON_INC_OP_FEATURE_INTERNAL_H_
13+ 
14+#include "aclnn/acl_meta.h"
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+#endif // OP_API_OP_API_COMMON_INC_OP_FEATURE_INTERNAL_H_
Msrc/nnopbase/common/utils/op_cache.cpp+23-0
@@ -22,6 +22,7 @@
22#include "kernel_utils.h"22#include "kernel_utils.h"
23#include "op_dfx_internal.h"23#include "op_dfx_internal.h"
24#include "op_cache_internal.h"24#include "op_cache_internal.h"
25+#include "op_feature_internal.h"
25#include "thread_local_context.h"26#include "thread_local_context.h"
26#include "opdev/op_cache_container.h"27#include "opdev/op_cache_container.h"
27#include "lock_free_queue.h"28#include "lock_free_queue.h"
@@ -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 
173void UnInitPTACacheThreadLocal()175void 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 
194void AddTensorAddrToCachedList(void* addr)197void 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 
207void SetPTAHashKey(uint64_t hash)213void 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 
242static void AddAclTensorToCachedList(const aclTensor* tensor, OpCacheThreadLocalData* tlsData)249static 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 
272inline uint64_t Rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (ROTL_CONSTANT - r)); }282inline 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 
1254OpExecCache* OpExecCacheManager::GetOpExecCache(uint64_t hash)1264OpExecCache* 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 
1268OpExecCache* OpExecCacheManager::GetOpExecCache(OpCacheKey& key)1282OpExecCache* 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 
1304bool OpExecCacheManager::AddOpExecCache(OpExecCache* exec)1322bool 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;
Asrc/nnopbase/common/utils/op_feature.cpp+83-0
@@ -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+#include "op_feature_internal.h"
12+ 
13+#include <cstdint>
14+#include <mutex>
15+#include <vector>
16+ 
17+#include "acl/acl_rt.h"
18+ 
19+#include "aclnn/acl_meta.h"
20+#include "opdev/platform.h"
21+#include "opdev/op_log.h"
22+#include "opdev/op_errno.h"
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
Msrc/nnopbase/composite_op/aclnn_engine/op_executor.cpp+2-0
@@ -25,6 +25,7 @@
25#include "kernel_workspace.h"25#include "kernel_workspace.h"
26#include "shape_inference.h"26#include "shape_inference.h"
27#include "op_cache_internal.h"27#include "op_cache_internal.h"
28+#include "op_feature_internal.h"
28#include "kernel_utils.h"29#include "kernel_utils.h"
29#include "thread_local_context.h"30#include "thread_local_context.h"
30#include "op_dfx_internal.h"31#include "op_dfx_internal.h"
@@ -1029,6 +1030,7 @@ int64_t GetDeterministicLevelFromRt()
1029void InitL2Phase1Context(const char* l2Name, [[maybe_unused]] aclOpExecutor** executor)1030void 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();