@@ -121,6 +121,67 @@ template <const std::uint8_t IDX, typename T>
121121 } \
122122 }
123123
124+ #define test_quant_int2 (ti, to, rnd, is_stochastic, is_signed ) \
125+ TEST (quantize, quantize_##ti##_to_##to##_##rnd) { \
126+ std::mt19937 gen {0x9032002 }; \
127+ std::uniform_real_distribution<fp32_t > dist {-1.0 , 1.0 }; \
128+ \
129+ for (std::size_t n {}; n < iters; ++n) { \
130+ std::cout << " Iteration " << n << std::endl; \
131+ fp32_t scale {std::uniform_real_distribution<fp32_t >{0.1 , 1.0 }(gen)}; \
132+ std::size_t numel {std::uniform_int_distribution<std::size_t >{5000 , 1'5000 }(gen)}; \
133+ std::size_t numel_out {std::is_same_v<uint2_t , to> ? (numel+3 )>>2 : numel}; \
134+ std::int32_t zero_point {std::is_same_v<uint2_t , to> ? std::uniform_int_distribution<std::int32_t >{-1 , 2 }(gen) : \
135+ std::uniform_int_distribution<std::int32_t >{-128 , 127 }(gen)}; \
136+ \
137+ std::vector<ti> data_in {}; \
138+ std::vector<to> data_out_naive {}; \
139+ std::vector<to> data_out {}; \
140+ data_in.resize (numel); \
141+ data_out.resize (numel_out); \
142+ data_out_naive.resize (numel_out); \
143+ std::ranges::generate (data_in, [&] { return dist (gen); }); \
144+ quantize_naive<ti, to, piquant::round_mode::rnd>(data_in, data_out_naive, scale, zero_point); \
145+ piquant::context ctx {std::max (1u , std::thread::hardware_concurrency ())}; \
146+ ctx.quantize_generic <ti, to>(data_in, data_out, scale, zero_point, piquant::round_mode::rnd); \
147+ for (std::size_t i {}; i < numel_out; ++i) { \
148+ bool eq {eq = data_out[i] == data_out_naive[i]}; \
149+ std::int32_t a {unpack_nibble<0 >(data_out[i], is_signed)}; \
150+ std::int32_t b {unpack_nibble<1 >(data_out[i], is_signed)}; \
151+ std::int32_t a_naive {unpack_nibble<0 >(data_out_naive[i], is_signed)}; \
152+ std::int32_t b_naive {unpack_nibble<1 >(data_out_naive[i], is_signed)}; \
153+ if (is_stochastic) { \
154+ eq |= std::abs (a - a_naive) <= stochastic_epsilon; \
155+ eq |= std::abs (b - b_naive) <= stochastic_epsilon; \
156+ } else { \
157+ eq = eq && (a == a_naive) && (b == b_naive); \
158+ } \
159+ if (!eq) { \
160+ std::cout << " Mismatch at index " << i << " : " << " (" << a << " , " << b << " ) != (" << a_naive << " , " << b_naive << " ) -> " << (std::int32_t )(data_out[i].bits ) << " != " << (std::int32_t )(data_out_naive[i].bits ) << std::endl; \
161+ std::cout << " Input: " << static_cast <fp32_t >(data_in[i]) << std::endl; \
162+ std::cout << " Data in: [" ; \
163+ for (std::size_t j {}; j < numel; ++j) { \
164+ std::cout << static_cast <fp32_t >(data_in[j]) << " " ; \
165+ } \
166+ std::cout << " ]" << std::endl; \
167+ std::cout << " Data out (f): [" ; \
168+ for (std::size_t j {}; j < numel_out; ++j) { \
169+ std::cout << static_cast <std::int32_t >(data_out[j].bits ) << " " ; \
170+ } \
171+ std::cout << " ]" << std::endl; \
172+ std::cout << " Data out (n): [" ; \
173+ for (std::size_t j {}; j < numel_out; ++j) { \
174+ std::cout << static_cast <std::int32_t >(data_out_naive[j].bits ) << " " ; \
175+ } \
176+ std::cout << " ]" << std::endl; \
177+ std::cout << " Num el out: " << numel_out << std::endl; \
178+ std::cout << " Num el in: " << numel << std::endl; \
179+ ASSERT_TRUE (eq); \
180+ } \
181+ } \
182+ } \
183+ }
184+
124185test_quant_int4 (fp32_t , uint4_t , nearest, false , false )
125186test_quant_int4(fp32_t , uint4_t , stochastic, true , false )
126187test_quant_int4(bfp16_t , uint4_t , nearest, false , false )
0 commit comments