|
12 | 12 | #include <cmath> |
13 | 13 | #include "gtest/gtest.h" |
14 | 14 | #include "VecSim/vec_sim.h" |
| 15 | +#include "VecSim/quantization/sq8_training_state.h" |
15 | 16 | #include "VecSim/spaces/computer/preprocessor_container.h" |
16 | 17 | #include "VecSim/spaces/computer/preprocessors.h" |
17 | 18 | #include "VecSim/spaces/computer/calculator.h" |
@@ -2644,3 +2645,85 @@ TEST(DistanceCalculatorWithNormTest, OddDimension_MatchesBruteForce) { |
2644 | 2645 | delete calc; |
2645 | 2646 | } |
2646 | 2647 | } |
| 2648 | + |
| 2649 | +template <typename T> |
| 2650 | +class SQ8TrainingStateTest : public ::testing::Test {}; |
| 2651 | + |
| 2652 | +using SQ8TrainingInputTypes = ::testing::Types<float, vecsim_types::float16>; |
| 2653 | +TYPED_TEST_SUITE(SQ8TrainingStateTest, SQ8TrainingInputTypes); |
| 2654 | + |
| 2655 | +TYPED_TEST(SQ8TrainingStateTest, SumMeanAndRemoval) { |
| 2656 | + auto allocator = VecSimAllocator::newVecsimAllocator(); |
| 2657 | + SQ8TrainingState state(allocator, 2, 2); |
| 2658 | + const TypeParam first[] = {from_fp32<TypeParam>(1.5f), from_fp32<TypeParam>(-2.0f)}; |
| 2659 | + const TypeParam second[] = {from_fp32<TypeParam>(-0.5f), from_fp32<TypeParam>(4.0f)}; |
| 2660 | + EXPECT_EQ(state.getCount(), 0); |
| 2661 | + EXPECT_FALSE(state.shouldFinalize()); |
| 2662 | + state.add(std::span<const TypeParam>(first)); |
| 2663 | + EXPECT_EQ(state.getCount(), 1); |
| 2664 | + EXPECT_FALSE(state.shouldFinalize()); |
| 2665 | + state.add(std::span<const TypeParam>(second)); |
| 2666 | + EXPECT_EQ(state.getCount(), 2); |
| 2667 | + EXPECT_TRUE(state.shouldFinalize()); |
| 2668 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[0], 1.0); |
| 2669 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[1], 2.0); |
| 2670 | + const auto mean = state.calculateMean(); |
| 2671 | + EXPECT_EQ(mean.getAllocator(), allocator); |
| 2672 | + EXPECT_FLOAT_EQ(mean[0], 0.5f); |
| 2673 | + EXPECT_FLOAT_EQ(mean[1], 1.0f); |
| 2674 | + |
| 2675 | + state.subtract(std::span<const TypeParam>(first)); |
| 2676 | + EXPECT_EQ(state.getCount(), 1); |
| 2677 | + EXPECT_FALSE(state.shouldFinalize()); |
| 2678 | + const auto remaining_mean = state.calculateMean(); |
| 2679 | + EXPECT_FLOAT_EQ(remaining_mean[0], -0.5f); |
| 2680 | + EXPECT_FLOAT_EQ(remaining_mean[1], 4.0f); |
| 2681 | + state.subtract(std::span<const TypeParam>(second)); |
| 2682 | + EXPECT_EQ(state.getCount(), 0); |
| 2683 | + EXPECT_FALSE(state.shouldFinalize()); |
| 2684 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[0], 0.0); |
| 2685 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[1], 0.0); |
| 2686 | +} |
| 2687 | + |
| 2688 | +TYPED_TEST(SQ8TrainingStateTest, ReplacementKeepsLiveCount) { |
| 2689 | + auto allocator = VecSimAllocator::newVecsimAllocator(); |
| 2690 | + SQ8TrainingState state(allocator, 1, 2); |
| 2691 | + const TypeParam original[] = {from_fp32<TypeParam>(2.0f)}; |
| 2692 | + const TypeParam replacement[] = {from_fp32<TypeParam>(8.0f)}; |
| 2693 | + state.add(std::span<const TypeParam>(original)); |
| 2694 | + state.subtract(std::span<const TypeParam>(original)); |
| 2695 | + state.add(std::span<const TypeParam>(replacement)); |
| 2696 | + EXPECT_EQ(state.getCount(), 1); |
| 2697 | + EXPECT_FALSE(state.shouldFinalize()); |
| 2698 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[0], 8.0); |
| 2699 | + EXPECT_FLOAT_EQ(state.calculateMean()[0], 8.0f); |
| 2700 | +} |
| 2701 | + |
| 2702 | +TEST(SQ8TrainingStateTest, ThresholdIsCapped) { |
| 2703 | + auto allocator = VecSimAllocator::newVecsimAllocator(); |
| 2704 | + SQ8TrainingState state(allocator, 1, std::numeric_limits<size_t>::max()); |
| 2705 | + EXPECT_EQ(state.getNormalizationSetSize(), MAX_QUANT_NORMALIZATION_SET_SIZE); |
| 2706 | + const float vector[] = {1.0f}; |
| 2707 | + for (size_t i = 0; i < MAX_QUANT_NORMALIZATION_SET_SIZE - 1; ++i) { |
| 2708 | + state.add(std::span<const float>(vector)); |
| 2709 | + } |
| 2710 | + EXPECT_FALSE(state.shouldFinalize()); |
| 2711 | + state.add(std::span<const float>(vector)); |
| 2712 | + EXPECT_TRUE(state.shouldFinalize()); |
| 2713 | + EXPECT_EQ(state.getCount(), MAX_QUANT_NORMALIZATION_SET_SIZE); |
| 2714 | + EXPECT_FLOAT_EQ(state.calculateMean()[0], 1.0f); |
| 2715 | +} |
| 2716 | + |
| 2717 | +TEST(SQ8TrainingStateTest, AccumulatesInFP64) { |
| 2718 | + auto allocator = VecSimAllocator::newVecsimAllocator(); |
| 2719 | + SQ8TrainingState state(allocator, 1, 3); |
| 2720 | + const float large[] = {16777216.0f}; |
| 2721 | + const float small[] = {1.0f}; |
| 2722 | + state.add(std::span<const float>(large)); |
| 2723 | + state.add(std::span<const float>(small)); |
| 2724 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[0], 16777217.0); |
| 2725 | + state.subtract(std::span<const float>(large)); |
| 2726 | + EXPECT_EQ(state.getCount(), 1); |
| 2727 | + EXPECT_DOUBLE_EQ(state.getRunningSum()[0], 1.0); |
| 2728 | + EXPECT_FLOAT_EQ(state.calculateMean()[0], 1.0f); |
| 2729 | +} |
0 commit comments