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 指令设置为向量处理,实现以下步骤:
性能增强
提高性能:
实现
下面的实现使用内部函数进行向量化,并使用 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中文网其他相关文章!