Heim >Backend-Entwicklung >C++ >Wie kann ich mithilfe von SSE/AVX-Anweisungen effizient zwischen Gleitkommazahlen mit doppelter Genauigkeit und 64-Bit-Ganzzahlen konvertieren?
Effiziente Double/int64-Konvertierungen mit SSE/AVX
SSE2 bietet Funktionen für die Konvertierung von Vektoren zwischen Gleitkommazahlen mit einfacher Genauigkeit und 32-Bit-Ganzzahlen. Es fehlen jedoch direkte Gegenstücke für Gleitkommazahlen mit doppelter Genauigkeit und 64-Bit-Ganzzahlen. AVX bietet diese Konvertierungen ebenfalls nicht an.
Methoden zur Simulation von Intrinsics
1. Für begrenzte Werte:
Wenn bestimmte Einschränkungen toleriert werden, können Konvertierungen zwischen doubles und int64 mit nur zwei Anweisungen durchgeführt werden:
double -> ; uint64_t:
__m128i double_to_uint64(__m128d x){ x = _mm_add_pd(x, _mm_set1_pd(0x0010000000000000)); return _mm_xor_si128( _mm_castpd_si128(x), _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)) ); }
double -> int64_t:
__m128i double_to_int64(__m128d x){ x = _mm_add_pd(x, _mm_set1_pd(0x0018000000000000)); return _mm_sub_epi64( _mm_castpd_si128(x), _mm_castpd_si128(_mm_set1_pd(0x0018000000000000)) ); }
uint64_t -> double:
__m128d uint64_to_double(__m128i x){ x = _mm_or_si128(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000))); return _mm_sub_pd(_mm_castsi128_pd(x), _mm_set1_pd(0x0010000000000000)); }
int64_t -> doppelt:
__m128d int64_to_double(__m128i x){ x = _mm_add_epi64(x, _mm_castpd_si128(_mm_set1_pd(0x0018000000000000))); return _mm_sub_pd(_mm_castsi128_pd(x), _mm_set1_pd(0x0018000000000000)); }
2. Vollständiger Bereich int64 -> double:
Um den gesamten Bereich von int64 in double zu konvertieren, sind 5 Anweisungen für uint64_t und 6 Anweisungen für int64_t erforderlich:
uint64_t -> ; double:
__m128d uint64_to_double_full(__m128i x){ __m128i xH = _mm_srli_epi64(x, 32); xH = _mm_or_si128(xH, _mm_castpd_si128(_mm_set1_pd(19342813113834066795298816.))); // 2^84 __m128i xL = _mm_blend_epi16(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)), 0xcc); // 2^52 __m128d f = _mm_sub_pd(_mm_castsi128_pd(xH), _mm_set1_pd(19342813118337666422669312.)); // 2^84 + 2^52 return _mm_add_pd(f, _mm_castsi128_pd(xL)); }
int64_t -> double:
__m128d int64_to_double_full(__m128i x){ __m128i xH = _mm_srai_epi32(x, 16); xH = _mm_blend_epi16(xH, _mm_setzero_si128(), 0x33); xH = _mm_add_epi64(xH, _mm_castpd_si128(_mm_set1_pd(442721857769029238784.))); // 3*2^67 __m128i xL = _mm_blend_epi16(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)), 0x88); // 2^52 __m128d f = _mm_sub_pd(_mm_castsi128_pd(xH), _mm_set1_pd(442726361368656609280.)); // 3*2^67 + 2^52 return _mm_add_pd(f, _mm_castsi128_pd(xL)); }
AVX512
AVX512 bietet direkte Konvertierungen in/von 64-Bit-Ganzzahlen, sowohl mit als auch ohne Vorzeichen unterzeichnet. Diese Konvertierungen werden mithilfe von Intrinsics wie _mm512_cvtpd_epi64 und _mm256_cvtpd_epi64 durchgeführt.
Bitte beachten Sie, dass diese Lösungen nicht als vollständiger Code bereitgestellt werden. Vom Leser wird erwartet, dass er sie vervollständigt und bei Bedarf optimiert, um sie an seinen spezifischen Kontext anzupassen.
Das obige ist der detaillierte Inhalt vonWie kann ich mithilfe von SSE/AVX-Anweisungen effizient zwischen Gleitkommazahlen mit doppelter Genauigkeit und 64-Bit-Ganzzahlen konvertieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!