@@ -66,15 +66,16 @@ class InnerProductFloat {
6666// -------------------------------------------------------------------
6767
6868DEGLIB_TARGET_AVX2 inline static float fp32_hsum256 (__m256 s) {
69- __m128 sum128 = _mm_add_ps (_mm256_extractf128_ps (s, 0 ), _mm256_extractf128_ps (s, 1 ));
70- alignas (32 ) float f[4 ];
71- _mm_store_ps (f, sum128);
72- return f[0 ] + f[1 ] + f[2 ] + f[3 ];
69+ __m128 sum128 = _mm_add_ps (_mm256_castps256_ps128 (s), _mm256_extractf128_ps (s, 1 ));
70+ __m128 shuf = _mm_movehdup_ps (sum128);
71+ __m128 sums = _mm_add_ps (sum128, shuf);
72+ shuf = _mm_movehl_ps (shuf, sums);
73+ sums = _mm_add_ss (sums, shuf);
74+ return _mm_cvtss_f32 (sums);
7375}
7476
7577DEGLIB_TARGET_AVX512 inline static float fp32_hsum512 (__m512 s) {
76- __m256 sum256 = _mm256_add_ps (_mm512_extractf32x8_ps (s, 0 ), _mm512_extractf32x8_ps (s, 1 ));
77- return fp32_hsum256 (sum256);
78+ return _mm512_reduce_add_ps (s);
7879}
7980
8081template <ResidualMode Mode = ResidualMode::Full>
@@ -344,15 +345,10 @@ using DistanceVariant = std::variant<
344345 >;
345346
346347inline DistanceVariant select_dist (const size_t dim, const deglib::cpu::InstructionSet instruction = deglib::cpu::InstructionSet::Auto) {
347- if (instruction == deglib::cpu::InstructionSet::Scalar) {
348- return InnerProductFloat{};
349- }
348+ const auto target = deglib::cpu::resolve_instruction_set (instruction);
350349
351350#if defined(DEGLIB_X86)
352- if (instruction == deglib::cpu::InstructionSet::AVX512 || (instruction == deglib::cpu::InstructionSet::Auto && deglib::cpu::has_avx512 ())) {
353- if (instruction == deglib::cpu::InstructionSet::AVX512 && !deglib::cpu::has_avx512 ()) {
354- throw std::runtime_error (" AVX512 instruction set requested, but not supported by CPU" );
355- }
351+ if (target == deglib::cpu::InstructionSet::AVX512 ) {
356352 if (dim < 16 ) {
357353 return InnerProductFloat_AVX512<ResidualMode::TailOnly>{};
358354 } else if (dim < 32 ) {
@@ -368,10 +364,7 @@ inline DistanceVariant select_dist(const size_t dim, const deglib::cpu::Instruct
368364 else
369365 return InnerProductFloat_AVX512<ResidualMode::Full>{};
370366 }
371- } else if (instruction == deglib::cpu::InstructionSet::AVX2 || (instruction == deglib::cpu::InstructionSet::Auto && deglib::cpu::has_avx2 ())) {
372- if (instruction == deglib::cpu::InstructionSet::AVX2 && !deglib::cpu::has_avx2 ()) {
373- throw std::runtime_error (" AVX2 instruction set requested, but not supported by CPU" );
374- }
367+ } else if (target == deglib::cpu::InstructionSet::AVX2 ) {
375368 if (dim < 8 ) {
376369 return InnerProductFloat_AVX2<ResidualMode::TailOnly>{};
377370 } else if (dim < 16 ) {
@@ -388,10 +381,6 @@ inline DistanceVariant select_dist(const size_t dim, const deglib::cpu::Instruct
388381 return InnerProductFloat_AVX2<ResidualMode::Full>{};
389382 }
390383 }
391- #else
392- if (instruction != deglib::cpu::InstructionSet::Auto && instruction != deglib::cpu::InstructionSet::Scalar) {
393- throw std::runtime_error (" Requested SIMD instruction set is not supported on this platform" );
394- }
395384#endif
396385
397386 return InnerProductFloat{};
0 commit comments