昇腾AI原生创新算子挑战赛(S1赛季)复盘-Spence算子
发表于2024-05-14 16:22:12
0 查看
- 正文前感谢昇腾各位工作人员,没有你们的辛勤就没有我们的进步
- 本文立意交流大赛Spence算子编译过程
- 这道题难点在于
- 如何解析Spence公式
- 如何找到Spence,tensorflow源码
- 复杂的计算过程如何重新compute出来

- 这个公式看上去一脸懵逼,居然还有积分,去哪找这样的API
- 那肯定有替代算法,所以必须找到tensorflow相关源码
- 200DK A2原驱动并不支持tensorflow,需要自行安装,太麻烦
- 就直接修改scripts/gen_data.py,使用scipy来生成数据
- 因为装了virtualenv , tensorflow相关源码在相对应的site-packages中
- 可以直接用VSCODE CTRL+左键单击跳转代码,也可以search代码
- 最后在 tf\Lib\site-packages\tensorflow\include\tensorflow\core\kernels\special_math 找到源码
- 看到源码也蒙了,太长了,太多分类了
- 有大数组A,B
- 要求一元多次,internal::ppolevl<Scalar, 7>::run(w, A)
- 多个区间函数
- 累积函数太多,误差叠加过多,只能转换大类型包含误差,最后再转回来
- 这里需要联合使用compare select进行区间函数设计
- compute代码可以参考中奖团队代码,这里就不贴了,怕丢人哈哈

- 可以先以1.5分割左右两款
- 再分别以此基础分别分割0.5左侧,2.0右侧
- 这样就能解决分割问题
- 最后NAN如何输出呢?这个问题困扰很久
- 虽然最后测试案例并不要求负数,但是没见过测试案例并不知道不要求负数
- 单纯使用for循环,逐数据赋值这样是不行的,理论可以,但是测试很多次,发现数据总会缺失或者乱序
- 能不用for就不用for循环,用API操作最安全,用for真的奔溃到想G,0XCCCCCCC大神是真的牛,预选就能顺利完成
- 最终使用下列操作就可以实现NaN输出
本帖最后由 匿名用户 于 2024/05/16 09:43:09 编辑
// Implementation of Spence's Integral based on Cephes. template <typename Scalar> struct spence_op { EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& x) const { const Scalar A[] = { Scalar(4.65128586073990045278E-5), Scalar(7.31589045238094711071E-3), Scalar(1.33847639578309018650E-1), Scalar(8.79691311754530315341E-1), Scalar(2.71149851196553469920E0), Scalar(4.25697156008121755724E0), Scalar(3.29771340985225106936E0), Scalar(1.00000000000000000126E0), }; const Scalar B[] = { Scalar(6.90990488912553276999E-4), Scalar(2.54043763932544379113E-2), Scalar(2.82974860602568089943E-1), Scalar(1.41172597751831069617E0), Scalar(3.63800533345137075418E0), Scalar(5.03278880143316990390E0), Scalar(3.54771340985225096217E0), Scalar(9.99999999999999998740E-1), }; const Scalar zero = Scalar(0.0); const Scalar one = Scalar(1.0); const Scalar three_halves = Scalar(1.5); const Scalar two = Scalar(2.0); const Scalar half = Scalar(0.5); const Scalar nan = Scalar(NumTraits<Scalar>::quiet_NaN()); // pi**2 / 6. const Scalar PI2O6 = Scalar(EIGEN_PI * EIGEN_PI / 6.0); if (x < zero) { return nan; } else if (x == zero) { return PI2O6; } else if (x == one) { return zero; } Scalar y; if (x < two) { y = x; } else { y = one / x; } Scalar w; if (three_halves < y) { w = one / y - one; } else { if (y < half) { w = -y; } else { w = y - one; } } Scalar spence = -w * (internal::ppolevl<Scalar, 7>::run(w, A) / internal::ppolevl<Scalar, 7>::run(w, B)); Scalar z = numext::log(y); if (y < half) { spence = -z * numext::log1p(-y) + PI2O6 - spence; } if (three_halves < x) { spence = -half * z * z - spence; } return spence; } };if(this->dt == 0) { int16_t __NaN = 0x7E00; this->NaN=*((half *)&__NaN); }else if(this->dt == 1) { int32_t __NaNF = 0x7FC00000; this->NaN=*((float *)&__NaNF); } Select(outLocal,tempTensor1,outLocal,this->NaN,SELMODE::VSEL_TENSOR_SCALAR_MODE, this->tileLength);