DataCacheCleanAndInvalid
产 品 支 持 情 况
| 产 品 | 是 否 支 持(支 持 配 置dcciDst的 原 型) | 是 否 支 持(不 支 持 配 置dcciDst的 原 型) |
|---|---|---|
Ascend 950PR/Ascend 950DT | √ | √ |
Atlas A3 训 练 系 列 产 品/Atlas A3 推 理 系 列 产 品 | √ | √ |
Atlas A2 训 练 系 列 产 品/Atlas A2 推 理 系 列 产 品 | √ | √ |
Atlas 200I/500 A2 推 理 产 品 | √ | √ |
Atlas 推 理 系 列 产 品AI Core | x | √ |
Atlas 推 理 系 列 产 品Vector Core | x | x |
Atlas 训 练 系 列 产 品 | x | x |
Kirin X90 | √ | √ |
Kirin 9030 | √ | √ |
功 能 说 明
头 文 件 路 径 为:"basic_api/kernel_operator_cache_intf.h"。
如 图1所 示,在AI Core内 部,Scalar单 元 和DMA单 元 都 可 能 对GM进 行 访 问:
- DMA搬 运 单 元 读 写GM,数 据 通 过DataCopy等 接 口 在UB等Local Memory和GM间 交 互,没 有Cache一 致 性 问 题。
- Scalar单 元 访 问GM,首 先 会 访 问 每 个 核 内 的Data Cache,因 此 存 在Data Cache与GM的Cache一 致 性 问 题。

DataCacheCleanAndInvalid接 口 用 于 解 决 上 述 一 致 性 问 题,其 功 能 可 以 拆 解 为 两 部 分:
- Clean:将 缓 存 中 被 修 改 过 的 数 据(脏 数 据,Dirty Data)写 回 到GM中,避 免 数 据 丢 失。
- Invalid:
- 将 指 定 地 址 范 围 的Cache Line标 记 为“无 效”,使 其 从 缓 存 中 移 除。
- 保 证 下 一 次 访 问 这 些 内 存 地 址 时,会 从GM重 新 加 载 数 据,而 不 是 使 用 可 能 过 期 的 缓 存 数 据。
该 接 口 的 典 型 使 用 场 景 如 下:
- 读 取GM的 数 据,但 该 数 据 可 能 在 外 部 被 其 余 核 修 改,此 时 需 要 使 用DataCacheCleanAndInvalid接 口,直 接 访 问GM,获 取 最 新 数 据。
- 用 户 通 过Scalar单 元 写GM的 数 据,希 望 立 刻 写 出,也 需 要 使 用DataCacheCleanAndInvalid接 口。
- 针 对Ascend 950PR/Ascend 950DT,原 子 操 作 过 程 中,如 果 希 望 改 变 后 续 数 据 的 饱 和 模 式,需 要 先 使 用DataCacheCleanAndInvalid接 口 将Cache Line中 现 存 的 数 据 立 刻 写 出,再 调 用SetCtrlSpr设 置 后 续 数 据 的 饱 和 模 式。
函 数 原 型
支 持 通 过 配 置dcciDst确 保DCache与GM存 储 的 一 致 性。
C++template <typename T, CacheLine entireType, DcciDst dcciDst> __aicore__ inline void DataCacheCleanAndInvalid(const GlobalTensor<T>& dst)支 持 通 过 配 置dcciDst确 保DCache与Local Memory存 储 的 一 致 性。
C++template <typename T, CacheLine entireType, DcciDst dcciDst> __aicore__ inline void DataCacheCleanAndInvalid(const LocalTensor<T>& dst)不 支 持 配 置dcciDst,仅 支 持 保 证DCache与GM的 一 致 性。
C++template <typename T, CacheLine entireType> __aicore__ inline void DataCacheCleanAndInvalid(const GlobalTensor<T>& dst)
参 数 说 明
表 1 模 板 参 数 说 明
| 参 数 名 | 描 述 |
|---|---|
| T | dst的 数 据 类 型。 |
| entireType | 指 令 操 作 的 模 式: SINGLE_CACHE_LINE:只 刷 新 传 入 地 址 所 在 的Cache Line,注 意 如 果 该 地 址 非64B对 齐,只 会 操 作 传 入 地 址 到64B对 齐 的 部 分。 ENTIRE_DATA_CACHE:此 时 传 入 的 地 址 无 效,核 内 会 刷 新 整 个DCache,但 是 耗 时 较 大,性 能 敏 感 的 场 景 慎 用。 |
| dcciDst | 表 示 使 用 该 接 口 来 保 证DCache与 哪 一 种 存 储 保 持 一 致 性,类 型 为DcciDst枚 举 类。 • CACHELINE_ALL:与CACHELINE_OUT效 果 一 致。 • CACHELINE_UB:表 示 通 过 该 接 口 来 保 证DCache与UB的 一 致 性。 • CACHELINE_OUT:表 示 通 过 该 接 口 来 保 证DCache与GM的 一 致 性。 • CACHELINE_ATOMIC: • Ascend 950PR/Ascend 950DT,原 子 操 作 过 程 中 保 证DCache和GM的 一 致 性。 • Atlas A3 训 练 系 列 产 品/Atlas A3 推 理 系 列 产 品,暂 未 支 持。 • Atlas A2 训 练 系 列 产 品/Atlas A2 推 理 系 列 产 品,暂 未 支 持。 • Atlas 200I/500 A2 推 理 产 品,暂 未 支 持。 • Atlas 推 理 系 列 产 品AI Core,暂 未 支 持。 |
表 2 参 数 说 明
| 参 数 名 | 输 入/输 出 | 描 述 |
|---|---|---|
| dst | 输 入 | 需 要 刷 新Cache的Tensor。 |
返 回 值 说 明
无
约 束 说 明
无
调 用 示 例
示 例1:SINGLE_CACHE_LINE模 式(64B对 齐 场 景)
假 设mmAddr_为0x40(64B对 齐),调 用 一 次 指 令 即 可 刷 新 整 个Cache Line。C++AscendC::GlobalTensor<uint64_t> global; global.SetGlobalBuffer((__gm__ uint64_t*)mmAddr_ + AscendC::GetBlockIdx() * 1024); for( int i = 0; i < 8; i++) { global.SetValue(i, AscendC::GetBlockIdx()); } // 由 于 首 地 址64B对 齐,调 用DataCacheCleanAndInvalid指 令 后,会 立 刻 刷 新 前8个 数。 AscendC::DataCacheCleanAndInvalid<uint64_t, AscendC::CacheLine::SINGLE_CACHE_LINE, AscendC::DcciDst::CACHELINE_OUT>(global);示 例2:SINGLE_CACHE_LINE模 式(非64B对 齐 场 景)
假 设mmAddr_为0x20(非64B对 齐),需 要 调 用 两 次 指 令 才 能 刷 新 完 整Cache Line。C++AscendC::GlobalTensor<uint64_t> global; global.SetGlobalBuffer((__gm__ uint64_t*)mmAddr_ + AscendC::GetBlockIdx() * 1024); for( int i = 0; i < 8; i++) { global.SetValue(i, AscendC::GetBlockIdx()); } // 由 于 首 地 址 非64B对 齐,调 用1条 指 令,只 会 刷 新 起 始 地 址 至64B字 节 对 齐 的 部 分,即 前4个 数。 AscendC::DataCacheCleanAndInvalid<uint64_t, AscendC::CacheLine::SINGLE_CACHE_LINE, AscendC::DcciDst::CACHELINE_OUT>(global); // 需 要 再 次 调 用DataCacheCleanAndInvalid指 令,刷 新 后4个 数。 AscendC::DataCacheCleanAndInvalid<uint64_t, AscendC::CacheLine::SINGLE_CACHE_LINE, AscendC::DcciDst::CACHELINE_OUT>(global[4]);示 例3:SINGLE_CACHE_LINE模 式(多 核 处 理 场 景)
假 设mmAddr_为0x40(64B对 齐),多 核 操 作 同 一 条Cache Line时 可 能 出 现 随 机 覆 盖。本 样 例 仅 做 示 例 说 明,便 于 开 发 者 理 解 使 用 限 制,非 正 常 使 用 样 例。C++AscendC::GlobalTensor<uint64_t> global; global.SetGlobalBuffer((__gm__ uint64_t*)mmAddr_); global.SetValue(AscendC::GetBlockIdx(), AscendC::GetBlockIdx()); // 算 子 中 多 核 操 作 虽 然 不 在 同 一 个 地 址,但 在 同 一 个Cache Line,会 出 现 数 据 的 随 机 覆 盖,和 通 用CPU的 行 为 不 同。 // 调 用DataCacheCleanAndInvalid指 令 后,由 于 多 核 操 作 的 时 间 不 一 致,最 终 结 果 存 在 随 机 性,后 执 行 的 核 会 覆 盖 前 面 核 的 结 果。 AscendC::DataCacheCleanAndInvalid<uint64_t, AscendC::CacheLine::SINGLE_CACHE_LINE, AscendC::DcciDst::CACHELINE_OUT>(global);示 例4:ENTIRE_DATA_CACHE模 式
假 设mmAddr_为0x20(非64B对 齐),刷 新 整 个DCache。本 样 例 仅 做 示 例 说 明,便 于 开 发 者 理 解 使 用 限 制,非 正 常 使 用 样 例。C++AscendC::GlobalTensor<uint64_t> global; global.SetGlobalBuffer((__gm__ uint64_t*)mmAddr_ + AscendC::GetBlockIdx() * 1024); for( int i = 0; i < 8; i++) { global.SetValue(i, AscendC::GetBlockIdx()); } // 刷 新 整 个DCache,性 能 较 差。 AscendC::DataCacheCleanAndInvalid<uint64_t, AscendC::CacheLine::ENTIRE_DATA_CACHE, AscendC::DcciDst::CACHELINE_OUT>(global);