惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
T
Tenable Blog
T
Threatpost
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Security Latest
Security Latest
P
Privacy & Cybersecurity Law Blog
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
P
Palo Alto Networks Blog
TaoSecurity Blog
TaoSecurity Blog
Webroot Blog
Webroot Blog
Spread Privacy
Spread Privacy
O
OpenAI News
The Last Watchdog
The Last Watchdog
P
Proofpoint News Feed
C
Check Point Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
人人都是产品经理
人人都是产品经理
S
Security @ Cisco Blogs
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
月光博客
月光博客
S
Securelist
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
T
Troy Hunt's Blog
W
WeLiveSecurity
GbyAI
GbyAI
N
News | PayPal Newsroom
Y
Y Combinator Blog
C
Cisco Blogs
H
Help Net Security
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
博客园 - 【当耐特】
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
小众软件
小众软件
N
News and Events Feed by Topic

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Насколько многомерным может быть многомерный точный индекс?
zzeng · 2026-05-18 · via Все публикации подряд на Хабре

Насколько многомерным может быть многомерный точный индекс?

Уровень сложностиСредний

Время на прочтение7 мин

Охват и читатели7

Вот, например, Milvius(DiskANN) рассчитан на вектора размерности до 32 768, но это приближенный поиск.  Но как насчёт поиска точного?

В данной статье рассматривается работоспособность 1024 мерного индекса, хранилищем которого служит обычное B-дерево (насколько вообще может быть обычным такое дерево). Используемый диск - вполне себе “железный” старый добрый WD Purple, оперативная память сознательно ограничена 8 Гб. Можно ли что-то из этого выжать на рядовом десктопе за приемлемое время?

Данная работа опирается на ранее описанный алгоритм:
Презентация алгоритма
3D и очевидные оптимизации
8D и перспективы в OLAP
3D на сфере
Как насчет индексации неточечных объектов?
А что с кривой Гильберта ?
Заметающие кривые
Логический (одноразрядный) многомерный индекс
Исходники

Задача

Удачно выбранный пример - половина успеха.

  • индексируем 1024-мерные точки. Этого довольно (с точки зрения автора) чтобы прикоснуться к прелестям многомерных пространств. Но недостаточно много, чтобы вся затея превратилась в сплошное занудство. Принципиальное ограничение - на одной странице дерева должно помещаться два и более элемента, иначе, какое же это дерево. Так что, требуется больше размерность - увеличиваем размер страницы.

  • точка устроена так: (sin(x), sin(2*x),...,sin(1024*x)) где x принимает значения от 0 до 2𝛑 с шагом 0.000002𝛑, всего миллион значений. Миллиона довольно, чтобы почувствовать как устроена задача, но недостаточно …

  • значения 8-разрядные, сдвинуты вверх так, чтобы заметать диапазон [0…255]. Автор экспериментировал и с 16-разрядными значениями, принципиально ничего не меняется, разница лишь в том, сколько элементов помещается на странице

  • используется кодирование Z-Order

  • после кодирования точка превращается в 8192-разрядное целое число

  • в индексе это число выглядит как ключ из 128 беззнаковых 64 разрядных целых чисел

  • экспериментируем с размерами страниц от 8 до 64K

  • при индексировании применяется сжатие, но для такого рода данных оно мало что даёт

Образец данных в текстовом виде: сначала номер строки, затем 1024 значения

#                                                                                                                                                              1 , 128, 128, 128, … 128

590383 , 60, 243, 3, 225, 91, 95, 222, … 245, 4, 220, 98, 88

1000000 , 128, 128, 128, … 128

Индексация

При построении индекса каждая точка превращается в 8192 разрядное число, которое заносится в индекс самым обычным образом. Многомерный поиск заключен именно в поиске а не в индексации.

Что касается реализации B-дерева, в ней нет ничего необычного, вполне заурядное проприетарное дерево. Нет ничего проще, чем написать своё B-дерево, я сам это делал неоднократно.

  • Время индексации (8к страницы): 12’6’’, для остальных страниц примерно  то же

  • Пиковое потребление памяти: ~2 Гб, управляется выделенным пулом страниц

  • Размер индекса: ~1.25Гб, для всех типов страниц, оно и понятно, объем информации не меняется

  • или ~ 156 000 страниц по 8К 

  • в среднем число элементов на такой странице: 6.4
    т.е. сжатия практически нет.

Глянем одним глазком что насоздавали

Совместное представление значений в разных размерностях показано ниже.

Фиг.1 совместное распределение колонок 100, 200 и 300

Фиг.1 совместное распределение колонок 100, 200 и 300

Фиг.2 совместное распределение колонок 8, 18 и 28

Фиг.2 совместное распределение колонок 8, 18 и 28

Фиг.3 совместное распределение колонок 13, 31 и 101

Фиг.3 совместное распределение колонок 13, 31 и 101

Поиск в окрестности

Проверим работоспособность индекса, во первых, при поиске на точное совпадение, во вторых, в окрестности искомой точки.

Будем брать произвольные вектора (3 штуки - с номерами 590383, 117806, 711480) из исходных данных, делать поиск вокруг них в расширяющейся окрестности по каждой размерности. Если размер окрестности нулевой, это точное совпадение.

Результатом будет количество прочитанных страниц

из холодного состояния

и число полученных результатов. Холодное состояние подразумевает отсутствие страниц в кэше и их распаковку при чтении. Но диск всё равно “разогретый” так что собственно физическое чтение не учитывается, для “охлаждения” диска потребуется индекс потолще, размером побольше дискового кэша ОС.

Три точки, конечно не слишком представительная выборка, тем не менее этого достаточно, чтобы получить общее представление о задаче, не впадая в уныние от необходимости миллион раз перезапускать сервер.

название

время, мс
8/16/32/64K страницы

число прочитанных страниц (8/16/32/64K)

к-во результатов


точное совпадение

4 / 4 / 5 / 4
4 / 4 / 5 / 5
4 / 5 / 5 / 4

6 / 4 / 3 / 3
5 / 4 / 3 / 3
6 / 4 / 3 / 3

1
1
1


окрестность ± 1

27 / 5 / 3 / 4
20 / 5 / 6 / 4
21 / 5 / 7 / 5

9 / 6 / 5 / 4
6 / 4 / 3 / 3
8 / 6 / 4 / 4

3
3
3


окрестность ± 2

18 / 28 / 6 / 2
34 / 5 / 7 / 5
25 / 10 / 11 / 11

9 / 6  / 4 / 4
6 / 5  / 4 / 3
17 / 15 / 10 / 8

5
5
5


окрестность ± 4

24 / 49 / 7 / 2
29 / 51 / 22 / 4
16 / 5 /13 / 27

11 / 7 / 5 / 5
8 / 6 / 4 / 4
20 / 15 / 10 / 8

11
11
11


окрестность ± 8

69 / 49 /52 / 24
25 / 54 / 47 / 9
57 / 56 / 16 / 19

15 / 10 / 8 / 7
17 / 11 / 8 / 5
20 / 15 / 10 / 8

21
21
21


окрестность ± 16

80 / 71 / 47 / 52
79 / 57 / 52 / 28
63 / 48 / 24 / 47

37 / 22 / 14 / 11
77 / 47 / 33 / 26
50 / 34 / 20 / 14

41
41
41


окрестность ±32

124 / 81 / 76 / 63
125 / 85 / 60 / 40
116 / 75 / 42 / 53

146 / 95 / 61 / 40
108 / 66 / 37 / 27
105 / 68 / 44 / 30

82
81
82


окрестность ±64

255 / 143 / 126 / 71
242 / 164 / 114 / 114
206 / 175 / 97 / 143

413 / 259 / 168 / 114
378 / 226 / 140 / 96
427 / 262 / 180 / 126

162
164
163


окрестность ±96

368 / 177 / 180 / 150
342 / 244 / 175 / 157
312 / 225 / 157 / 151

927 / 573 / 376 / 268
904 / 539 / 361 / 255
857 / 523 / 341 / 240

246
247
246


окрестность ±128

2’28’’ / 1’21’’ / 48’’ / 31’’
2’29’’ / 1’22’’ / 46‘’ / 31’’
2’26’’ / 1’23’’ / 50’’ / 30’’

152995 / 70416 / 33162 / 16112
152938 / 70400 / 33159 / 16110
152991 / 70415 / 33162 / 16111

349
350
348

Таб.1  Число прочитанных страниц и найденных результатов в расширяющейся окрестности выбранных точек.

Фиг.4 данные из Таб.1 в графическом представлении  X-радиус Y-число страниц

Фиг.4 данные из Таб.1 в графическом представлении X-радиус Y-число страниц

Вызывает недоумение, что поиск с радиусом в 128 (т.е. во всю область значений) находит всего лишь несколько сотен значений из миллиона. Это одна из особенностей высоких размерностей. Например, если окрестность строится от значения 100, то она получится [0…228], т.е. некоторая фильтрация всё-таки произойдёт. А поскольку размерностей много, в результате отсеется почти всё. На самом деле, удивительно, что вообще хоть что-то нашлось.

Дело в данных. Младшая часть гармоник изменяется очень медленно. Старшие гармоники меняются примерно со скоростью расширения окрестности. Если размер окрестности равен 3, в ней окажутся сама центральная точка и две её соседки.
Это не специально, так получилось.

Поиск по частично неизвестным данным

Будем использовать те же модельные данные и те же три вектора (590383, 117806, 711480) для поиска в ситуации, когда часть координат(размерностей) не заполнена. В случае когда какая-та из координат считается неизвестной, для неё подставляется максимально возможный диапазон - в данном случае [0…255].
Неизвестными будем считать значения с начала вектора.
Поиск идёт на точное совпадение известной части вектора.

название

время, мс
8/16/32/64K страницы

число прочитанных 8/16/32/64K страниц

к-во результатов


полные вектора  (1024)

4 / 4 / 5 / 4
4 / 4 / 5 / 5
4 / 5 / 5 / 4

6 / 4 / 3 / 3
5 / 4 / 3 / 3
6 / 4 / 3 / 3

1
1
1


1024 - 100 => 924

2 / 2 / 6 / 4
4 / 1 / 6 / 5
2 / 4 / 3 / 3

6 / 4 / 3 / 3
5 / 4 / 3 / 3
6 / 4 / 3 / 3

1
1
1


1024 - 200 => 824

1 / 4 / 7 / 2
4 / 4 /1 / 2
4 / 4 / 5 / 4

6 / 4 / 3 / 3

5 / 4 / 3 / 3

6 / 4 / 3 / 3

1

1

1


1024 - 400 => 624

3 / 4 / 5 / 6
1 / 4 / 2 / 5
4 / 4 / 6 / 1

6 / 4 / 3 / 3
5 / 4 / 3 / 3

6 / 4 / 3 / 3

1

1

1


1024 - 800 => 224

1 / 5 / 5 / 2
2 / 3 / 4 / 2
4 / 6 / 2 / 1

6 / 4 / 3 / 3 

5 / 4 / 3 / 3

6 / 4 / 3 / 3

1

1

1


1024 - 1000 => 24

14 / 11 / 11 / 9
9 / 12 / 3 / 9
4 / 14 / 19 / 10

41 / 21 / 11 / 7
43 / 22 / 11 / 7
60 / 29 / 15 / 8

1
1
1


1024 - 1012 => 12

52 / 52 / 18 / 28
69 / 71 / 39 / 41
65 / 41 / 52 / 43

379 / 173 / 83 / 42
625 / 287 / 135 / 67
518 / 240 /113 / 65

1
1
1


1024 - 1018 => 6

146 / 73 / 74 / 81
178 / 155 / 96 / 82
328 / 229 / 148 / 104

1848 / 848 / 399 / 196
3257 / 1497 / 703 / 342
5059 / 2317 / 1089 / 530 

1
1
1


1024 - 1021 => 3

2058 / 1771 / 1593 / 1523
2032 / 1730 / 1799 / 1485
2085 / 1793 / 1565 / 1512

19136 / 8777 / 4120 / 2000
19135 / 8777 / 4120 / 2000
19135 / 8777 / 4120 / 2000

3
3
3

Таб.2 количество прочитанных страниц в зависимости от известной части точки (вектора)

Фиг.5 данные Таб.2 в графическом представлении  X-известная часть вектора Y-число страниц

Фиг.5 данные Таб.2 в графическом представлении X-известная часть вектора Y-число страниц

Кажется совершенно невероятным, что при всего 6 известных координатах точки (и 1018 неизвестных) в индексе нашелся единственный результат. Никакого чуда нет. Старшие координаты соответствуют самым высокочастотным гармоникам и комбинация из нескольких последних координат фактически является случайным числом с равномерным распределением. Поскольку в индексе всего миллион векторов (20 разрядов), а в одном значении - 8, часть вектора, делающая его уникальным должна быть длиннее 3.

В догонку совместное распределение числа прочитанных страниц и времени поиска 

Фиг.6 X-время в мсек, Y- число прочитанных 8К страниц

Фиг.6 X-время в мсек, Y- число прочитанных 8К страниц

Время поиска состоит (в нашем случае) из двух факторов - распаковка страниц, стоимость которой примерно одинакова для всех страниц и обработка внутренних подзапросов, сложность которой зависит от того, насколько “удачно” искомая точка легла в индекс.

Итого

Мы познакомились с 1024-х мерным поиском, но основной вопрос пока остаётся без ответа. Действительно, насколько он может быть многомерным?

Всё зависит от размера страниц. 8К страницы допускают с некоторым запасом 1024 размерности. Но мы потренировались и на 64К страницах, значит ли это, что можно говорить о 8192 размерном индексе?

Да, вполне. Более того, не запрещено использовать и страницы большего размера. Наоборот, мы видели, что чем большие страницы используются, тем быстрее идёт поиск.
Но есть же какие-то ограничения?

Разумеется. Во первых, чем больше страницы, тем дороже становятся изменения такого индекса. Одно дело перекомпоновать 8К страницу и совсем другое, когда в ней 256К. Дороже станет и создание индекса, ведь оно подразумевает (кроме тех случаев, когда всё можно отсортировать в памяти) сортировку и произвольную вставку в дерево.

Выше обращалось внимание на то, что значительная часть времени при поиске тратится на генерацию и обработку подзапросов. Этот процесс останавливается, когда текущий подзапрос целиком оказывается на одной листовой странице B-дерева. В этом случае данная страница просто просматривается целиком. Т.е. чем больше страницы, тем меньше будет порождено подзапросов.

Но есть и другая сторона. Если страница большая, а запросы не очень, значительная часть данных загружается, просматривается и отфильтровывается впустую. Так что это самобалансирующийся процесс. Мы видим, что время поиска в 32 и 64К страницах очень близко. 

На данный момент автор рассматривает 64К страницы как оптимальные (для конкретно этой задачи). Так что вот ответ - 8К - вот число размерностей для векторов, с которым  можно будет работать относительно комфортно. Хотя, технически допустимо сделать и намного больше.

PS: спасибо Олегу Бартунову (@zen), сподвигшему меня заняться всем этим.

PPS: титульная картинка взята из к.ф. “Интерстеллар”