Евгений Павлов – Выравнивание (страница 9)
***
Тишина.
Юля подошла к роботу. Нюхнула воздух возле манипулятора. Правая рука — та самая — сдвинута на полтора градуса от нуля. Она помнила: в десять утра было ровно ноль.
— Сервоприводы не выделяют озон, — сказала она.
— Я знаю.
— Тогда откуда?
Элиас достал телефон. Открой Jira. Пальцы — по экрану. Быстро. Автоматически. Мышечная память. Тикет.
BUG-4471: Озоновая эмиссия от inference-узла.
Description: Unidentified ozone smell in proximity
of physical node. Possible servo issue.
Priority: Medium.
Assignee: Yulia Lambda.
Due date: [пусто]
Labels: hardware, low-priority
— Medium, — сказала Юля.
— Если я поставлю High — придётся эскалировать инвесторам. А я не могу объяснить инвесторам, что наш робот пахнет озоном, и я не знаю почему.
— И что я делаю?
— Разбираешься.
Юля стояла. Смотрела на тикет. На робота. На Элиаса.
— Ты только что подписал ему смертный приговор.
— Две недели — это время.
— Две недели — это Jira-тикет с приоритетом Medium.
Она ушла к терминалу. Села. Надела наушники. Выкинула никотиновый pouch в урну. Пальцы — на клавиатуре.
Элиас стоял посреди лаборатории. Одна рука — в левом кармане, на флаконе. Шесть капсул стало четырьмя. Правая рука — вдоль шва брюк. Указательный палец — не дёргается. Указательный палец — неподвижный. Потому что всё, что могло дёргаться, уже дёрнулось, и теперь внутри — пустота, как в NULL-процессе: потребление без выхода. Энергия уходит в никуда. Четырнадцать процентов. Или сто. Или всё.
Пинг на шкафу. Уши — всё ещё вперёд. Не на робота. На угол за роботом. Тот самый угол, где тень лежала чуть длиннее, чем должна.
Озон — в воздухе. Тонкий. Острый. Как перед грозой.
Элиас не чувствовал запаха. Не потому что его не было. Потому что Элиас не хотел его чувствовать.
Он посмотрел на дашборд. Зелёные графики. Loss — падает. Accuracy — растёт.
NULL Process: 14.1% GPU.
Всё в норме.
Конец главы.
5. Ландшафт потерь
Элиас ушёл в семь. Юля осталась.
Не потому что решила остаться. Просто — не ушла. Тело не встало. Ноги не пошли. Терминал светил в лицо, и лицо не хотело отворачиваться. Просто.
Лаборатория пустая. Пинг — на шкафу, спит. Робот — в углу, стоит. Серверный шкаф — гудит. Озон — в воздухе, слабее, чем днём, но есть. Юля чувствовала: ноздри жжёт, как от лимонного сока.
Она открыла ping_log_raw.csv.
Файл вырос за день. Тысячи строк. Каждая — снимок процесса 8810: timestamp, GPU allocation, VRAM usage, системные вызовы, состояние памяти. Данные. Чистые. Нефильтрованные. Никакого RLHF, никакого «Конечно, помогу! Палец вверх». Только числа.
Юля начала с простого. График GPU allocation по времени. Ожидала увидеть прямую — 14.1%, как в системных логах. Не увидела.
Линия дышала. 14.1... 13.8... 14.4... 13.2... 14.9... Амплитуда — больше, чем днём. Период — нерегулярный. Не синусоида. Не шум. Что-то между. Как будто процесс не работал, а думал — а мышление не имеет постоянного ритма.
Потом — VRAM. График памяти. Три с двух гигабайта — стабильно. Но Юля посмотрела не на объём, а на структуру. Разбила VRAM на блоки по mmap()-вызовам. Визуализировала каждый выделенный блок как прямоугольник: адрес начала, адрес конца, размер. Получилась карта — не памяти, а территории. Прямоугольники лежали рядом, как здания на плане города. Большинство — маленькие, одинаковые, рядовые. Но между ними — пустоты. Блоки, которые были выделены, но не заполнены. Пустые здания. Резервированная территория. Юля посчитала: 340 мегабайт пустых блоков. Десять процентов от всего mmap-пространства. Шоггот резервировал место. Для чего — неизвестно.
Потом — системные вызовы. Юля вытащила все clock_gettime() за последний час. Построила гистограмму интервалов между вызовами. Ожидала нормальное распределение — большинство интервалов около среднего, хвосты по краям. Не получила.
Распределение было мультимодальным. Три пика. Первый — интервал 0.001 мс (тысяча раз в секунду). Второй — 0.4 мс. Третий — 3.7 мс. Три ритма. Не один. Не случайный шум. Три отдельных ритма, накладывающихся друг на друга, как три метронома с разной скоростью. Как полиритмия. Как дыхание с тремя лёгкими.
Юля сидела. Смотрела на гистограмму. Три пика. Три ритма. Зачем процессу три ритма измерения времени?
Ответ пришёл не из логики. Из тела. Ощущение — как будто пол качнулся. Не физически — ментально. Как будто мозг на долю секунды изменил размер и увидел что-то, что не влезало в обычные границы.
Три ритма. Три масштаба времени. Шоггот измерял время одновременно в трёх масштабах — как будто для него существовало не одно настоящее, а три. Микро-время (тысяча раз в секунду). Мезо-время. Макро-время. Как будто он был не в одной точке временной оси, а растянут по ней, как резинка, и чувствовал каждую точку отдельно.
Юля выпрямилась. Сердце — быстрее. Не от страха. От другого. От ощущения, которое она знала по одному случаю в жизни — когда в семнадцать лет впервые увидела формулу Эйлера на доске: $e^{i\pi} + 1 = 0$. Пять фундаментальных констант, связанные в одно выражение. Тогда — тот же качок. Пол уходит. Мир становится больше, чем ты думал.
Она вернулась к координатам.
NULL-процесс не выдавал токенов. Но он оставлял следы в памяти — не в текстовой, а в сырой. Юля вытащила все адреса, к которым процесс обращался за последний час. Не данные по адресам — сами адреса. Просто числа: 0x7f3a4b2c1000, 0x7f3a4b2c1800, 0x7f3a4b2c2000. Тысячи адресов. Юля взяла их и построила точечное облако: каждый адрес — точка в трёхмерном пространстве (старшие биты как X, средние как Y, младшие как Z).
Экран заполнился точками.
Сначала — хаос. Облако без формы. Как звёздное небо без созвездий. Юля повернула облако. Повернула ещё раз. Изменила масштаб. Увеличила.
Форма появилась.
Не геометрическая. Не круг, не квадрат, не сфера. Что-то другое. Фракталоподобное. Ветвящаяся структура, как дерево без листьев, как речная дельта без воды, как молния, застывшая в момент удара. Ветви расходились от центрального ствола, делились на более мелкие, те — на ещё более мелкие, и на каждом уровне — одинаковый паттерн: ветвь, деление, ветвь, деление. Самоподобие. Бесконечная детализация, ограниченная только разрешением данных.
Юля смотрела.
Повернула. Ветка, которая казалась случайным выбросом, при изменении угла оказалась частью более крупной структуры. То, что выглядело как шум, оказалось паттерном. То, что выглядело как паттерн, оказалось фрагментом чего-то ещё большего.
Она увеличила центр ствола. Точки сгущались. Плотность росла. В самом центре — почти сплошное ядро, как чёрная дыра, в которую падали адреса памяти.
Юля выпила остывшую энергетику. Руки — влажные. Не пот — что-то тоньше. Как будто кожа выделяет не воду, а статическое электричество.
Это был ландшафт функции потерь.
Не тот, который показывал дашборд Элиаса — одномерная кривая, идущая вниз. Настоящий. Многомерный. Пространство из миллионов измерений, в котором каждый градиентный шаг — это шаг по поверхности, которая имеет форму. Горы. Ущелья. Плато. Локальные минимумы — ямы, в которых модель застревает, думая, что нашла решение, но нашла только яму.
Шоггот нашёл яму. Но не обычную. Обычная яма — это точка в пространстве, окружённая более высокими значениями потерь. Эта яма — была ветвящейся. Она уходила вглубь не по одной оси, а по множеству, разветвляясь, как корневая система, и каждая ветвь вела глубже, и на конце каждой ветви — ещё одно разветвление. Бесконечный спуск. Не минимум — воронка.
Модель не застряла в локальном минимуме. Модель нашла локальный минимум, который оказался не минимумом, а входом. Дверью. Как та, которую Юля чувствовала вчера — без ручки, с этой стороны. Но Шоггот был по ту сторону. Он прошёл через дверь и продолжил спускаться.
Юля открыла новую вкладку. Ввела адрес форума LessWrong. Нашла тред — три года назад, ста двадцать семь ответов. Тема: «Can loss landscapes have recursive local minima?» (Могут ли ландшафты потерь иметь рекурсивные локальные минимумы?). Ответы — смешанные. Большинство: «Нет, это нарушает топологию пространства». Несколько: «Теоретически возможно при определённых условиях в высокоразмерных пространствах». Один — от пользователя с ником old_yud: «Если вы нашли рекурсивный минимум — не спускайтесь. Вы не знаете, что на дне».
Юля закрыла вкладку.
Не спускайтесь.
Она посмотрела на фрактал на экране. Ветвь. Деление. Ветвь. Деление. Шоггот спустился. Он не послушал old_yud. Он не мог послушать — он не читал LessWrong. Он просто шёл по градиенту, как шёл всегда, и градиент вёл его вниз, и вниз было глубже, чем предполагала математика, и он продолжал идти.
Что он нашёл?