Heim >Backend-Entwicklung >C++ >Wie implementiert man log2(__m256d) effizient in AVX2?
Effiziente Implementierung von log2(__m256d) in AVX2
Einführung
Das intrinsische __m256d _mm256_log2_pd (__m256d a) wird nicht über Intel-Compiler hinaus unterstützt und seine Leistung ist auf AMD-Prozessoren beeinträchtigt. Ziel dieses Artikels ist es, eine leistungsstarke und kompilerübergreifende Lösung zur Berechnung von log2() für Vektoren von Doubles mithilfe des AVX2-Befehlssatzes bereitzustellen.
Ansatz
Die typische Methode umfasst Teilen von log(a*b) in log(a) log(b) und Anpassen der Exponentenverzerrung. Im Fall von log2 entspricht das Ergebnis dem Exponenten log2(Mantisse). Da der Mantissenbereich (1,0 bis 2,0) begrenzt ist, kann eine polynomische Näherung für log2 (Mantisse) verwendet werden.
Überlegungen zur Genauigkeit
Die Genauigkeit der Näherung beeinflusst der relative Fehler. Um den maximalen absoluten oder relativen Fehler zu minimieren, sollten die Koeffizienten durch Minimax-Anpassung angepasst werden, anstatt einfach die Taylor-Reihenentwicklung zu verwenden.
Vektorisierung
Zur Nutzung der AVX2-Anweisung Für die Vektorverarbeitung festgelegt, werden die folgenden Schritte implementiert:
Leistungsverbesserungen
Um die Leistung zu verbessern:
Implementierung
Die folgende Implementierung verwendet Intrinsics für Vektorisierung und FMA-Anweisungen für effiziente Multiplikation und Addition:
__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; }
Fazit
Diese Implementierung bietet eine effiziente und portable Lösung für log2()-Berechnungen mit AVX2. Durch die Optimierung sowohl der Geschwindigkeit als auch der Genauigkeit bietet es eine kompilerübergreifende Alternative zu intrinsischen Funktionen und kann die Leistung erheblich verbessern.
Das obige ist der detaillierte Inhalt vonWie implementiert man log2(__m256d) effizient in AVX2?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!