Je potřeba dobrý index a nepočítat věci pořád znovu.
Jak počítá pgvector třeba cosine similarity?
Takto:
/* Auto-vectorized */
for (int i = 0; i < dim; i++)
{
similarity += ax[i] * bx[i];
norma += ax[i] * ax[i];
normb += bx[i] * bx[i];
}
A přitom 2/3 výpočtů se dá předpočítat. A toto funkce je bottleneck!
Takže problém pgvectoru je, že se nikdo nepokusil o optimalizace, a nebo je to v rámci pg prostě jedno, protože tam jsou jiné režie. Takže jak říkám, není to pro ty co chcou třeba 5k qps na jádro, ale pro ty, co jim stačí třeba 20.
To má i pgvector (tu aproximaci), ale i tak to nemá výkon, protože i při aproximaci je potřeba volat tu distance funkci třeba 10000x na query (když chci recall třeba kolem 98-99%).
V tomto případě se prostě vyplatí ručně optimalizovat a přemýšlet - fakt nechápu, proč by si ta databáze nemohla předpočítat ty sumy pro každý vektor, je to snad to nejjednodušší co se dá udělat a v tomto případě to je 66% compute gain (FMA není zadarmo a tento loop FMA jednoznačně saturuje).
Ale samozřejmě se vyplatí i další optimalizace - když mám index, tak to znamená "skoky" v DB, takže tady je lepší bulking a implementovat to přímo v té funkci. Dělal jsem na něčem takovám a je to fakt neuvěřitelné jak se to celé dá zoptimalizovat tak, že compute už není problém, ale memory bandwidth je - pak už není co dělat :)