Весело же — спросить у трёх миллиардов векторов, словно просить совета у толпы математиков на мини‑хакатоне: все говорят одновременно, но результат нужно упаковать в пару мегабайт. Я прошёл путь от полностью наивной реализации до векторизованного вычисления и столкнулся с классической цепочкой открытий: “это быстро”, “это всё ещё быстро”, и в конце — “погодите, у меня закончилась память”.
Начал с тривиального двойного цикла: для каждой пары документ‑вектор / запросный‑вектор вычислять скалярное произведение. Работает, но медленно — на небольших выборках уже видна деградация. Переложив вычисления на линейную алгебру NumPy и заменив циклы на матричное умножение, получил потрясающее ускорение: миллионы пересечений в доли секунды на локальной машине. Переход на float32 дал ещё прирост и экономию памяти.
Однако масштаб 3 миллиардов — это другая вселенная. Даже при float32 объём данных уходит в миллионы гигабайт (порядок тысяч терабайт), и ОЗУ обычного сервера тут бессильно. Решения очевидны по тексту: батчинг, генераторы, mmap для работы с данными на диске, запись промежуточных результатов, или использование системных оптимизаций на уровне C/Rust. Jeff Dean в ответах на подобные вопросы намекает на map‑reduce‑подходы для распределения работы — и это действительно жизнеспособный путь (см. обсуждение Jeff Dean и оригинальную заметку Vicki Boykis).
Если задача — вернуть только top‑k похожих документов, достаточно приближённых (ANN), то требования к хранению и скорости резко падают: специализированные структуры и библиотеки (а также SIMD‑оптимизированные реализации вроде SimSIMD) помогают свести проблему к разумным ресурсам. Но ключевой вывод, который часто забывают: прежде чем оптимизировать, нужно точно сформулировать требования — частота запросов, допустимая погрешность, доступный железный ресурс и характер результата (всё или только top‑k).
В итоге — технических путей много, но самый первый шаг всегда один: спросите у продукта, что он ждёт в ответ. Без этого даже самый изящный алгоритм будет битвой с ветряными векторами.
