首页 > 后端开发 > C++ > 如何在AVX2中高效实现log2(__m256d)?

如何在AVX2中高效实现log2(__m256d)?

DDD
发布: 2024-12-04 14:06:11
原创
193 人浏览过

How to Efficiently Implement log2(__m256d) in AVX2?

AVX2 中 log2(__m256d) 的高效实现

简介

内在 __m256d _mm256_log2_pd (__m256d a) 不受 Intel 编译器之外的支持,并且其性能在 AMD 处理器上会受到影响。本文旨在提供一种高性能的交叉编译器解决方案,用于使用 AVX2 指令集计算双精度向量的 log2()。

方法

典型方法包括将 log(a*b) 除以 log(a) log(b) 并调整指数偏差。对于 log2 的情况,结果相当于指数 log2(尾数)。由于尾数范围(1.0 到 2.0)有限,可以使用 log2(尾数) 的多项式逼近。

精度注意事项

逼近的精度影响相对误差。为了最小化最大绝对或相对误差,应通过极小极大拟合来调整系数,而不是简单地使用泰勒级数展开。

矢量化

利用 AVX2 指令设置为向量处理,实现以下步骤:

  1. 提取指数位并将其转换为浮点数偏差调整。
  2. 提取尾数并通过指数调整将其修改为 [0.5, 1.0) 范围。
  3. 使用 AVX2 对 log(x) 进行多项式近似,精确到 x=1.0使用 FMA 进行说明。
  4. 通过添加指数和多项式近似。
  5. 结合对下溢、溢出和非正规情况的特殊处理。

性能增强

提高性能:

  • 使用高阶多项式或比率多项式以获得更高的精度。
  • 利用 AVX512 指令实现扩展功能,例如更有效地提取指数和尾数。
  • 如果已知值是有限的,则删除或调整对特殊情况的检查

实现

下面的实现使用内部函数进行向量化,并使用 FMA 指令进行高效乘法和加法:

__m256d Log2(__m256d x) {
  // Extract exponent and adjust bias
  const __m256i exps64 = _mm256_srli_epi64(_mm256_and_si256(gDoubleExpMask, _mm256_castpd_si256(x)), 52);
  const __m256i exps32_avx = _mm256_permutevar8x32_epi32(exps64, gTo32bitExp);
  const __m128i exps32_sse = _mm256_castsi256_si128(exps32_avx);
  const __m128i normExps = _mm_sub_epi32(exps32_sse, gExpNormalizer);
  const __m256d expsPD = _mm256_cvtepi32_pd(normExps);

  // Prepare mantissa
  const __m256d y = _mm256_or_pd(_mm256_castsi256_pd(gDoubleExp0),
    _mm256_andnot_pd(_mm256_castsi256_pd(gDoubleExpMask), x));

  // Calculate t=(y-1)/(y+1) and t**2
  const __m256d tNum = _mm256_sub_pd(y, gVect1);
  const __m256d tDen = _mm256_add_pd(y, gVect1);
  const __m256d t = _mm256_div_pd(tNum, tDen);
  const __m256d t2 = _mm256_mul_pd(t, t); // t**2

  // Calculate terms and final log2
  const __m256d t3 = _mm256_mul_pd(t, t2); // t**3
  const __m256d terms01 = _mm256_fmadd_pd(gCoeff1, t3, t);
  const __m256d t5 = _mm256_mul_pd(t3, t2); // t**5
  const __m256d terms012 = _mm256_fmadd_pd(gCoeff2, t5, terms01);
  const __m256d t7 = _mm256_mul_pd(t5, t2); // t**7
  const __m256d terms0123 = _mm256_fmadd_pd(gCoeff3, t7, terms012);
  const __m256d t9 = _mm256_mul_pd(t7, t2); // t**9
  const __m256d terms01234 = _mm256_fmadd_pd(gCoeff4, t9, terms0123);
  const __m256d log2_y = _mm256_mul_pd(terms01234, gCommMul);
  const __m256d log2_x = _mm256_add_pd(log2_y, expsPD);

  return log2_x;
}
登录后复制

结论

这个实现提供了一个高效且使用 AVX2 进行 log2() 计算的便携式解决方案。通过优化速度和准确性,它提供了内部函数的交叉编译器替代方案,并且可以显着提高性能。

以上是如何在AVX2中高效实现log2(__m256d)?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板