Maison >développement back-end >C++ >Comment implémenter efficacement log2(__m256d) dans AVX2 ?
Implémentation efficace de log2(__m256d) dans AVX2
Introduction
Le __m256d intrinsèque _mm256_log2_pd (__m256da) n'est pas pris en charge au-delà des compilateurs Intel et ses performances sont compromises sur les processeurs AMD. Cet article vise à fournir une solution performante et multi-compilateur pour calculer log2() pour les vecteurs de doubles à l'aide du jeu d'instructions AVX2.
Approche
La méthode typique implique diviser log(a*b) en log(a) log(b) et ajuster le biais des exposants. Pour le cas de log2, le résultat est équivalent à l'exposant log2(mantisse). Comme la plage de mantisse (1,0 à 2,0) est limitée, une approximation polynomiale pour log2 (mantisse) peut être utilisée.
Considérations sur la précision
La précision de l'approximation influence l'erreur relative. Afin de minimiser l'erreur absolue ou relative maximale, les coefficients doivent être ajustés via un ajustement minimax plutôt que simplement en utilisant l'expansion en série de Taylor.
Vectorisation
Pour tirer parti de l'instruction AVX2 défini pour le traitement vectoriel, les étapes suivantes sont mises en œuvre :
Améliorations des performances
Pour améliorer les performances :
Implémentation
L'implémentation ci-dessous utilise principes intrinsèques pour la vectorisation et instructions FMA pour une multiplication et une addition efficaces :
__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; }
Conclusion
Cette implémentation fournit une solution efficace et portable pour les calculs log2() utilisant AVX2. En optimisant à la fois la vitesse et la précision, il offre une alternative multi-compilateur aux fonctions intrinsèques et peut améliorer considérablement les performances.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!