mirror of
https://github.com/hanzoai/datastore.git
synced 2026-09-26 13:55:07 +00:00
Give `AggregateFunctionVarianceSimple` (`varPop`, `varSamp`, `stddevPop`, `stddevSamp`, `skewPop`, `skewSamp`, `kurtPop`, `kurtSamp`, `covarPop`, `covarSamp`, `corr`) the same treatment as `groupBitOr`/`groupBitAnd`/ `groupBitXor`: `addBatchSinglePlace`/`addBatchSinglePlaceNotNull` overrides with vectorized kernels on `VarMoments`/`CovarMoments`/`CorrMoments`. The `-If`/null flag zeroes the value's bit pattern with an integer mask (multiplying by the flag would let NaN/Inf in discarded rows poison the accumulators), and the loops unroll into 16 partial accumulators per moment - FP addition is not associative, so the compiler cannot do this itself. This also breaks the sequential FP dependency chain of the per-row path, so the no-`If` case speeds up as well. `Decimal` inputs keep the generic per-row path. Dispatch with `MULTITARGET_FUNCTION_X86_V4`, like `sum`. Measured (50M rows, 1 thread, unpredictable 50% predicate, server-side query time): `varSampIf`/`stddevSampIf`/`skewSampIf`/`kurtSampIf` -64..-67%, `covarSampIf`/`corrIf` -59..-62%, `Nullable` -57%, and -35..-68% without `-If` (`varSamp`/`kurtSamp`/`corr`). Summation order changes, so float results can differ in the last bits; on integer inputs the moment sums are exact and results are bit-identical (covered by the test).
27 lines
1.6 KiB
XML
27 lines
1.6 KiB
XML
<test>
|
|
<query>SELECT varSampIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT stddevPopIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT skewSampIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT kurtSampIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT covarSampIf(number, number + 1, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT corrIf(number, number + 1, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
|
|
<query>SELECT varSampIf(toFloat64(number), rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT varSampIf(toFloat32(number), rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
|
|
<query>SELECT varSamp(number) FROM numbers(100000000)</query>
|
|
<query>SELECT kurtSamp(number) FROM numbers(100000000)</query>
|
|
<query>SELECT corr(number, number + 1) FROM numbers(100000000)</query>
|
|
|
|
<!-- ~20% NULL values, random so the branch predictor doesn't do all the work -->
|
|
<create_query>CREATE TABLE nullfloat64_stats (x Nullable(Float64)) ENGINE = Memory</create_query>
|
|
<fill_query>INSERT INTO nullfloat64_stats
|
|
SELECT IF(rand() % 5 == 0, NULL::Nullable(Float64), toFloat64(cityHash64(number) % 1000000)) AS x
|
|
FROM numbers_mt(200000000)
|
|
SETTINGS max_threads = 8
|
|
</fill_query>
|
|
<query>SELECT varSamp(x) FROM nullfloat64_stats</query>
|
|
<query>SELECT varSampIf(x, rand32() % 2 = 0) FROM nullfloat64_stats</query>
|
|
<drop_query>DROP TABLE IF EXISTS nullfloat64_stats</drop_query>
|
|
</test>
|