[AI][昇腾950]同步BufID 方案
2026/7/29 3:59:57 网站建设 项目流程

Ascend 950PR (Ascend950) bufid 原理、实现约束与使用约束

目标芯片:Ascend 950PR / DT(Atlas A5),__NPU_ARCH__ == Ascend950
核心结论bufid(buffer ID)与mutex_id(互斥锁编号)是同一个硬件资源——一个 5 位编号[0, 31],命名 32 个硬件"取缓冲/释放缓冲"信号量。
底层指令get_buf(pipe, bufId, mode)/rls_buf(pipe, bufId, mode)
2201 差异:2201无 mutex 能力,使用set_flag/wait_flag替代


1. bufid 是什么

1.1 定义

在 Ascend950 上,每个 AI Core 内置32 个硬件缓冲锁槽位(buffer-lock slots),每个槽位由一个 5 位编号bufid ∈ [0, 31]标识。每个槽位是一个二值信号量,可被核内异步流水线(MTE2/MTE1/M/V/MTE3/FIX/S)通过get_buf/rls_buf指令获取与释放。

1.2 类型与常量

// include/basic_api/kernel_common.h:143usingMutexID=uint8_t;// impl/basic_api/kernel_event.h:708-710constexprTBufId INVALID_TBUFID=255;// static_cast<uint8_t>(-1)constexprTBufId MAX_TBUFID=31;// 硬件上限constexprTBufId MAX_MUTEXID=27;// 用户可用上限(28~31 系统预留)autoid=AllocMutexID();Mutex::Lock<pipe>(id);xxx Mutex::UnLock<pipe>(id);

三种用途共享同一 32 槽位池,由AllocMutexID/ReleaseMutexID统一分配。

2. 硬件原理

2.1 信号量机制

每个 bufid 槽位是一个硬件二值信号量。get_buf(pipe, id, mode)pipe流水线上尝试获取槽位id

  • 若槽位空闲:获取成功,pipe流水线继续执行后续指令
  • 若槽位已被占用(前序get_buf未配对rls_buf):阻塞该 pipe 流水线(BLOCK 模式)或继续执行(NON_BLOCK 模式)

rls_buf(pipe, id, mode)释放槽位id,使等待该槽位的后续get_buf解除阻塞。

2.2 跨流水线同步语义

bufid 的核心价值在于跨异步流水线建立依赖。典型场景:

MTE2 流水: DataCopy(GM→UB) → rls_buf(MTE2, id) // 数据就绪,释放锁 V 流水: get_buf(V, id) → Add → rls_buf(V, id) // 等数据就绪后计算 MTE3流水: get_buf(MTE3, id) → DataCopy(UB→GM) // 等计算完成后搬出

get_buf/rls_buf配对在不同流水线上形成 happens-before 链,无需set_flag/wait_flag

3. Basic-API(Mutex::Lock/Mutex::Unlock

usingMutexID=uint8_t;classMutex{public:template<pipe_t pipe>static__aicore__inlinevoidLock(MutexID id);// 仅 Ascend950/5102 编译template<pipe_t pipe>static__aicore__inlinevoidUnlock(MutexID id);// 仅 Ascend950/5102 编译};

实现特点

  • 运行时ASCENDC_ASSERT(id <= MAX_MUTEXID),即id <= 27(比 C-API 更严格)

3.1 ID 分配器(AllocMutexID/ReleaseMutexID

__aicore__inlineMutexIDAllocMutexID();// 返回最低空闲位__aicore__inlinevoidReleaseMutexID(MutexID id);

实现kernel_common.h:172-186):

__BLOCK_LOCAL__ __inline__uint32_tg_bufId;// 32 位掩码,每 bit 对应一个槽位MutexID id=static_cast<uint8_t>(sff0(Internal::g_bufId));// find-first-zeroInternal::g_bufId=sbitset1(Internal::g_bufId,id);// 置位ASCENDC_ASSERT(id<=MAX_MUTEXID,...);returnid;
  • __BLOCK_LOCAL__每 AI Core block 独立一份(非 per-pipe、非 per-subblock)

4. 实现约束

4.1 编号范围约束

AllocMutexIDReleaseMutexID只分配 0~27, 超过范围运行时 assert
文档明确:“28-31为系统内部规划预留,不建议使用。”

4.2 模式约束

  • Basic-APIMutex::Lock/Unlock
  • 配对的 lock/unlock 必须使用相同 mode,否则硬件行为不可预测

4.3 配对规则

  • 同一mutex_idMutex::Lock必须在unlock之前(程序序)
  • lock/unlock必须严格配对lock, unlock, lock, unlock(不可lock, lock, unlock, unlock
  • 配对的lock/unlock必须使用相同mutex_id相同mode
  • 配对的lock/unlock必须使用相同pipe

4.4 禁止嵌套

相同mutex_id的 lock/unlock 对不可嵌套(无论pipe/mode是否相同),否则硬件行为不可预测。

错误: lock(id=1) → lock(id=1) → unlock(id=1) → unlock(id=1) // 嵌套 正确: lock(id=1) → unlock(id=1) → lock(id=1) → unlock(id=1) // 顺序

4.5 同流水同 ID 的失效陷阱

同一pipe+ 同一mutex_id连续出现两次 lock/unlock 对时,第二次 lock 不会阻塞流水,无法建立同步。同流水线内部依赖应使用PipeBarrier<pipe>()

4.6 双缓冲交替模式(推荐用法)

为允许流水重叠,分配两个MutexID,按迭代交替使用:

uint8_tid0=AllocMutexID();uint8_tid1=AllocMutexID();for(inti=0;i<n;i++){uint8_tid=(i%2==0)?id0:id1;// 用 id 同步 MTE2→V→MTE3}ReleaseMutexID(id0);ReleaseMutexID(id1);

这样第 N+1 次的 MTE2 可与第 N 次的 V/MTE3 并行(不同 id 不互斥)。

4.7 多锁联合(join 依赖)

同一流水可同时持有多个锁,表达多源依赖的 join:

Mutex::Lock(PIPE_V,input_mutex);// 等输入就绪Mutex::Lock(PIPE_V,output_mutex);// 等上次输出缓冲释放// ... 计算 ...Mutex::Unlock(PIPE_V,input_mutex);Mutex::Unlock(PIPE_V,output_mutex);

4.8 跨核同步不适用

bufid/mutex 是核内机制。跨核(cross-core)同步使用ffts_cross_core_sync/wait_flag_dev+ flag ID,不使用bufid。core_mng/roc/的 cube_group/group_barrier 也用 event ID,不涉及 bufid。

5. 实战示例

5.1 Basic-API 双缓冲流水(官方示例)

__aicore__inlinevoidProcess(){// 分配双缓冲 tensorLocalTensor<float>xLocal0=ubAllocator.Alloc<float,TILE_LENGTH>();LocalTensor<float>xLocal1=ubAllocator.Alloc<float,TILE_LENGTH>();// ... yLocal0/1, zLocal0/1 ...uint8_tmutexId0=AscendC::AllocMutexID();uint8_tmutexId1=AscendC::AllocMutexID();for(int32_ti=0;i<loopCount;i++){uint8_tmutexId=(i%2==0)?mutexId0:mutexId1;auto&x=(i%2==0)?xLocal0:xLocal1;auto&y=(i%2==0)?yLocal0:yLocal1;auto&z=(i%2==0)?zLocal0:zLocal1;// MTE2: GM → UBAscendC::Mutex::Lock<PIPE_MTE2>(mutexId);AscendC::DataCopy(x,src0Global[...],TILE_LENGTH);AscendC::DataCopy(y,src1Global[...],TILE_LENGTH);AscendC::Mutex::Unlock<PIPE_MTE2>(mutexId);// V: AddAscendC::Mutex::Lock<PIPE_V>(mutexId);AscendC::Add(z,x,y,TILE_LENGTH);AscendC::Mutex::Unlock<PIPE_V>(mutexId);// MTE3: UB → GMAscendC::Mutex::Lock<PIPE_MTE3>(mutexId);AscendC::DataCopy(dstGlobal[...],z,TILE_LENGTH);AscendC::Mutex::Unlock<PIPE_MTE3>(mutexId);}AscendC::ReleaseMutexID(mutexId0);AscendC::ReleaseMutexID(mutexId1);}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询