From 6bce3cd000e210a68f7febe03f7983a28a4820cc Mon Sep 17 00:00:00 2001 From: Yermalayeu Ihar Date: Thu, 10 Aug 2023 11:41:52 +0300 Subject: [PATCH] *fix bug: The memory reading outside border of input array in AVX2 optimizations of functions DescrIntDecode32f, DescrIntDecode16f, DescrIntCosineDistance, DescrIntCosineDistancesMxNa, DescrIntCosineDistancesMxNp. --- docs/2023.html | 10 +- src/Simd/SimdAvx2DescrIntCdd.cpp | 267 +++++++++++++++++++++++-------- src/Simd/SimdAvx2DescrIntCdu.cpp | 12 +- src/Simd/SimdAvx2DescrIntDec.cpp | 38 ++--- 4 files changed, 224 insertions(+), 103 deletions(-) diff --git a/docs/2023.html b/docs/2023.html index 27b6797655..def13da0b5 100644 --- a/docs/2023.html +++ b/docs/2023.html @@ -65,11 +65,11 @@
New features
Bug fixing

Test framework

diff --git a/src/Simd/SimdAvx2DescrIntCdd.cpp b/src/Simd/SimdAvx2DescrIntCdd.cpp index ccccb5502e..57399c0cef 100644 --- a/src/Simd/SimdAvx2DescrIntCdd.cpp +++ b/src/Simd/SimdAvx2DescrIntCdd.cpp @@ -52,8 +52,8 @@ namespace Simd } for (; i < size; i += 8, a += 4, b += 4) { - __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)a), Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); - __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)b), Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); + __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<4>(a), Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); + __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<4>(b), Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); ab32 = _mm256_add_epi32(_mm256_madd_epi16(_mm256_castsi128_si256(_a), _mm256_castsi128_si256(_b)), ab32); } return ExtractSum(ab32); @@ -63,17 +63,23 @@ namespace Simd { assert(size % 8 == 0); __m256i _ab = _mm256_setzero_si256(); - size_t i = 0, size16 = AlignLo(size, 16); - for (; i < size16; i += 16, a += 10, b += 10) + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16); + for (; i < size16a; i += 16, a += 10, b += 10) { __m256i _a = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)a)), C5_SHFL), C5_MULLO), 11); __m256i _b = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)b)), C5_SHFL), C5_MULLO), 11); _ab = _mm256_add_epi32(_mm256_madd_epi16(_a, _b), _ab); } + for (; i < size16; i += 16, a += 10, b += 10) + { + __m256i _a = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(a)), C5_SHFL), C5_MULLO), 11); + __m256i _b = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(b)), C5_SHFL), C5_MULLO), 11); + _ab = _mm256_add_epi32(_mm256_madd_epi16(_a, _b), _ab); + } for (; i < size; i += 8, a += 5, b += 5) { - __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)a), Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); - __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)b), Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); + __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<5>(a), Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); + __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<5>(b), Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); _ab = _mm256_add_epi32(_mm256_madd_epi16(_mm256_castsi128_si256(_a), _mm256_castsi128_si256(_b)), _ab); } return ExtractSum(_ab); @@ -83,17 +89,23 @@ namespace Simd { assert(size % 8 == 0); __m256i _ab = _mm256_setzero_si256(); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16); for (; i < size16; i += 16, a += 12, b += 12) { __m256i _a = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)a)), C6_SHFL), C6_MULLO), 10); __m256i _b = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)b)), C6_SHFL), C6_MULLO), 10); _ab = _mm256_add_epi32(_mm256_madd_epi16(_a, _b), _ab); } + for (; i < size16a; i += 16, a += 12, b += 12) + { + __m256i _a = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(a)), C6_SHFL), C6_MULLO), 10); + __m256i _b = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(b)), C6_SHFL), C6_MULLO), 10); + _ab = _mm256_add_epi32(_mm256_madd_epi16(_a, _b), _ab); + } for (; i < size; i += 8, a += 6, b += 6) { - __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)a), Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); - __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)b), Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); + __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<6>(a), Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); + __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<6>(b), Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); _ab = _mm256_add_epi32(_mm256_madd_epi16(_mm256_castsi128_si256(_a), _mm256_castsi128_si256(_b)), _ab); } return ExtractSum(_ab); @@ -103,17 +115,23 @@ namespace Simd { assert(size % 8 == 0); __m256i _ab = _mm256_setzero_si256(); - size_t i = 0, size16 = AlignLo(size, 16); - for (; i < size16; i += 16, a += 14, b += 14) + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16); + for (; i < size16a; i += 16, a += 14, b += 14) { __m256i _a = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)a)), C7_SHFL), C7_MULLO), 9); __m256i _b = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)b)), C7_SHFL), C7_MULLO), 9); _ab = _mm256_add_epi32(_mm256_madd_epi16(_a, _b), _ab); } + for (; i < size16; i += 16, a += 14, b += 14) + { + __m256i _a = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(a)), C7_SHFL), C7_MULLO), 9); + __m256i _b = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(b)), C7_SHFL), C7_MULLO), 9); + _ab = _mm256_add_epi32(_mm256_madd_epi16(_a, _b), _ab); + } for (; i < size; i += 8, a += 7, b += 7) { - __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)a), Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); - __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(_mm_loadl_epi64((__m128i*)b), Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); + __m128i _a = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<7>(a), Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); + __m128i _b = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<7>(b), Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); _ab = _mm256_add_epi32(_mm256_madd_epi16(_mm256_castsi128_si256(_a), _mm256_castsi128_si256(_b)), _ab); } return ExtractSum(_ab); @@ -202,22 +220,22 @@ namespace Simd } for (; i < size; i += 8, o += 4) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C4_SHFL), C4_MULLO), 12); - a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[1] + o))), C4_SHFL), C4_MULLO), 12); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(A[0] + o)), C4_SHFL), C4_MULLO), 12); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(A[1] + o)), C4_SHFL), C4_MULLO), 12); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[0] + o)), C4_SHFL), C4_MULLO), 12); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[1] + o)), C4_SHFL), C4_MULLO), 12); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[2] + o)), C4_SHFL), C4_MULLO), 12); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[3] + o)), C4_SHFL), C4_MULLO), 12); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } @@ -227,7 +245,7 @@ namespace Simd template<> void MicroCosineDistancesDirect2x4<5>(const uint8_t* const* A, const uint8_t* const* B, size_t size, float* distances, size_t stride) { - size_t i = 0, size16 = AlignLo(size, 16), o = 16; + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16), o = 16; __m256i a0, a1, b0; __m256i ab00 = _mm256_setzero_si256(); __m256i ab01 = _mm256_setzero_si256(); @@ -237,7 +255,7 @@ namespace Simd __m256i ab11 = _mm256_setzero_si256(); __m256i ab12 = _mm256_setzero_si256(); __m256i ab13 = _mm256_setzero_si256(); - for (; i < size16; i += 16, o += 10) + for (; i < size16a; i += 16, o += 10) { a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[0] + o))), C5_SHFL), C5_MULLO), 11); a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[1] + o))), C5_SHFL), C5_MULLO), 11); @@ -258,24 +276,45 @@ namespace Simd ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } + for (; i < size16; i += 16, o += 10) + { + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(A[0] + o)), C5_SHFL), C5_MULLO), 11); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(A[1] + o)), C5_SHFL), C5_MULLO), 11); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[0] + o)), C5_SHFL), C5_MULLO), 11); + ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); + ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[1] + o)), C5_SHFL), C5_MULLO), 11); + ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); + ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[2] + o)), C5_SHFL), C5_MULLO), 11); + ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); + ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[3] + o)), C5_SHFL), C5_MULLO), 11); + ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); + ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); + } for (; i < size; i += 8, o += 5) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C5_SHFL), C5_MULLO), 11); - a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[1] + o))), C5_SHFL), C5_MULLO), 11); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(A[0] + o)), C5_SHFL), C5_MULLO), 11); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(A[1] + o)), C5_SHFL), C5_MULLO), 11); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[0] + o)), C5_SHFL), C5_MULLO), 11); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[1] + o)), C5_SHFL), C5_MULLO), 11); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[2] + o)), C5_SHFL), C5_MULLO), 11); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[3] + o)), C5_SHFL), C5_MULLO), 11); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } @@ -285,7 +324,7 @@ namespace Simd template<> void MicroCosineDistancesDirect2x4<6>(const uint8_t* const* A, const uint8_t* const* B, size_t size, float* distances, size_t stride) { - size_t i = 0, size16 = AlignLo(size, 16), o = 16; + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16), o = 16; __m256i a0, a1, b0; __m256i ab00 = _mm256_setzero_si256(); __m256i ab01 = _mm256_setzero_si256(); @@ -295,7 +334,7 @@ namespace Simd __m256i ab11 = _mm256_setzero_si256(); __m256i ab12 = _mm256_setzero_si256(); __m256i ab13 = _mm256_setzero_si256(); - for (; i < size16; i += 16, o += 12) + for (; i < size16a; i += 16, o += 12) { a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[0] + o))), C6_SHFL), C6_MULLO), 10); a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[1] + o))), C6_SHFL), C6_MULLO), 10); @@ -316,24 +355,45 @@ namespace Simd ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } + for (; i < size16; i += 16, o += 12) + { + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(A[0] + o)), C6_SHFL), C6_MULLO), 10); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(A[1] + o)), C6_SHFL), C6_MULLO), 10); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[0] + o)), C6_SHFL), C6_MULLO), 10); + ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); + ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[1] + o)), C6_SHFL), C6_MULLO), 10); + ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); + ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[2] + o)), C6_SHFL), C6_MULLO), 10); + ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); + ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[3] + o)), C6_SHFL), C6_MULLO), 10); + ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); + ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); + } for (; i < size; i += 8, o += 6) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C6_SHFL), C6_MULLO), 10); - a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[1] + o))), C6_SHFL), C6_MULLO), 10); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(A[0] + o)), C6_SHFL), C6_MULLO), 10); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(A[1] + o)), C6_SHFL), C6_MULLO), 10); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[0] + o)), C6_SHFL), C6_MULLO), 10); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[1] + o)), C6_SHFL), C6_MULLO), 10); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[2] + o)), C6_SHFL), C6_MULLO), 10); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[3] + o)), C6_SHFL), C6_MULLO), 10); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } @@ -343,7 +403,7 @@ namespace Simd template<> void MicroCosineDistancesDirect2x4<7>(const uint8_t* const* A, const uint8_t* const* B, size_t size, float* distances, size_t stride) { - size_t i = 0, size16 = AlignLo(size, 16), o = 16; + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16), o = 16; __m256i a0, a1, b0; __m256i ab00 = _mm256_setzero_si256(); __m256i ab01 = _mm256_setzero_si256(); @@ -353,7 +413,7 @@ namespace Simd __m256i ab11 = _mm256_setzero_si256(); __m256i ab12 = _mm256_setzero_si256(); __m256i ab13 = _mm256_setzero_si256(); - for (; i < size16; i += 16, o += 14) + for (; i < size16a; i += 16, o += 14) { a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[0] + o))), C7_SHFL), C7_MULLO), 9); a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[1] + o))), C7_SHFL), C7_MULLO), 9); @@ -374,24 +434,45 @@ namespace Simd ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } + for (; i < size16; i += 16, o += 14) + { + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(A[0] + o)), C7_SHFL), C7_MULLO), 9); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(A[1] + o)), C7_SHFL), C7_MULLO), 9); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[0] + o)), C7_SHFL), C7_MULLO), 9); + ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); + ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[1] + o)), C7_SHFL), C7_MULLO), 9); + ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); + ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[2] + o)), C7_SHFL), C7_MULLO), 9); + ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); + ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[3] + o)), C7_SHFL), C7_MULLO), 9); + ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); + ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); + } for (; i < size; i += 8, o += 7) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C7_SHFL), C7_MULLO), 9); - a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[1] + o))), C7_SHFL), C7_MULLO), 9); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(A[0] + o)), C7_SHFL), C7_MULLO), 9); + a1 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(A[1] + o)), C7_SHFL), C7_MULLO), 9); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[0] + o)), C7_SHFL), C7_MULLO), 9); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); ab10 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab10); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[1] + o)), C7_SHFL), C7_MULLO), 9); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); ab11 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab11); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[2] + o)), C7_SHFL), C7_MULLO), 9); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); ab12 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab12); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[3] + o)), C7_SHFL), C7_MULLO), 9); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); ab13 = _mm256_add_epi32(_mm256_madd_epi16(a1, b0), ab13); } @@ -499,18 +580,18 @@ namespace Simd } for (; i < size; i += 8, o += 4) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C4_SHFL), C4_MULLO), 12); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(A[0] + o)), C4_SHFL), C4_MULLO), 12); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[0] + o)), C4_SHFL), C4_MULLO), 12); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[1] + o)), C4_SHFL), C4_MULLO), 12); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[2] + o)), C4_SHFL), C4_MULLO), 12); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C4_SHFL), C4_MULLO), 12); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<4>(B[3] + o)), C4_SHFL), C4_MULLO), 12); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } __m128 ab0 = _mm_cvtepi32_ps(Extract4Sums(ab00, ab01, ab02, ab03)); @@ -519,13 +600,13 @@ namespace Simd template<> void MicroCosineDistancesDirect1x4<5>(const uint8_t* const* A, const uint8_t* const* B, size_t size, float* distances, size_t stride) { - size_t i = 0, size16 = AlignLo(size, 16), o = 16; + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16), o = 16; __m256i a0, b0; __m256i ab00 = _mm256_setzero_si256(); __m256i ab01 = _mm256_setzero_si256(); __m256i ab02 = _mm256_setzero_si256(); __m256i ab03 = _mm256_setzero_si256(); - for (; i < size16; i += 16, o += 10) + for (; i < size16a; i += 16, o += 10) { a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[0] + o))), C5_SHFL), C5_MULLO), 11); @@ -541,20 +622,36 @@ namespace Simd b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(B[3] + o))), C5_SHFL), C5_MULLO), 11); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } + for (; i < size16; i += 16, o += 10) + { + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(A[0] + o)), C5_SHFL), C5_MULLO), 11); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[0] + o)), C5_SHFL), C5_MULLO), 11); + ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[1] + o)), C5_SHFL), C5_MULLO), 11); + ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[2] + o)), C5_SHFL), C5_MULLO), 11); + ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(B[3] + o)), C5_SHFL), C5_MULLO), 11); + ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); + } for (; i < size; i += 8, o += 5) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C5_SHFL), C5_MULLO), 11); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(A[0] + o)), C5_SHFL), C5_MULLO), 11); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[0] + o)), C5_SHFL), C5_MULLO), 11); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[1] + o)), C5_SHFL), C5_MULLO), 11); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[2] + o)), C5_SHFL), C5_MULLO), 11); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C5_SHFL), C5_MULLO), 11); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<5>(B[3] + o)), C5_SHFL), C5_MULLO), 11); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } __m128 ab0 = _mm_cvtepi32_ps(Extract4Sums(ab00, ab01, ab02, ab03)); @@ -563,13 +660,13 @@ namespace Simd template<> void MicroCosineDistancesDirect1x4<6>(const uint8_t* const* A, const uint8_t* const* B, size_t size, float* distances, size_t stride) { - size_t i = 0, size16 = AlignLo(size, 16), o = 16; + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16), o = 16; __m256i a0, b0; __m256i ab00 = _mm256_setzero_si256(); __m256i ab01 = _mm256_setzero_si256(); __m256i ab02 = _mm256_setzero_si256(); __m256i ab03 = _mm256_setzero_si256(); - for (; i < size16; i += 16, o += 12) + for (; i < size16a; i += 16, o += 12) { a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[0] + o))), C6_SHFL), C6_MULLO), 10); @@ -585,20 +682,36 @@ namespace Simd b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(B[3] + o))), C6_SHFL), C6_MULLO), 10); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } + for (; i < size16; i += 16, o += 12) + { + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(A[0] + o)), C6_SHFL), C6_MULLO), 10); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[0] + o)), C6_SHFL), C6_MULLO), 10); + ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[1] + o)), C6_SHFL), C6_MULLO), 10); + ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[2] + o)), C6_SHFL), C6_MULLO), 10); + ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(B[3] + o)), C6_SHFL), C6_MULLO), 10); + ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); + } for (; i < size; i += 8, o += 6) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C6_SHFL), C6_MULLO), 10); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(A[0] + o)), C6_SHFL), C6_MULLO), 10); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[0] + o)), C6_SHFL), C6_MULLO), 10); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[1] + o)), C6_SHFL), C6_MULLO), 10); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[2] + o)), C6_SHFL), C6_MULLO), 10); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C6_SHFL), C6_MULLO), 10); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<6>(B[3] + o)), C6_SHFL), C6_MULLO), 10); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } __m128 ab0 = _mm_cvtepi32_ps(Extract4Sums(ab00, ab01, ab02, ab03)); @@ -607,13 +720,13 @@ namespace Simd template<> void MicroCosineDistancesDirect1x4<7>(const uint8_t* const* A, const uint8_t* const* B, size_t size, float* distances, size_t stride) { - size_t i = 0, size16 = AlignLo(size, 16), o = 16; + size_t i = 0, size16 = AlignLo(size, 16), size16a = AlignLo(size - 1, 16), o = 16; __m256i a0, b0; __m256i ab00 = _mm256_setzero_si256(); __m256i ab01 = _mm256_setzero_si256(); __m256i ab02 = _mm256_setzero_si256(); __m256i ab03 = _mm256_setzero_si256(); - for (; i < size16; i += 16, o += 14) + for (; i < size16a; i += 16, o += 14) { a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(A[0] + o))), C7_SHFL), C7_MULLO), 9); @@ -629,20 +742,36 @@ namespace Simd b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)(B[3] + o))), C7_SHFL), C7_MULLO), 9); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } + for (; i < size16; i += 16, o += 14) + { + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(A[0] + o)), C7_SHFL), C7_MULLO), 9); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[0] + o)), C7_SHFL), C7_MULLO), 9); + ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[1] + o)), C7_SHFL), C7_MULLO), 9); + ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[2] + o)), C7_SHFL), C7_MULLO), 9); + ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); + + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(B[3] + o)), C7_SHFL), C7_MULLO), 9); + ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); + } for (; i < size; i += 8, o += 7) { - a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(A[0] + o))), C7_SHFL), C7_MULLO), 9); + a0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(A[0] + o)), C7_SHFL), C7_MULLO), 9); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[0] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[0] + o)), C7_SHFL), C7_MULLO), 9); ab00 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab00); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[1] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[1] + o)), C7_SHFL), C7_MULLO), 9); ab01 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab01); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[2] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[2] + o)), C7_SHFL), C7_MULLO), 9); ab02 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab02); - b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadl_epi64((__m128i*)(B[3] + o))), C7_SHFL), C7_MULLO), 9); + b0 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(_mm256_castsi128_si256(Sse41::LoadLast8<7>(B[3] + o)), C7_SHFL), C7_MULLO), 9); ab03 = _mm256_add_epi32(_mm256_madd_epi16(a0, b0), ab03); } __m128 ab0 = _mm_cvtepi32_ps(Extract4Sums(ab00, ab01, ab02, ab03)); diff --git a/src/Simd/SimdAvx2DescrIntCdu.cpp b/src/Simd/SimdAvx2DescrIntCdu.cpp index c2588f15ba..e0e056fa67 100644 --- a/src/Simd/SimdAvx2DescrIntCdu.cpp +++ b/src/Simd/SimdAvx2DescrIntCdu.cpp @@ -40,28 +40,28 @@ namespace Simd template<> SIMD_INLINE __m128i UnpackData16<4>(const uint8_t* src) { - __m256i s4 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); + __m256i s4 = _mm256_broadcastsi128_si256(Sse41::LoadLast16<4>(src)); __m256i s16 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(s4, C4_SHFL), C4_MULLO), 12); return _mm256_castsi256_si128(PackI16ToU8(s16, K_ZERO)); } template<> SIMD_INLINE __m128i UnpackData16<5>(const uint8_t* src) { - __m256i s5 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); + __m256i s5 = _mm256_broadcastsi128_si256(Sse41::LoadLast16<5>(src)); __m256i s16 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(s5, C5_SHFL), C5_MULLO), 11); return _mm256_castsi256_si128(PackI16ToU8(s16, K_ZERO)); } template<> SIMD_INLINE __m128i UnpackData16<6>(const uint8_t* src) { - __m256i s6 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); + __m256i s6 = _mm256_broadcastsi128_si256(Sse41::LoadLast16<6>(src)); __m256i s16 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(s6, C6_SHFL), C6_MULLO), 10); return _mm256_castsi256_si128(PackI16ToU8(s16, K_ZERO)); } template<> SIMD_INLINE __m128i UnpackData16<7>(const uint8_t* src) { - __m256i s7 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); + __m256i s7 = _mm256_broadcastsi128_si256(Sse41::LoadLast16<7>(src)); __m256i s16 = _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(s7, C7_SHFL), C7_MULLO), 9); return _mm256_castsi256_si128(PackI16ToU8(s16, K_ZERO)); } @@ -103,7 +103,7 @@ namespace Simd template void UnpackDataA(size_t count, const uint8_t* const* src, size_t size, uint8_t* dst, size_t stride) { - size_t size16 = AlignLo(size, 16), size32 = AlignLo(size, 32); + size_t size16 = AlignLo(size, 16), size32 = AlignLo(size - 1, 32); for (size_t i = 0; i < count; i++) { const uint8_t* ps = src[i] + 16; @@ -166,7 +166,7 @@ namespace Simd template void UnpackDataB(size_t count, const uint8_t* const* src, size_t size, uint8_t* dst, size_t stride) { - size_t countDF = AlignLo(count, DF), size16 = AlignLo(size, 16), size32 = AlignLo(size, 32), i, j, o; + size_t countDF = AlignLo(count, DF), size16 = AlignLo(size, 16), size32 = AlignLo(size - 1, 32), i, j, o; for (i = 0; i < countDF; i += DF, src += DF) { for (j = 0, o = 16; j < size32; j += 32, o += 4 * bits, dst += 16 * A) diff --git a/src/Simd/SimdAvx2DescrIntDec.cpp b/src/Simd/SimdAvx2DescrIntDec.cpp index 3059d335d2..04d9e94cb7 100644 --- a/src/Simd/SimdAvx2DescrIntDec.cpp +++ b/src/Simd/SimdAvx2DescrIntDec.cpp @@ -52,8 +52,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s4 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s4, Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<4>(src), Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); _mm256_storeu_ps(dst + 0, _mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift)); src += 4; dst += 8; @@ -65,7 +64,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s5 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -77,8 +76,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s5 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s5, Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<5>(src), Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); _mm256_storeu_ps(dst + 0, _mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift)); src += 5; dst += 8; @@ -90,7 +88,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s6 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -102,8 +100,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s6 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s6, Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<6>(src), Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); _mm256_storeu_ps(dst + 0, _mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift)); src += 6; dst += 8; @@ -115,7 +112,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s6 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -127,8 +124,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s7 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s7, Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<7>(src), Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); _mm256_storeu_ps(dst + 0, _mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift)); src += 7; dst += 8; @@ -161,7 +157,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s4 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -173,8 +169,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s4 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s4, Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<4>(src), Sse41::C4_SHFL0), Sse41::C4_MULLO), 12); _mm_storeu_si128((__m128i*)dst, _mm256_cvtps_ph(_mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift), 0)); src += 4; dst += 8; @@ -186,7 +181,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s5 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -198,8 +193,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s5 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s5, Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<5>(src), Sse41::C5_SHFL0), Sse41::C5_MULLO), 11); _mm_storeu_si128((__m128i*)dst, _mm256_cvtps_ph(_mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift), 0)); src += 5; dst += 8; @@ -211,7 +205,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s6 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -223,8 +217,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s6 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s6, Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<6>(src), Sse41::C6_SHFL0), Sse41::C6_MULLO), 10); _mm_storeu_si128((__m128i*)dst, _mm256_cvtps_ph(_mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift), 0)); src += 6; dst += 8; @@ -236,7 +229,7 @@ namespace Simd assert(size % 8 == 0); __m256 _scale = _mm256_set1_ps(scale); __m256 _shift = _mm256_set1_ps(shift); - size_t i = 0, size16 = AlignLo(size, 16); + size_t i = 0, size16 = AlignLo(size - 1, 16); for (; i < size16; i += 16) { __m256i s6 = _mm256_broadcastsi128_si256(_mm_loadu_si128((__m128i*)src)); @@ -248,8 +241,7 @@ namespace Simd } for (; i < size; i += 8) { - __m128i s7 = _mm_loadl_epi64((__m128i*)src); - __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(s7, Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); + __m128i s16 = _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(Sse41::LoadLast8<7>(src), Sse41::C7_SHFL0), Sse41::C7_MULLO), 9); _mm_storeu_si128((__m128i*)dst, _mm256_cvtps_ph(_mm256_fmadd_ps(_mm256_cvtepi32_ps(_mm256_cvtepu16_epi32(s16)), _scale, _shift), 0)); src += 7; dst += 8;