| 440 | |
| 441 | |
| 442 | Float NO_INLINE buffered(const PODArray<UInt8> & keys, const PODArray<Float> & values) |
| 443 | { |
| 444 | State map[256]{}; |
| 445 | |
| 446 | static constexpr size_t BUF_SIZE = 16384 / 256 / sizeof(Float); /// Should fit in L1d. |
| 447 | |
| 448 | Float buffers[256 * BUF_SIZE]; |
| 449 | Float * ptrs[256]; |
| 450 | |
| 451 | for (size_t i = 0; i < 256; ++i) |
| 452 | ptrs[i] = &buffers[i * BUF_SIZE]; |
| 453 | |
| 454 | size_t size = keys.size(); |
| 455 | const auto * key = keys.data(); |
| 456 | const auto * key_end = key + size; |
| 457 | const auto * value = values.data(); |
| 458 | |
| 459 | while (key < key_end) |
| 460 | { |
| 461 | *ptrs[*key] = *value; |
| 462 | |
| 463 | if (++ptrs[*key] == &buffers[(*key + 1) * BUF_SIZE]) /// Calculation is better than L1d load of cached end pointer. |
| 464 | { |
| 465 | ptrs[*key] -= BUF_SIZE; |
| 466 | map[*key].addBatch<BUF_SIZE>(ptrs[*key], BUF_SIZE); |
| 467 | } |
| 468 | |
| 469 | ++key; |
| 470 | ++value; |
| 471 | } |
| 472 | |
| 473 | for (size_t i = 0; i < 256; ++i) |
| 474 | map[i].addBatch<4>(&buffers[i * BUF_SIZE], ptrs[i] - &buffers[i * BUF_SIZE]); |
| 475 | |
| 476 | return map[0].result(); |
| 477 | } |
| 478 | |
| 479 | #pragma clang diagnostic push |
| 480 | #pragma clang diagnostic ignored "-Wframe-larger-than" |
no test coverage detected