Thanks for sending an requirement! Please fill in the following template to help quickly solve your problem.
CANN社区任务,参考PyTorch IR prims.ndtri,在Ascend 950PR上使用Ascend C基础API实现Ndtri高阶API。接口输入概率ppp,逐元素输出标准正态分布的分位数xxx,满足:
prims.ndtri
P(Z≤x)=pP(Z\le x)=p P(Z≤x)=p
任务书给出的计算公式为:
Ndtri(p)=2 ∑k=0∞ck(p−1/21/2)2k+1\mathrm{Ndtri}(p)=\sqrt{2}\,\sum_{k=0}^{\infty}c_k \left(\frac{p-1/2}{1/2}\right)^{2k+1} Ndtri(p)=2k=0∑∞ck(1/2p−1/2)2k+1
本任务支持float(float32)和ND格式,适配及验收硬件为Ascend 950PR,开发和自验证使用任务指定的CANN 9.1环境。
float(float32)
Ndtri是标准正态分布累积分布函数的反函数。令:
u=p−1/21/2=2p−1u=\frac{p-1/2}{1/2}=2p-1 u=1/2p−1/2=2p−1
则任务书公式可写为:
Ndtri(p)=2 erf−1(u)=2 ∑k=0∞cku2k+1\mathrm{Ndtri}(p)=\sqrt{2}\,\mathrm{erf}^{-1}(u) =\sqrt{2}\,\sum_{k=0}^{\infty}c_k u^{2k+1} Ndtri(p)=2erf−1(u)=2k=0∑∞cku2k+1
设备侧不能直接计算无穷项,因此需要在满足精度要求的前提下截断级数。数值实验表明,在∣u∣≤0.85|u|\le0.85∣u∣≤0.85时取前24项可以满足任务书的float32双万分之一精度要求。设备实现采用Horner形式:
Ndtri24(p)=2 u(c0+u2(c1+u2(⋯+u2c23)))\mathrm{Ndtri}_{24}(p)=\sqrt{2}\,u \left(c_0+u^2\left(c_1+u^2\left(\cdots+u^2c_{23}\right)\right)\right) Ndtri24(p)=2u(c0+u2(c1+u2(⋯+u2c23)))
当ppp接近0或1时,∣u∣|u|∣u∣接近1,固定24项级数的收敛速度不足以覆盖极端概率和float32次正规数。该区域使用固定阶尾部延拓计算。任务书级数是中央区的直接计算公式,尾部延拓只用于固定项数级数无法满足精度的区域。
输入边界语义与PyTorch prims.ndtri保持一致:
其中,p<0p<0p<0、p>1p>1p>1以及正负Inf均属于越界或非法输入。除正常概率外,自验证需要覆盖越界值、极端概率、NaN和Inf,并按照任务书要求提供完整日志、整体通过截图和性能截图。
接口处理连续LocalTensor中的有效元素,不依赖逻辑维数。ND是调用方的逻辑数据格式,LocalTensor本身不携带格式元数据;标量和任意shape均按连续元素展平处理,输出shape和元素顺序由调用方保持。非连续数据由调用方连续化后传入。
交付内容包括API实现、中文接口文档、README、Kernel UT和多场景功能及性能自验证工程。
Ndtri共1个输入和1个输出。输入、输出数据类型均为float。接口使用Ascend C Reg矢量计算API,按一个矢量长度(VL)分批将LocalTensor数据加载到RegTensor,同时计算任务书级数、普通尾部和极端尾部候选值,通过MaskReg选择有效区间,最后覆盖特殊值并写回目标LocalTensor。接口计算流程如下图所示:
RegTensor
MaskReg
图1 接口计算流程图图1\ 接口计算流程图 图1 接口计算流程图
图1描述接口对各类输入应呈现的语义流程。为避免逐lane分支,实际实现不会先退出特殊值分支,而是先计算各区间候选值,再通过Mask选择区间并覆盖0、1、越界值和NaN;实际指令组织以图2为准。
输入输出数据位于Local Memory,计算中间结果保存在RegTensor和MaskReg中。接口通过Reg数据搬入、Reg计算和Reg数据搬出接口完成计算,不申请额外临时Tensor,也不调用PopStackBuffer。将计算过程拆解为Ascend C基础API后,函数实现流程如下图所示:
PopStackBuffer
图2 函数实现流程图图2\ 函数实现流程图 图2 函数实现流程图
中央区24个ckc_kck由任务书中的逆误差函数幂级数离线高精度展开得到,并以constexpr float保存。尾部计算令:
constexpr float
t=min(p,1−p),r=−ln(t)t=\min(p,1-p),\qquad r=\sqrt{-\ln(t)} t=min(p,1−p),r=−ln(t)
当r≤5r\le5r≤5时,以r−1.6r-1.6r−1.6为自变量计算第一组固定阶有理式;当r>5r>5r>5时,以r−5r-5r−5为自变量计算第二组固定阶有理式。两组尾部系数来源于Wichura Algorithm AS 241及R数学库qnorm.c公开实现,仅作为任务书级数的尾部延拓。
qnorm.c
对于t<2−126t<2^{-126}t<2−126的float32次正规概率,先计算:
t′=t×264t'=t\times2^{64} t′=t×264
再恢复:
ln(t)=ln(t′)−64ln2\ln(t)=\ln(t')-64\ln2 ln(t)=ln(t′)−64ln2
避免直接对极小次正规数计算对数时丢失有效范围。
带临时Tensor的接口:不提供。Ndtri的中间结果全部保存在RegTensor<float>和MaskReg中,不需要额外Local Memory临时空间。
RegTensor<float>
不带临时Tensor的接口包括指定计算元素数和处理整个源Tensor两种形式:
template <typename T, bool isReuseSource = false> __aicore__ inline void Ndtri(const LocalTensor<T>& dstTensor, const LocalTensor<T>& srcTensor, const uint32_t calCount)
template <typename T, bool isReuseSource = false> __aicore__ inline void Ndtri(const LocalTensor<T>& dstTensor, const LocalTensor<T>& srcTensor)
通用参数说明:
表1 模板参数说明
表2 接口参数说明
Kernel接口约束说明
不提供。Ndtri接口不需要额外临时Tensor,所需临时空间大小固定为0,因此无需提供最大、最小临时空间查询接口。
不提供。Ndtri为逐元素高阶API,不感知全局shape和核数,数据规模通过Kernel侧参数calCount表达。调用方根据UB容量完成分核、分块和GM/UB搬运,不需要Ndtri Host Tiling结构。
calCount
AIV_VEC流水占比按照官方自验证样例计算:
AIV_VEC占比=computeTimetotal2−total1\mathrm{AIV\_VEC占比}=\frac{computeTime}{total2-total1} AIV_VEC占比=total2−total1computeTime
其中,total1为纯搬运空跑基线的AIV时间,total2为搬运加1000次计算场景的AIV时间,computeTime为计算场景的AIV_VEC时间。原始op_summary、计算过程、完整日志、整体通过截图和性能截图保存在自验证报告中。
total1
total2
computeTime
op_summary
设计文档更新后,按照任务书要求在asc-devkit仓提交文档评审Issue;如方案更新,评审时间同步刷新。
Ndtri为新增高阶API,不修改既有接口,不涉及已有接口兼容性。公共接口通过adv_api/math/ndtri.h和adv_api/kernel_api.h提供。未支持的数据类型在编译期报错,不执行隐式数据类型转换。
adv_api/math/ndtri.h
adv_api/kernel_api.h
本设计和验证结论仅针对任务书指定的Ascend 950PR。同架构其他产品是否纳入正式产品支持范围,以仓库产品支持规范和对应硬件验证结果为准。
7月社区任务
@T350380 用户你好,issue已收到,已转相关committer进行代码检视,请关注pr检视意见。感谢您的贡献
@T350380 用户你好,prims.ndtri API开发相关pr已合入主线,当前issue先行关闭。感谢您的贡献。
Thanks for sending an requirement! Please fill in the following template to help quickly solve your problem.
Background(背景信息)
需求描述
需求来源
CANN社区任务,参考PyTorch IR
prims.ndtri,在Ascend 950PR上使用Ascend C基础API实现Ndtri高阶API。接口输入概率p,逐元素输出标准正态分布的分位数x,满足:P(Z≤x)=p
任务书给出的计算公式为:
Ndtri(p)=2k=0∑∞ck(1/2p−1/2)2k+1
本任务支持
float(float32)和ND格式,适配及验收硬件为Ascend 950PR,开发和自验证使用任务指定的CANN 9.1环境。需求分析
Ndtri是标准正态分布累积分布函数的反函数。令:
u=1/2p−1/2=2p−1
则任务书公式可写为:
Ndtri(p)=2erf−1(u)=2k=0∑∞cku2k+1
设备侧不能直接计算无穷项,因此需要在满足精度要求的前提下截断级数。数值实验表明,在∣u∣≤0.85时取前24项可以满足任务书的float32双万分之一精度要求。设备实现采用Horner形式:
Ndtri24(p)=2u(c0+u2(c1+u2(⋯+u2c23)))
当p接近0或1时,∣u∣接近1,固定24项级数的收敛速度不足以覆盖极端概率和float32次正规数。该区域使用固定阶尾部延拓计算。任务书级数是中央区的直接计算公式,尾部延拓只用于固定项数级数无法满足精度的区域。
输入边界语义与PyTorch
prims.ndtri保持一致:其中,p<0、p>1以及正负Inf均属于越界或非法输入。除正常概率外,自验证需要覆盖越界值、极端概率、NaN和Inf,并按照任务书要求提供完整日志、整体通过截图和性能截图。
接口处理连续LocalTensor中的有效元素,不依赖逻辑维数。ND是调用方的逻辑数据格式,LocalTensor本身不携带格式元数据;标量和任意shape均按连续元素展平处理,输出shape和元素顺序由调用方保持。非连续数据由调用方连续化后传入。
交付内容包括API实现、中文接口文档、README、Kernel UT和多场景功能及性能自验证工程。
方案设计
接口内部实现
Ndtri共1个输入和1个输出。输入、输出数据类型均为float。接口使用Ascend C Reg矢量计算API,按一个矢量长度(VL)分批将LocalTensor数据加载到

RegTensor,同时计算任务书级数、普通尾部和极端尾部候选值,通过MaskReg选择有效区间,最后覆盖特殊值并写回目标LocalTensor。接口计算流程如下图所示:图1 接口计算流程图
图1描述接口对各类输入应呈现的语义流程。为避免逐lane分支,实际实现不会先退出特殊值分支,而是先计算各区间候选值,再通过Mask选择区间并覆盖0、1、越界值和NaN;实际指令组织以图2为准。
输入输出数据位于Local Memory,计算中间结果保存在

RegTensor和MaskReg中。接口通过Reg数据搬入、Reg计算和Reg数据搬出接口完成计算,不申请额外临时Tensor,也不调用PopStackBuffer。将计算过程拆解为Ascend C基础API后,函数实现流程如下图所示:图2 函数实现流程图
中央区24个ck由任务书中的逆误差函数幂级数离线高精度展开得到,并以
constexpr float保存。尾部计算令:t=min(p,1−p),r=−ln(t)
当r≤5时,以r−1.6为自变量计算第一组固定阶有理式;当r>5时,以r−5为自变量计算第二组固定阶有理式。两组尾部系数来源于Wichura Algorithm AS 241及R数学库
qnorm.c公开实现,仅作为任务书级数的尾部延拓。对于t<2−126的float32次正规概率,先计算:
t′=t×264
再恢复:
ln(t)=ln(t′)−64ln2
避免直接对极小次正规数计算对数时丢失有效范围。
接口设计
Kernel侧接口
带临时Tensor的接口:不提供。Ndtri的中间结果全部保存在
RegTensor<float>和MaskReg中,不需要额外Local Memory临时空间。不带临时Tensor的接口包括指定计算元素数和处理整个源Tensor两种形式:
template <typename T, bool isReuseSource = false> __aicore__ inline void Ndtri(const LocalTensor<T>& dstTensor, const LocalTensor<T>& srcTensor, const uint32_t calCount)template <typename T, bool isReuseSource = false> __aicore__ inline void Ndtri(const LocalTensor<T>& dstTensor, const LocalTensor<T>& srcTensor)通用参数说明:
表1 模板参数说明
表2 接口参数说明
Kernel接口约束说明
Host侧接口
获取Ndtri完成所有临时空间大小接口
不提供。Ndtri接口不需要额外临时Tensor,所需临时空间大小固定为0,因此无需提供最大、最小临时空间查询接口。
获取Ndtri tiling结构接口
不提供。Ndtri为逐元素高阶API,不感知全局shape和核数,数据规模通过Kernel侧参数
calCount表达。调用方根据UB容量完成分核、分块和GM/UB搬运,不需要Ndtri Host Tiling结构。测试用例设计
可维可测
精度标准/性能标准
AIV_VEC流水占比按照官方自验证样例计算:
AIV_VEC占比=total2−total1computeTime
其中,
total1为纯搬运空跑基线的AIV时间,total2为搬运加1000次计算场景的AIV时间,computeTime为计算场景的AIV_VEC时间。原始op_summary、计算过程、完整日志、整体通过截图和性能截图保存在自验证报告中。设计文档更新后,按照任务书要求在asc-devkit仓提交文档评审Issue;如方案更新,评审时间同步刷新。
兼容性分析
Ndtri为新增高阶API,不修改既有接口,不涉及已有接口兼容性。公共接口通过
adv_api/math/ndtri.h和adv_api/kernel_api.h提供。未支持的数据类型在编译期报错,不执行隐式数据类型转换。本设计和验证结论仅针对任务书指定的Ascend 950PR。同架构其他产品是否纳入正式产品支持范围,以仓库产品支持规范和对应硬件验证结果为准。
Origin(信息来源)
7月社区任务
Benefit / Necessity (价值/作用)
Design(设计方案)