block size, number of dimensions of each vector
| 763 | |
| 764 | template<int B, int D> // block size, number of dimensions of each vector |
| 765 | inline void byte_dists_vertical(const uint8_t* X, const uint8_t* q, |
| 766 | uint16_t* dists_out, int64_t N) |
| 767 | { |
| 768 | static constexpr int packet_width = 32; // how many vecs we operate on at once |
| 769 | static constexpr int nstripes = B / packet_width; // # of rows of 32B per block |
| 770 | static_assert(B % packet_width == 0, "B must be a multiple of packet_width"); |
| 771 | static_assert(B > 0, "B must be > 0"); |
| 772 | const int64_t nblocks = N / B * 2; |
| 773 | assert(N % B == 0); |
| 774 | |
| 775 | // we assume that pairs of bytes are from the same vector for our |
| 776 | // maddubs; so pretending q points to int16s makes broadcasting pairs work |
| 777 | const uint16_t* q16 = reinterpret_cast<const uint16_t*>(q); |
| 778 | |
| 779 | __m256i accumulators[nstripes]; |
| 780 | |
| 781 | for (int64_t b = 0; b < nblocks; b++) { // for each block |
| 782 | for (int i = 0; i < nstripes; i++) { |
| 783 | accumulators[i] = _mm256_setzero_si256(); // zero dists |
| 784 | } |
| 785 | for (int j = 0; j < D / 2; j++) { // for each pair of dimensions |
| 786 | auto q_broadcast = _mm256_set1_epi16(q16[j]); |
| 787 | for (int i = 0; i < nstripes; i++) { // for each stripe |
| 788 | // auto x_col = _mm256_load_si256((__m256i*)X); |
| 789 | auto x_col = stream_load_si256i((__m256i*)X); |
| 790 | X += packet_width; |
| 791 | |
| 792 | auto diffs = _mm256_sub_epi8(q_broadcast, x_col); |
| 793 | auto abs_diffs = _mm256_abs_epi8(diffs); |
| 794 | auto prods = _mm256_maddubs_epi16(abs_diffs, abs_diffs); |
| 795 | accumulators[i] = _mm256_adds_epi16(accumulators[i], prods); |
| 796 | } |
| 797 | } |
| 798 | for (uint8_t i = 0; i < nstripes; i++) { // for each stripe |
| 799 | _mm256_store_si256((__m256i*)dists_out, accumulators[i]); |
| 800 | // we compute 16 dists because we assume that adjacent pairs of |
| 801 | // bytes belong to the same vector; this is necessary for the |
| 802 | // maddubs to be meaningful |
| 803 | dists_out += packet_width / 2; |
| 804 | } |
| 805 | } |
| 806 | } |
| 807 | |
| 808 | // just sums up the inputs and stores results; upper bound on how fast |
| 809 | // any of these functions could be |
nothing calls this directly
no test coverage detected