| 305 | } |
| 306 | |
| 307 | static inline void encode_simdized(const PT* input_vector, |
| 308 | PT* exceptions, |
| 309 | exp_p_t* exceptions_positions, |
| 310 | exp_c_t* exceptions_count, |
| 311 | ST* encoded_integers, |
| 312 | const factor_idx_t factor_idx, |
| 313 | const exponent_idx_t exponent_idx) { |
| 314 | // These arrays are thread_local static to ensure thread safety during multithreaded compression. |
| 315 | // See: https://github.com/cwida/ALP/issues/41 for discussion. |
| 316 | // Without thread_local, static arrays would be shared between threads, causing data races. |
| 317 | alignas(64) thread_local static PT ENCODED_VALUE_ARR[1024]; |
| 318 | alignas(64) thread_local static PT VALUE_ARR_WITHOUT_SPECIALS[1024]; |
| 319 | alignas(64) thread_local static UT TMP_INDEX_ARR[1024]; |
| 320 | |
| 321 | exp_p_t current_exceptions_count {0}; |
| 322 | uint64_t exceptions_idx {0}; |
| 323 | |
| 324 | // make copy of input with all special values replaced by ENCODING_UPPER_LIMIT |
| 325 | const auto* tmp_input = reinterpret_cast<const UT*>(input_vector); |
| 326 | for (size_t i {0}; i < config::VECTOR_SIZE; i++) { |
| 327 | const auto is_special = |
| 328 | ((tmp_input[i] & Constants<PT>::SIGN_BIT_MASK) >= |
| 329 | Constants<PT>::EXPONENTIAL_BITS_MASK) // any NaN, +inf and -inf |
| 330 | // (https://stackoverflow.com/questions/29730530/) |
| 331 | || tmp_input[i] == Constants<PT>::NEGATIVE_ZERO; |
| 332 | |
| 333 | if (is_special) { |
| 334 | VALUE_ARR_WITHOUT_SPECIALS[i] = ENCODING_UPPER_LIMIT; |
| 335 | } else { |
| 336 | VALUE_ARR_WITHOUT_SPECIALS[i] = input_vector[i]; |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | #pragma clang loop vectorize_width(64) |
| 341 | for (size_t i {0}; i < config::VECTOR_SIZE; i++) { |
| 342 | auto const actual_value = VALUE_ARR_WITHOUT_SPECIALS[i]; |
| 343 | |
| 344 | // Attempt conversion |
| 345 | const ST encoded_value = encode_value<false>(actual_value, factor_idx, exponent_idx); |
| 346 | encoded_integers[i] = encoded_value; |
| 347 | const PT decoded_value = decoder<PT>::decode_value(encoded_value, factor_idx, exponent_idx); |
| 348 | ENCODED_VALUE_ARR[i] = decoded_value; |
| 349 | } |
| 350 | |
| 351 | #ifdef __AVX512F__ |
| 352 | if constexpr (std::is_same_v<PT, double>) { |
| 353 | for (size_t i {0}; i < config::VECTOR_SIZE; i = i + 8) { |
| 354 | __m512d l = _mm512_loadu_pd(ENCODED_VALUE_ARR + i); |
| 355 | __m512d r = _mm512_loadu_pd(VALUE_ARR_WITHOUT_SPECIALS + i); |
| 356 | __m512i index = _mm512_loadu_pd(DOUBLE_INDEX_ARR + i); |
| 357 | auto is_exception = _mm512_cmpneq_pd_mask(l, r); |
| 358 | _mm512_mask_compressstoreu_pd(TMP_INDEX_ARR + exceptions_idx, is_exception, index); |
| 359 | exceptions_idx += LOOKUP_TABLE[is_exception]; |
| 360 | } |
| 361 | } else { |
| 362 | for (size_t i {0}; i < config::VECTOR_SIZE; i = i + 16) { |
| 363 | __m512 l = _mm512_loadu_ps(ENCODED_VALUE_ARR + i); |
| 364 | __m512 r = _mm512_loadu_ps(VALUE_ARR_WITHOUT_SPECIALS + i); |
nothing calls this directly
no outgoing calls
no test coverage detected