CAM cam_feature 分支深度分析:ZB 共享工具、构建系统演进与 HFA 新模块
分析分支:
remotes/origin/cam_featurevsremotes/origin/master分析日期:2026-07-21 分析范围:共享工具(op_host / op_kernel utils)、构建系统、HFA 内存分配模块、pybind 层、operator_registry.json
目录
- ZB 共享工具变化
- 构建系统演进
- HFA (HBM Fast Alloc) 新模块
- pybind 层变化
- operator_registry.json 解读
- 从 master 到 cam_feature 的整体架构演进
1. ZB 共享工具变化
1.1 comm_args.h — 新增 memLen 字段与常量清理
文件路径: src/cam/comm_operator/ascend_kernels/utils/op_kernel/comm_args.h
1.1.1 新增字段
// cam_feature 新增
int64_t memLen;
CommArgs 结构体新增 memLen 字段(位于 dfx[DFX_COUNT] 之后),用于传递内存长度参数。这是 ZB(Zero-Buffer)系列算子的关键参数——在 SHMEM 共享内存方案中,memLen 指定了预分配的共享内存窗口大小,算子通过该长度计算 flag 区域和数据区域的偏移。
1.1.2 删除的常量
| 删除的常量 | 原值 | 说明 |
|---|---|---|
NOTIFY_DISPATCH_BUFF_OFFSET |
204UL * 1024UL * 1024UL |
通知分发缓冲区偏移,已迁移到 tiling_args.h 的 Moe 命名空间 |
该常量在 master 中定义在 comm_args.h,cam_feature 中已删除(迁移到 tiling_args.h 的 NOTIFY_DISPATCH_WIN_OFFSET)。
1.1.3 关键常量保留
cam_feature 保留了以下核心常量:
constexpr int CAM_MAX_RANK_SIZE = 384; // 最大 NPU 卡数
constexpr int64_t IPC_BUFF_MAX_SIZE = 100 * 1024 * 1024; // IPC 缓冲区 100MB
constexpr int64_t IPC_DATA_OFFSET = 2 * 1024 * 1024; // 前 2MB 为 flag,后 100MB 为数据
constexpr int64_t UB_SINGLE_DMA_SIZE_MAX = 190 * 1024; // UB 单次 DMA 最大 190KB
constexpr int64_t UB_SINGLE_PING_PONG_ADD_SIZE_MAX = UB_SINGLE_DMA_SIZE_MAX / 2; // Ping-Pong 半区
constexpr int UB_ALIGN_SIZE = 32; // UB 对齐 32B
constexpr uint8_t COMM_NUM = 2; // 通信域数量(EP + TP)
constexpr uint8_t COMM_EP_IDX = 0;
constexpr uint8_t COMM_TP_IDX = 1;
constexpr int64_t STATE_WIN_OFFSET = 900 * 1024; // 状态窗口偏移
constexpr int64_t UB_SINGLE_TOTAL_SIZE_MAX = 192 * 1024; // UB 总大小 192KB
constexpr int64_t START_OFFSET_FOR_SHARE = 512; // 共享区域起始偏移
1.1.4 Op 枚举
enum Op : int {
COPYONLY = -1,
ADD = 0,
MUL = 1,
MAX = 2,
MIN = 3
};
该枚举定义了 CpGM2GMPingPong 的原子操作类型,用于 GM→GM 拷贝时的原子归约。
1.2 sync_collectives.h — Detour 原语与 Offset 重载
文件路径: src/cam/comm_operator/ascend_kernels/utils/op_kernel/sync_collectives.h
这是 cam_feature 中变化最大的共享工具文件。SyncCollectives 类是 Ascend C kernel 间同步的核心原语库,管理两套 flag 区域(Memory A 卡内同步 / Memory B 卡间同步)。
1.2.1 新增 InitDetour — 共享内存偏移初始化
__aicore__ inline void InitDetour(int rank, int rankSize, GM_ADDR *shareAddrs,
int64_t shareMemOffset, TBuf<QuePosition::VECCALC> &tBuf)
{
// ...
localSyncAddr = (__gm__ int64_t*)(shareAddrs[rank] + shareMemOffset);
basicSyncAddr = (__gm__ int64_t*)(shareAddrs[rank] + shareMemOffset) + GetBlockIdx() * FLAG_UNIT_INT_NUM;
blockOuterSyncAddr = (__gm__ int64_t*)(shareAddrs[rank] + shareMemOffset) + segmentCount + GetBlockIdx() * FLAG_UNIT_INT_NUM;
// ...
}
设计意图: 在 ZB 系列中,共享内存窗口被划分为多个逻辑区域(combine 区域、notify-dispatch 区域等)。shareMemOffset 允许同一算子内的不同 kernel 使用同一块共享内存的不同偏移段,避免 flag 区域冲突。这是 Detour 算子的核心需求——detour 算子需要在同一共享内存窗口内复用同步原语。
1.2.2 新增 WaitSyncFlag 6 参数重载
__aicore__ inline void WaitSyncFlag(int32_t magic, int32_t value, int32_t eventID,
int32_t rank, int64_t flagNum, int64_t offset)
{
int64_t v = MergeMagicWithValue(magic, value);
WaitOneRankPartFlag((__gm__ int64_t*)(shareAddrs[rank] + offset) + eventID * FLAG_UNIT_INT_NUM, flagNum, v);
}
相比 5 参数版本,新增 offset 参数,支持在共享内存中指定偏移后等待 flag。
1.2.3 新增 SetOuterFlagDetour / WaitOuterFlagDetour
__aicore__ inline void SetOuterFlagDetour(int32_t magic, int32_t eventID,
int64_t setRank, int64_t setBlock, int64_t shareMemOffset)
{
__gm__ int64_t* flagAddr = GetOuterFlagAddrDetour(setRank, setBlock, shareMemOffset);
int64_t value = MergeMagicWithValue(magic, eventID);
SetFlag(flagAddr, value);
}
__aicore__ inline void WaitOuterFlagDetour(int32_t magic, int32_t eventID,
int64_t waitRank, int64_t waitBlock, int64_t shareMemOffset)
{
int64_t value = MergeMagicWithValue(magic, eventID);
__gm__ int64_t* flagAddr = GetOuterFlagAddrDetour(waitRank, waitBlock, shareMemOffset);
WaitOneRankPartFlag(flagAddr, 1, value);
}
1.2.4 新增 GetOuterFlagAddrDetour
__aicore__ inline __gm__ int64_t* GetOuterFlagAddrDetour(int64_t flagRank, int64_t flagBlock, int64_t shareMemOffset)
{
return (__gm__ int64_t*)(shareAddrs[flagRank] + shareMemOffset) + segmentCount + flagBlock * FLAG_UNIT_INT_NUM;
}
总结: 所有 Detour 变体都在原始地址计算基础上增加了 shareMemOffset,使得同步原语可以在共享内存窗口的任意偏移处工作。这是 ZB 系列算子(moe_combine_*_zb、moe_dispatch_*_zb、moe_notify_dispatch_zb)的核心基础设施。
1.2.5 同步原语内存布局
共享内存窗口 (peerMems[rank])
├── [0, segmentCount * FLAG_UNIT_INT_NUM * 8) ← Memory A: 卡内同步 flag
│ ├── block 0: [flag0, flag1, flag2, flag3] (FLAG_UNIT_INT_NUM = 4)
│ ├── block 1: [flag0, flag1, flag2, flag3]
│ └── ...
├── [segmentCount * 4 * 8, ...) ← Memory B: 卡间同步 flag
│ ├── block 0: [flag0, flag1, flag2, flag3]
│ └── ...
└── [IPC_CHUNK_FLAG, ...) ← Chunk Flag 区域 (IPC 用)
segmentCount = blockNum * FLAG_UNIT_INT_NUMFLAG_UNIT_INT_NUM = 4(每个同步单元 4 个 int64_t = 32 Bytes)MAGIC_OFFSET = 32(magic 占高 32 bits,value 占低 32 bits)
1.3 moe_distribute_base.h — 结构体无变化
文件路径: src/cam/comm_operator/ascend_kernels/utils/op_kernel/moe_distribute_base.h
git diff 显示 master 与 cam_feature 之间无差异。该文件定义了 HCCL 通信库的核心资源描述结构:
| 结构体 | 用途 |
|---|---|
HcclSignalInfo |
信号资源(resId、addr、devId、tsId、rankId、flag) |
HcclStreamInfo |
流信息(streamId、sqId、cqId、logicCqId) |
LocalResInfoV2 |
本地资源 V2(64 个 signal、19 个 stream、2 个 AICPU notify) |
AlgoTopoInfo |
拓扑信息(rank、rankSize、superPod、RDMA、NIC 等) |
HcclOpConfig |
算子配置(deterministic、retry、highPerf、floatOverflowMode) |
HcclOpResParam |
算子资源参数(workspace、window、config、zero-copy ring buffer 等) |
HDCommunicateParams |
HD 通信参数(host/device addr、cache、flag) |
关键常量:
constexpr uint32_t LOCAL_NOTIFY_MAX_NUM = 64; // 最大本地 notify 数
constexpr uint32_t LOCAL_STREAM_MAX_NUM = 19; // 最大本地 stream 数
constexpr uint32_t AICPU_OP_NOTIFY_MAX_NUM = 2; // AICPU notify 数
constexpr uint32_t AICPU_MAX_RANK_NUM = 128 * 1024; // AICPU 最大 rank 数
1.4 tiling_args.h — 窗口偏移常量
文件路径: src/cam/comm_operator/ascend_kernels/utils/op_host/tiling_args.h
namespace Moe {
constexpr uint64_t COMBINE_STATE_WIN_OFFSET = 4U * 1024UL * 1024UL; // 4MB
constexpr uint64_t NOTIFY_DISPATCH_WIN_OFFSET = 204U * 1024UL * 1024UL; // 204MB
} // namespace Moe
该文件定义了 ZB 系列算子的共享内存窗口偏移常量:
- COMBINE_STATE_WIN_OFFSET (4MB):combine 算子的状态窗口偏移
- NOTIFY_DISPATCH_WIN_OFFSET (204MB):notify-dispatch 算子的窗口偏移
这些常量在 master 中已存在,cam_feature 保持不变。
1.5 mc2_tiling_utils.h — HCCL_BUFFSIZE 解析
文件路径: src/cam/comm_operator/ascend_kernels/utils/op_host/mc2_tiling_utils.h
class Mc2TilingUtils {
public:
static uint64_t GetMaxWindowSize() {
uint16_t defaultWindowSize = 200; // 默认 200MB
if (getenv("HCCL_BUFFSIZE") != nullptr) {
try {
std::string envStr(getenv("HCCL_BUFFSIZE"));
defaultWindowSize = std::stoi(envStr);
} catch (...) { /* 异常处理 */ }
}
return static_cast<uint64_t>(defaultWindowSize) * 1024UL * 1024UL;
}
};
通过环境变量 HCCL_BUFFSIZE 动态获取 HCCL 缓冲区大小(单位 MB),用于计算最大窗口尺寸。默认 200MB。
1.6 DFX 工具链(dfx_base.h / ops_log.h / ops_error.h / error_log.h)
1.6.1 dfx_base.h — 统一日志基础设施
class DfxBase {
public:
static constexpr const int MAX_LOG_LEN = 16000;
static constexpr const int MSG_HDR_LEN = 200;
static inline uint64_t GetTid(); // 获取线程 ID
static inline std::string GetOpInfo(const gert::TilingContext *context); // 获取算子信息
// ... 支持 TilingContext / TilingParseContext / InferShapeContext / InferDataTypeContext
};
核心宏:
#define OPS_LOG_STUB(MOD_ID, LOG_LEVEL, OPS_DESC, FMT, ...)
// 统一日志记录,包含文件名、行号、函数名、TID、算子名
#define OPS_INNER_ERR_STUB(ERR_CODE_STR, OPS_DESC, FMT, ...)
// 内部错误报告 + 日志
#define OPS_CALL_ERR_STUB(ERR_CODE_STR, OPS_DESC, FMT, ...)
// 调用错误报告 + 日志
1.6.2 ops_log.h — 分级日志宏
#define OPS_LOG_D(OPS_DESC, ...) OPS_LOG_STUB_D(OPS_DESC, __VA_ARGS__) // Debug
#define OPS_LOG_I(OPS_DESC, ...) OPS_LOG_STUB_I(OPS_DESC, __VA_ARGS__) // Info
#define OPS_LOG_W(OPS_DESC, ...) OPS_LOG_STUB_W(OPS_DESC, __VA_ARGS__) // Warn
#define OPS_LOG_E(OPS_DESC, ...) OPS_INNER_ERR_STUB("EZ9999", OPS_DESC, __VA_ARGS__) // Error + Report
#define OPS_LOG_EVENT(OPS_DESC, ...) OPS_LOG_STUB_EVENT(OPS_DESC, __VA_ARGS__) // Event
条件日志宏:
#define OPS_LOG_D_IF(COND, OP_DESC, EXPR, ...)
#define OPS_LOG_E_IF_NULL(OPS_DESC, PTR, EXPR) // 空指针检查 + 错误报告
1.6.3 ops_error.h — 错误报告宏
#define OPS_REPORT_VECTOR_INNER_ERR(OPS_DESC, ...) OPS_INNER_ERR_STUB("E89999", OPS_DESC, __VA_ARGS__)
#define OPS_REPORT_CUBE_INNER_ERR(OPS_DESC, ...) OPS_INNER_ERR_STUB("E69999", OPS_DESC, __VA_ARGS__)
#define OPS_ERR_IF(COND, LOG_FUNC, EXPR) OPS_LOG_STUB_IF(COND, LOG_FUNC, EXPR)
错误码体系:
- EZ9999:通用错误
- E89999:Vector 内核内部错误
- E69999:Cube 内核内部错误
1.6.4 error_log.h — 轻量级 printf 日志
#define OP_LOGI(opname, ...) // Info 级别(空实现)
#define OP_LOGW(opname, ...) // Warn 级别(printf)
#define OP_LOGE_WITHOUT_REPORT(opname, ...) // Error 不报告
#define OP_LOGE(opname, ...) // Error 级别(printf)
#define OP_LOGD(opname, ...) // Debug 级别(空实现)
这是 tiling 侧的轻量级日志,使用 printf 而非 Alog。
1.7 data_copy.h — GM↔GM Ping-Pong 拷贝
文件路径: src/cam/comm_operator/ascend_kernels/utils/op_kernel/data_copy.h
核心函数 CpGM2GMPingPong:
template <typename K, typename U = K>
FORCE_INLINE_AICORE void CpGM2GMPingPong(int64_t dataSizeRemain,
const GlobalTensor<U> &sendDataInputGt,
const GlobalTensor<K> &recvDataOutputGT, int op)
设计要点:
1. Ping-Pong 双缓冲:UB 分为两个区域(UB_HEAD_OFFSET 和 UB_MID_OFFSET),MTE2(GM→UB)和 MTE3(UB→GM)流水线化
2. 类型转换支持:当 K != U 时(如 half→float),UB 按 sizeof(U):sizeof(K) 比例分割
3. 原子操作:通过 SetAtomic<K>(op) 支持 ADD/MUL/MAX/MIN 归约
4. 事件同步:使用 MTE3_MTE2、MTE2_MTE3、MTE2_V、V_MTE3 等硬事件
辅助函数:
template <typename T> void CpUB2GM(__gm__ T *gmAddr, __ubuf__ T *ubAddr, uint32_t size);
template <typename T> void CpGM2UB(__ubuf__ T *ubAddr, __gm__ T *gmAddr, uint32_t size);
template<typename T> void CopyUB2UB(__ubuf__ T *dst, __ubuf__ T *src, const uint32_t calCount);
template<typename T> void copyGmToGmWithBlocks(...); // 多核分块 GM→GM
2. 构建系统演进
2.1 operator_registry.json — 从 5 个算子到 13 个算子
2.1.1 master 版本(5 个算子)
{
"soc_versions": {
"ascend910_93": [
"dispatch_layout",
"fused_deep_moe",
"moe_combine_normal",
"moe_dispatch_normal",
"notify_dispatch"
]
},
"operator_meta": {
"dispatch_layout": { "requires_shmem": false },
"fused_deep_moe": { "requires_shmem": false, "family": "fused_deep_moe", "variant": "base" },
"moe_combine_normal": { "requires_shmem": false },
"moe_dispatch_normal": { "requires_shmem": false },
"notify_dispatch": { "requires_shmem": false }
}
}
2.1.2 cam_feature 版本(13 个算子)
{
"soc_versions": {
"ascend910_93": [
"a2e",
"all_to_all_detour",
"e2a",
"fused_deep_moe",
"fused_deep_moe_fwk",
"fused_deep_moe_w4a8",
"moe_combine_lowlatency_zb",
"moe_combine_normal_zb",
"moe_dispatch_layout_zb",
"moe_dispatch_lowlatency_zb",
"moe_dispatch_normal_zb",
"moe_notify_dispatch_zb",
"reduce_scatter_detour"
]
}
}
2.1.3 新增算子清单
| 算子名 | requires_shmem | family | variant | 说明 |
|---|---|---|---|---|
a2e |
- | - | - | Attention→Expert 数据搬运 |
e2a |
- | - | - | Expert→Attention 数据搬运 |
all_to_all_detour |
- | - | - | All-to-All Detour 通信 |
reduce_scatter_detour |
- | - | - | Reduce-Scatter Detour 通信 |
fused_deep_moe_fwk |
false | fused_deep_moe | fwk | 独立 FWK 变体 |
fused_deep_moe_w4a8 |
false | fused_deep_moe | w4a8 | W4A8 量化变体 |
moe_combine_lowlatency_zb |
true | - | - | ZB 低延迟 Combine |
moe_combine_normal_zb |
true | - | - | ZB 标准 Combine |
moe_dispatch_layout_zb |
true | - | - | ZB Dispatch 布局 |
moe_dispatch_lowlatency_zb |
true | - | - | ZB 低延迟 Dispatch |
moe_dispatch_normal_zb |
true | - | - | ZB 标准 Dispatch |
moe_notify_dispatch_zb |
true | - | - | ZB Notify-Dispatch |
2.1.4 SHMEM 依赖分析
requires_shmem = true(7 个): 全部为 ZB 系列算子
- moe_combine_lowlatency_zb
- moe_combine_normal_zb
- moe_dispatch_layout_zb
- moe_dispatch_lowlatency_zb
- moe_dispatch_normal_zb
- moe_notify_dispatch_zb
requires_shmem = false(2 个):
- fused_deep_moe_fwk
- fused_deep_moe_w4a8
未标记 requires_shmem(4 个): 默认为 false
- a2e, e2a, all_to_all_detour, reduce_scatter_detour
2.1.5 fused_deep_moe 家族互斥规则
fused_deep_moe (base) ──┐
├── 互斥(共享 fused_deep_moe.* 文件名)
fused_deep_moe_w4a8 ────┘
fused_deep_moe_fwk ───── 独立(fused_deep_moe_fwk.* 文件名),可与 base/w4a8 共存
base和w4a8共享fused_deep_moe.h/fused_deep_moe.cpp,互斥fwk使用独立文件名fused_deep_moe_fwk.*,可与任意变体共存--quant标志选择w4a8变体
2.2 select_ops.py — 算子选择逻辑
文件路径: build/cam/comm_operator/select_ops.py
2.2.1 核心 resolve 函数流程
输入: registry, soc_list, shmem, quant, user_ops
│
├─ 1. 确定候选集: user_ops 或全量 soc_list
│
├─ 2. fused_deep_moe 互斥规则
│ ├─ quant=true: 强制 w4a8,移除 base
│ ├─ quant=false + 两者都在: 保留 base,移除 w4a8
│ └─ fwk 不受影响
│
├─ 3. SHMEM 过滤
│ └─ shmem=false: 移除所有 requires_shmem=true 的算子
│
└─ 4. 按注册表顺序排序输出
2.2.2 命令行参数
python3 select_ops.py \
--registry operator_registry.json \
--soc ascend910_93 \
--shmem 1 \
--quant \
--ops "a2e;e2a;fused_deep_moe"
2.2.3 master vs cam_feature 差异
select_ops.py 在 master 和 cam_feature 之间逻辑完全一致,仅注释语言不同(master 英文,cam_feature 中文)。变化的是 operator_registry.json 的内容。
2.3 compile_ascend_proj.sh — SHMEM 注入与中文注释
文件路径: build/cam/comm_operator/compile_ascend_proj.sh
2.3.1 SHMEM 检测逻辑
shmem_installed=1
if [ -z "${SHMEM_HOME_PATH}" ]; then
shmem_installed=0
fi
通过 SHMEM_HOME_PATH 环境变量判断 SHMEM 是否安装。
2.3.2 SHMEM 编译选项注入(关键 patch)
# Patch kernel compile .make files to pass custom include paths to OPC tool.
KERNEL_COMPILE_OPTS=""
if [ -n "${SHMEM_HOME_PATH}" ]; then
KERNEL_COMPILE_OPTS="-I${SHMEM_HOME_PATH}/shmem/include -I${SHMEM_HOME_PATH}/shmem/src/device"
fi
if [ -n "${CATLASS_HOME_PATH}" ]; then
KERNEL_COMPILE_OPTS="${KERNEL_COMPILE_OPTS}-I${CATLASS_HOME_PATH}/include"
fi
if [ -n "${KERNEL_COMPILE_OPTS}" ]; then
find build_out/op_kernel/CMakeFiles -name "build.make" \
-exec sed -i "s|--compile-options=\"\"|--compile-options=\\\"${KERNEL_COMPILE_OPTS}\\\"|g" {} +
fi
设计意图: npu_op_* 构建系统的 simple_kernel_compile 不读取 custom_compile_options.ini,导致 --compile-options 为空。该 patch 通过 sed 直接修改 .make 文件,将 SHMEM 和 Catlass 的 include 路径注入到编译选项中。
2.3.3 Include-List 构建模式
copy_ops_include() {
# 始终复制 utils 公共头目录
cp -rf "$src_dir/utils/op_host/"* "$dst_dir/op_host/"
cp -rf "$src_dir/utils/op_kernel/"* "$dst_dir/op_kernel/"
# 仅复制选中算子的 op_host/op_kernel/op_api
for name in "${ops[@]}"; do
cp -rf "$subdir/op_host/"* "$dst_dir/op_host/"
cp -rf "$subdir/op_kernel/"* "$dst_dir/op_kernel/"
cp -rf "$subdir/op_api/"* "$dst_dir/pregen/build_out/autogen/"
done
}
相比旧版全量拷贝 + exclude-list,新版只复制 select_ops.py 求解出的算子,从根本上避免同名算子文件覆盖。
2.3.4 master vs cam_feature 差异
compile_ascend_proj.sh 在 master 和 cam_feature 之间逻辑完全一致,仅注释语言不同(master 英文,cam_feature 中文)。
2.4 ascendc_impl_build.py — SHMEM 路径修复
文件路径: src/cam/comm_operator/ascend_kernels/cmake_files/cmake/util/ascendc_impl_build.py
2.4.1 关键 Bug Fix
# master(有 bug)
options.append("-I" + SHMEM_HOME_PATH + "shmem/include/device") # 缺少 / 分隔符
# cam_feature(修复)
options.append("-I" + SHMEM_HOME_PATH + "/shmem/include/device") # 正确路径
影响: 在 master 中,如果 SHMEM_HOME_PATH 以 / 结尾则正常,否则路径拼接错误。cam_feature 修复了此问题。
2.4.2 SHMEM Include 路径列表
options.append("-I" + SHMEM_HOME_PATH + "/shmem/include")
options.append("-I" + SHMEM_HOME_PATH + "/shmem/include/device")
options.append("-I" + SHMEM_HOME_PATH + "/shmem/include/host_device")
options.append("-I" + SHMEM_HOME_PATH + "/shmem/include/internal")
options.append("-I" + SHMEM_HOME_PATH + "/shmem/src")
options.append("-I" + SHMEM_HOME_PATH + "/shmem/src/device")
options.append("-I" + SHMEM_HOME_PATH + "/memfabric_hybrid/include/smem/device")
2.5 CMakeLists.txt 演进
2.5.1 op_kernel/CMakeLists.txt — Catlass 架构宏
# cam_feature 新增
list(APPEND KERNEL_COMPILE_OPTS -I${CMAKE_CURRENT_SOURCE_DIR} -DASCENDC_DUMP=0 --cce-auto-sync=off -DCATLASS_ARCH=2201)
变化:
1. 新增 -I${CMAKE_CURRENT_SOURCE_DIR}:将当前源码目录加入全局头搜索路径
2. 新增 -DCATLASS_ARCH=2201:Catlass 架构版本宏(2201 对应 Ascend 910B)
2.5.2 op_host/CMakeLists.txt — CANN 版本检测
set(CANN83_PATH "${CANN_ROOT}/include/platform/platform_infos_def.h")
set(CANN82_PATH "${CANN_ROOT}/include/experiment/platform/platform/platform_infos_def.h")
if(EXISTS "${CANN83_PATH}")
add_definitions(-DUSE_CANN83_PATH)
elseif(EXISTS "${CANN82_PATH}")
add_definitions(-DUSE_CANN82_PATH)
endif()
自动检测 CANN 8.2 vs 8.3+ 版本,定义对应的宏。
2.5.3 顶层 CMakeLists.txt
cmake_minimum_required(VERSION 3.16.0)
project(opp)
find_package(ASC REQUIRED)
set(package_name ${vendor_name})
npu_op_package(${package_name} TYPE RUN CONFIG INSTALL_PATH ${CMAKE_BINARY_DIR}/)
add_subdirectory(op_host)
add_subdirectory(op_kernel)
使用 npu_op_package 宏定义算子包,类型为 RUN(run 包)。
3. HFA (HBM Fast Alloc) 新模块
文件路径: src/cam/utilities/hfa/
HFA 是 cam_feature 中全新引入的模块,master 中不存在。
3.1 模块概览
hfa/
├── .gitignore
├── CMakeLists.txt
├── README.md
├── doc/
│ └── HFA.pdf
├── include/
│ └── hbm_fast_alloc.h ← 对外头文件
├── src/
│ ├── CMakeLists.txt
│ ├── acl_free_chunks.cpp ← 空闲块管理
│ ├── acl_virtual_memory.cpp ← 虚拟内存管理
│ ├── acl_virtual_memory.h ← 虚拟内存头文件
│ ├── flex_alloc.cpp ← 弹性分配器
│ ├── flex_alloc.h ← 弹性分配器头文件
│ ├── hbm_fast_alloc.cpp ← HBM 快速分配器
│ └── hfa_log.h ← 日志工具
└── test/
3.2 FlexAlloc — 双索引弹性分配器
文件路径: src/cam/utilities/hfa/src/flex_alloc.h / flex_alloc.cpp
3.2.1 数据结构
class FlexAlloc {
private:
struct Range { length_t size; };
// 主索引:按起始偏移排序
using StartMap = std::map<offset_t, Range>;
// 辅助索引:按大小排序,值为 StartMap 的迭代器
using SizeMap = std::multimap<length_t, typename StartMap::iterator>;
StartMap m_free_ranges_by_offset; // 按偏移索引的空闲区间
SizeMap m_free_ranges_by_size; // 按大小索引的空闲区间
size_t m_mem_size { 0 };
size_t m_total_alloc_bytes { 0 };
size_t m_total_free_bytes { 0 };
size_t m_total_alloc_objs { 0 };
};
设计亮点: 双索引结构——StartMap 支持 O(log n) 的邻居合并,SizeMap 支持 O(log n) 的最佳适配查找。SizeMap 存储的是 StartMap 的迭代器,避免数据冗余。
3.2.2 分配算法
FlexAlloc::FlexRetCode FlexAlloc::alloc(length_t req_size, size_t &offset, size_t &alloc_size)
{
alloc_size = round_up_bits(req_size, OBJ_SIZE_BITS); // 64 字节对齐
// 1. 在 SizeMap 中查找第一个 >= alloc_size 的区间
auto sizeIt = m_free_ranges_by_size.lower_bound(alloc_size);
// 2. 如果没找到,区分"内存不足"和"碎片化"
if (sizeIt == m_free_ranges_by_size.end()) {
if (get_total_free_mem() >= alloc_size)
return FLEX_RC_ERR_FRAGMENTATION; // 总空闲够但无连续块
else
return FLEX_RC_ERR_NO_MEM; // 总空闲不够
}
// 3. 分配并分割剩余
offset = rangeIt->first;
blkSz = rangeIt->second.size;
// 从两个索引中删除
// 如果有剩余,将新区间插回两个索引
}
时间复杂度: O(log n)(红黑树操作)
3.2.3 释放与合并
bool FlexAlloc::free(offset_t offset, length_t size)
{
// 1. 查找第一个起始位置 >= offset 的区间
auto next = m_free_ranges_by_offset.lower_bound(offset);
// 2. 尝试与前一个区间合并
if (prevEnd == offset) { /* 合并 */ }
// 3. 尝试与后一个区间合并
while (newStart + newSize == rangeStart) { /* 合并 */ }
// 4. 插入合并后的区间
}
3.2.4 对齐策略
static size_t const OBJ_SIZE_BITS = 6; // 2^6 = 64 字节对齐
static size_t const MIN_OBJ_SIZE = (1UL << OBJ_SIZE_BITS); // 最小 64 字节
template <typename T>
T round_up_bits(T num, uint32_t nbits) {
T shift = ((static_cast<T>(1)) << nbits) - 1;
return (num + shift) & ~(shift);
}
3.2.5 返回码
enum FlexRetCode {
FLEX_RC_SUCCESS, // 成功
FLEX_RC_ERROR, // 通用错误
FLEX_RC_ERR_INVAL_ARG, // 无效参数
FLEX_RC_ERR_NO_MEM, // 内存不足
FLEX_RC_ERR_FRAGMENTATION // 碎片化(总空闲够但无连续块)
};
3.3 AclVirtualMemory — ACL 虚拟内存管理
文件路径: src/cam/utilities/hfa/src/acl_virtual_memory.h / acl_virtual_memory.cpp
3.3.1 核心能力
class AclVirtualMemory {
public:
// 分配 HBM 内存:虚拟内存最大 128GB,物理内存最大 32GB
std::pair<VmRet, void*> alloc(int32_t device_id, size_t vr_mem_size,
size_t ph_mem_size, size_t ph_page_size);
// 碎片整理:将分散的物理页重新映射为连续块
VmRet defrag(AclFreeChunks* p_free_chunks);
void* get_base_addr() { return mp_vr_base_addr; }
void free();
};
3.3.2 关键常量
const size_t MAX_VIRTUAL_MEM_SIZE = 128UL * 1024 * 1024 * 1024; // 128GB
const size_t PH_PAGE_ALIGN_SIZE = 2 * 1024 * 1024; // 2MB 页对齐
const size_t DEF_INITIAL_FREE_PAGES = 1024;
const size_t DEF_INITIAL_FREE_CHUNKS = 1024;
3.3.3 碎片整理算法(defrag)
输入: 空闲块列表 (AclFreeChunks)
│
├─ 1. 遍历每个空闲块,提取完整物理页
│ ├─ 对齐的首页 → 加入 free_pages
│ ├─ 对齐的尾页 → 加入 free_pages
│ └─ 中间完整页 → 加入 free_pages
│
├─ 2. 重新映射完整页到虚拟内存末尾
│ for each page in free_pages:
│ if 完整页: aclrtMapMem 到末尾
│ else: 作为不完整块保留
│
└─ 3. 输出: 一个连续大块 + 若干不完整边块
关键 API:
- aclrtMapMem:将物理页映射到指定虚拟地址
- aclrtUnmapMem:解除映射
- aclrtFreePhysical:释放物理内存
- aclrtReleaseMemAddress:释放虚拟地址空间
3.3.4 错误码体系
enum class VmRet {
SUCCESS = 0,
E_OUT_OF_MEMORY = 0x100,
E_INSTANCE_NOT_INITIALIZED = 0x101,
E_INSUFFICIENT_MEM = 0x102,
E_INVALID_PARAMETER = 0x103,
// ...
E_ACL_MAP_MEM_FAILED = ACL_BASE_ERROR + 5,
E_ACL_UNMAP_MEM_FAILED = ACL_BASE_ERROR + 6,
};
3.4 HbmFastAlloc — 统一分配器
文件路径: src/cam/utilities/hfa/include/hbm_fast_alloc.h / src/cam/utilities/hfa/src/hbm_fast_alloc.cpp
3.4.1 类定义
class HbmFastAlloc {
public:
bool init(int32_t device_id, size_t vr_mem_size, size_t ph_mem_size,
size_t ph_page_size, size_t initial_free_pages);
void deinit();
void *alloc(size_t req_size);
bool free(void *ptr);
void free_all();
size_t get_last_defrag_elem_size() { return m_last_defrag_elem_size; }
static void set_log_level(int lvl);
static int get_log_level();
private:
bool try_defrag();
bool handle_defrag(size_t size, size_t &alloc_offset, size_t &alloc_size);
AclVirtualMemory *mp_avm { nullptr };
FlexAlloc *mp_fa { nullptr };
std::mutex m_alloc_map_lock;
AllocMap m_alloc_map; // ptr → (offset, size)
size_t m_last_defrag_elem_size { 0 };
size_t m_defrag_ctr { 0 };
size_t m_defrag_failed { 0 };
};
3.4.2 分配流程
alloc(size)
│
├─ 1. mp_fa->alloc(size, offset, alloc_size)
│ ├─ 成功 → 返回对象地址
│ └─ 失败且为 FRAGMENTATION → 进入 defrag 流程
│
├─ 2. handle_defrag(size, offset, alloc_size)
│ ├─ try_defrag()
│ │ ├─ 获取所有空闲区间
│ │ ├─ 调用 mp_avm->defrag() 重新映射物理页
│ │ └─ 将新区间插回 FlexAlloc
│ └─ 再次尝试 mp_fa->alloc()
│
└─ 3. 记录到 m_alloc_map,返回地址
3.4.3 释放流程
bool HbmFastAlloc::free(void *ptr)
{
std::lock_guard<std::mutex> lock(m_alloc_map_lock);
auto iter = m_alloc_map.find(static_cast<uint8_t*>(ptr));
if (iter == m_alloc_map.end()) return false;
// 通过 FlexAlloc 释放
mp_fa->free(iter->second.first, iter->second.second);
m_alloc_map.erase(iter);
return true;
}
3.5 hfa_log.h — 分级日志
enum HfaLogLevel {
HFA_LOG_DEBUG = 0,
HFA_LOG_INFO = 1,
HFA_LOG_WARNING = 2,
HFA_LOG_ERROR = 3
};
#define DEBUG_PRINT(...) HFA_LOG_PRINT_IF(HFA_LOG_DEBUG, stdout, __VA_ARGS__)
#define INFO_PRINT(...) HFA_LOG_PRINT_IF(HFA_LOG_INFO, stdout, __VA_ARGS__)
#define WARNING_PRINT(...) HFA_LOG_PRINT_IF(HFA_LOG_WARNING, stdout, __VA_ARGS__)
#define ERROR_PRINT(...) HFA_LOG_PRINT_IF(HFA_LOG_ERROR, stderr, __VA_ARGS__)
默认日志级别:HFA_LOG_WARNING。
3.6 HFA 与 Zero-Buffer 的关系
HFA 虽然位于 src/cam/utilities/hfa/ 公共目录,但其设计目标是为 ZB 系列算子提供共享内存窗口的动态分配能力:
- ZB 算子的内存需求: ZB 系列(
moe_combine_*_zb、moe_dispatch_*_zb、moe_notify_dispatch_zb)需要在 HBM 上预分配大块共享内存窗口,用于卡间 flag 同步和数据交换 - HFA 的角色: 提供高效的 HBM 分配/释放/碎片整理,使 ZB 算子能动态管理共享内存窗口
- 碎片整理: ZB 算子的内存分配模式(频繁 alloc/free 不同大小块)容易产生碎片,HFA 的
defrag通过 ACL API 重新映射物理页解决
性能指标(README 描述): - ~99.7% HBM 利用率(所有对象大小) - ~0.5 µs 分配/释放延迟(超低且稳定)
4. pybind 层变化
文件路径: src/cam/comm_operator/pybind/pybind.cpp / functions.h
4.1 master 版本(4 个算子)
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("fused_deep_moe", &FusedDeepMoeImplAutograd);
m.def("get_dispatch_layout", &GetDispatchLayoutImplAutograd);
m.def("moe_dispatch_prefill", &MoeDispatchPrefillImplAutograd);
m.def("moe_combine_prefill", &MoeCombinePrefillImplAutograd);
}
4.2 cam_feature 版本(10 个算子 + 1 个类)
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("fused_deep_moe", &FusedDeepMoeImplAutograd);
m.def("all2_all_detour", &all2_all_detour_impl_autograd);
m.def("reduce_scatter_detour", &reduce_scatter_detour_impl_autograd);
m.def("cam_get_comm", &cam_get_comm);
m.def("cam_free_comm", &cam_free_comm);
m.def("cam_get_rank_size", &cam_get_rank_size);
m.def("cam_get_and_increase_magic", &cam_get_and_increase_magic);
m.def("cam_get_magic", &cam_get_magic);
m.def("a2e", &A2eImplAutograd);
m.def("e2a", &E2aImplAutograd);
// ZB Fused Deep MOE Buffer 类
pybind11::class_<fused_deep_moe::Buffer>(m, "FusedDeepMoeBuffer")
.def(pybind11::init<>())
.def("init", &fused_deep_moe::Buffer::init)
.def("zb_fused_deep_moe", &fused_deep_moe::Buffer::zb_fused_deep_moe)
.def("is_initialized", &fused_deep_moe::Buffer::is_initialized)
.def("get_ext_info", &fused_deep_moe::Buffer::get_ext_info)
.def("get_shmem_workspace", &fused_deep_moe::Buffer::get_shmem_workspace);
}
4.3 新增算子详解
| 算子 | 功能 | 参数 |
|---|---|---|
all2_all_detour |
All-to-All Detour 通信 | sendData, commRankIds, commArgs, commId |
reduce_scatter_detour |
Reduce-Scatter Detour | sendData, commRankIds, commArgs, commId, op |
cam_get_comm |
获取通信资源 | comm_id, rank, group_size, server_ip_port |
cam_free_comm |
释放通信资源 | comm_id |
cam_get_rank_size |
获取 rank 数量 | comm_id |
cam_get_and_increase_magic |
原子获取并递增 magic | comm_id |
cam_get_magic |
获取当前 magic | comm_id |
a2e |
Attention→Expert 数据搬运 | x, expert_ids, scales, batch_size, hidden_size, topk, ... |
e2a |
Expert→Attention 数据搬运 | expand_x, atten_batch_size, batch_size, hidden_size, topk, ... |
4.4 FusedDeepMoeBuffer 类
namespace fused_deep_moe {
class Buffer {
void init(int rank, int num_ranks, uint64_t memsize, const std::string &ip_port);
std::vector<at::Tensor> zb_fused_deep_moe(
const at::Tensor &x,
const at::Tensor &expert_ids,
const TensorVector &gmm1_weight,
// ... 完整参数列表
);
bool is_initialized() const;
int64_t get_ext_info() const;
int64_t get_shmem_workspace() const;
};
}
设计意图: FusedDeepMoeBuffer 封装了 ZB Fused Deep MOE 算子的状态管理:
- init:初始化共享内存工作区(通过 HCCL 通信)
- zb_fused_deep_moe:执行 ZB 融合 MOE 前向计算
- get_shmem_workspace:返回共享内存工作区指针(供其他算子使用)
4.5 TORCH_LIBRARY 注册
TORCH_LIBRARY(umdk_cam_op_lib, m) {
m.def("fused_deep_moe(...) -> Tensor[]");
m.def("all2_all_detour(Tensor sendData, Tensor commRankIds, Tensor commArgs, int commId) -> Tensor");
m.def("reduce_scatter_detour(Tensor sendData, Tensor commRankIds, Tensor commArgs, int commId, int op) -> Tensor");
m.def("cam_get_comm(int comm_id, int rank, int group_size, str server_ip_port) -> Tensor");
m.def("cam_free_comm(int comm_id) -> Tensor");
m.def("a2e(...) -> Tensor[]");
m.def("e2a(...) -> Tensor");
}
通过 TORCH_LIBRARY 注册为 PyTorch 自定义算子,支持 torch.compile 和 AOTInductor。
4.6 functions.h 签名变化
| master | cam_feature |
|---|---|
GetDispatchLayoutImplAutograd |
移除 |
MoeDispatchPrefillImplAutograd |
移除 |
MoeCombinePrefillImplAutograd |
移除 |
| - | all2_all_detour_impl_autograd (新增) |
| - | reduce_scatter_detour_impl_autograd (新增) |
| - | A2eImplAutograd (新增) |
| - | E2aImplAutograd (新增) |
5. operator_registry.json 解读
5.1 架构设计
operator_registry.json
├── _comment: 元数据说明
├── soc_versions: 代际 → 算子目录名列表
│ └── ascend910_93: [13 个算子]
└── operator_meta: 算子元数据
├── requires_shmem: 是否需要 SHMEM
├── family: 家族(用于互斥)
└── variant: 变体(base/w4a8/fwk)
5.2 算子分类
5.2.1 按功能分类
| 类别 | 算子 | 说明 |
|---|---|---|
| ZB MOE 核心 | moe_combine_*_zb, moe_dispatch_*_zb, moe_notify_dispatch_zb |
7 个,全部 requires_shmem=true |
| Fused MOE | fused_deep_moe, fused_deep_moe_w4a8, fused_deep_moe_fwk |
3 个变体 |
| 数据搬运 | a2e, e2a |
Attention↔Expert |
| 通信 Detour | all_to_all_detour, reduce_scatter_detour |
通信加速 |
5.2.2 按 SHMEM 依赖分类
| requires_shmem | 算子数 | 算子 |
|---|---|---|
| true | 6 | moe_combine_lowlatency_zb, moe_combine_normal_zb, moe_dispatch_layout_zb, moe_dispatch_lowlatency_zb, moe_dispatch_normal_zb, moe_notify_dispatch_zb |
| false | 2 | fused_deep_moe_fwk, fused_deep_moe_w4a8 |
| 未指定(默认 false) | 5 | a2e, e2a, all_to_all_detour, reduce_scatter_detour, fused_deep_moe |
5.3 family/variant 互斥规则
fused_deep_moe (family=fused_deep_moe, variant=base)
fused_deep_moe_w4a8 (family=fused_deep_moe, variant=w4a8)
└── 互斥:共享 fused_deep_moe.* 文件名
fused_deep_moe_fwk (family=fused_deep_moe, variant=fwk)
└── 独立:fused_deep_moe_fwk.* 文件名,可与 base/w4a8 共存
互斥规则代码实现:
if quant:
# -q 选择 w4a8,移除 base
candidates = [o for o in candidates if o != BASE]
if W4A8 not in candidates:
candidates.append(W4A8)
else:
# 默认选择 base,移除 w4a8
if has_base and has_w4a8:
candidates = [o for o in candidates if o != W4A8]
5.4 构建流程中的算子选择
build.sh
│
├─ CAM_USE_W4A8=1 → --quant
├─ CAM_OP_SELECT="a2e;e2a" --ops
└─ SHMEM_HOME_PATH → --shmem 1/0
│
└─ select_ops.py
│
├─ 1. 确定候选集
├─ 2. 应用互斥规则
├─ 3. SHMEM 过滤
└─ 4. 输出最终列表
6. 从 master 到 cam_feature 的整体架构演进
6.1 算子体系演进
master (5 个算子) cam_feature (13 个算子)
───────────────── ──────────────────────
dispatch_layout → (移除,替换为 ZB 版本)
fused_deep_moe → fused_deep_moe (保留)
moe_combine_normal → moe_combine_normal_zb (SHMEM 化)
moe_dispatch_normal → moe_dispatch_normal_zb (SHMEM 化)
notify_dispatch → moe_notify_dispatch_zb (SHMEM 化)
+ moe_combine_lowlatency_zb (新增)
+ moe_dispatch_lowlatency_zb (新增)
+ moe_dispatch_layout_zb (新增)
+ fused_deep_moe_w4a8 (新增量化变体)
+ fused_deep_moe_fwk (新增 FWK 变体)
+ a2e (新增)
+ e2a (新增)
+ all_to_all_detour (新增)
+ reduce_scatter_detour (新增)
6.2 共享内存架构演进
master: 使用 HCCL 标准通信,无自定义共享内存
cam_feature: 引入 SHMEM 共享内存窗口
共享内存窗口布局 (HBM)
├── [0, 4MB) ← COMBINE_STATE_WIN_OFFSET
│ └── combine 算子 flag 区域
├── [204MB, ...) ← NOTIFY_DISPATCH_WIN_OFFSET
│ └── notify-dispatch 算子 flag 区域
├── [IPC_CHUNK_FLAG, ...) ← IPC Chunk 标志区域
└── [peerMems[rank], ...) ← 每个 rank 的 flag 区域
├── Memory A: 卡内同步 flag
└── Memory B: 卡间同步 flag
6.3 同步原语演进
| 特性 | master | cam_feature |
|---|---|---|
| 基础 Init | ✓ | ✓ |
| Detour Init(偏移初始化) | ✗ | ✓ |
| WaitSyncFlag 5 参数 | ✓ | ✓ |
| WaitSyncFlag 6 参数(+offset) | ✗ | ✓ |
| SetOuterFlagDetour | ✗ | ✓ |
| WaitOuterFlagDetour | ✗ | ✓ |
| GetOuterFlagAddrDetour | ✗ | ✓ |
6.4 构建系统演进
| 特性 | master | cam_feature |
|---|---|---|
| 构建系统 | npu_op_* | npu_op_* |
| 算子选择 | select_ops.py | select_ops.py |
| 构建模式 | include-list | include-list |
| SHMEM 检测 | SHMEM_HOME_PATH | SHMEM_HOME_PATH |
| SHMEM 编译注入 | sed patch .make | sed patch .make |
| SHMEM 路径修复 | 有 bug(缺 /) | 已修复 |
| Catlass 架构宏 | 无 | CATLASS_ARCH=2201 |
| 全局头搜索路径 | 无 | -I${CMAKE_CURRENT_SOURCE_DIR} |
6.5 新增模块
| 模块 | master | cam_feature |
|---|---|---|
| HFA (HBM Fast Alloc) | ✗ | ✓ |
| FusedDeepMoeBuffer (pybind) | ✗ | ✓ |
| a2e / e2a 算子 | ✗ | ✓ |
| all_to_all_detour / reduce_scatter_detour | ✗ | ✓ |
| cam_get_comm / cam_free_comm 等通信 API | ✗ | ✓ |
6.6 架构演进总结
cam_feature 分支代表了 CAM 库从标准 HCCL 通信向SHMEM 共享内存加速的架构转型:
- ZB 系列算子: 7 个新的 ZB 算子(全部 requires_shmem=true)使用自定义共享内存窗口替代部分 HCCL 通信,降低延迟
- Detour 同步原语:
SyncCollectives新增 Detour 变体,支持在共享内存窗口任意偏移处工作 - HFA 内存管理: 全新的 HBM 快速分配器,提供 O(log n) 分配/释放 + 碎片整理能力
- pybind 扩展: 新增 6 个通信管理 API + 1 个 ZB Fused MOE Buffer 类
- 构建系统: 修复 SHMEM 路径 bug,新增 Catlass 架构宏,支持更灵活的算子选择
附录:关键文件路径索引
| 文件 | 路径 |
|---|---|
| tiling_args.h | src/cam/comm_operator/ascend_kernels/utils/op_host/tiling_args.h |
| mc2_tiling_utils.h | src/cam/comm_operator/ascend_kernels/utils/op_host/mc2_tiling_utils.h |
| dfx_base.h | src/cam/comm_operator/ascend_kernels/utils/op_host/dfx_base.h |
| ops_log.h | src/cam/comm_operator/ascend_kernels/utils/op_host/ops_log.h |
| error_log.h | src/cam/comm_operator/ascend_kernels/utils/op_host/error_log.h |
| ops_error.h | src/cam/comm_operator/ascend_kernels/utils/op_host/ops_error.h |
| comm_args.h | src/cam/comm_operator/ascend_kernels/utils/op_kernel/comm_args.h |
| sync_collectives.h | src/cam/comm_operator/ascend_kernels/utils/op_kernel/sync_collectives.h |
| data_copy.h | src/cam/comm_operator/ascend_kernels/utils/op_kernel/data_copy.h |
| moe_distribute_base.h | src/cam/comm_operator/ascend_kernels/utils/op_kernel/moe_distribute_base.h |
| operator_registry.json | src/cam/comm_operator/ascend_kernels/operator_registry.json |
| select_ops.py | build/cam/comm_operator/select_ops.py |
| compile_ascend_proj.sh | build/cam/comm_operator/compile_ascend_proj.sh |
| ascendc_impl_build.py | src/cam/comm_operator/ascend_kernels/cmake_files/cmake/util/ascendc_impl_build.py |
| flex_alloc.h | src/cam/utilities/hfa/src/flex_alloc.h |
| flex_alloc.cpp | src/cam/utilities/hfa/src/flex_alloc.cpp |
| hbm_fast_alloc.h | src/cam/utilities/hfa/include/hbm_fast_alloc.h |
| hbm_fast_alloc.cpp | src/cam/utilities/hfa/src/hbm_fast_alloc.cpp |
| acl_virtual_memory.h | src/cam/utilities/hfa/src/acl_virtual_memory.h |
| acl_virtual_memory.cpp | src/cam/utilities/hfa/src/acl_virtual_memory.cpp |
| hfa_log.h | src/cam/utilities/hfa/src/hfa_log.h |
| pybind.cpp | src/cam/comm_operator/pybind/pybind.cpp |
| functions.h | src/cam/comm_operator/pybind/functions.h |
| buffer.h | src/cam/comm_operator/pybind/buffer.h |
| ext_utils.h | src/cam/comm_operator/pybind/ext_utils.h |