Плагин для прошивки Rockbox запускает модели TinyStories из проекта llama2.c Андрея Карпати прямо на iPod Video 5.5G. Автор порта под ником u/r0tlier0 описал проект 1 ноября 2026 года в сообществе r/LocalLLaMA: плагин читает модель с жёсткого диска плеера и считает инференс на процессоре 2006 года (пост автора).
Железо: PortalPlayer PP5022, ядро ARM7TDMI на 80 МГц, 64 МБ ОЗУ, FPU отсутствует. Модель на 15 млн параметров занимает 17 МБ и грузится в буфер, который в Rockbox обычно отведён под музыку. Побочный эффект простой: одновременно слушать треки и работать с моделью нельзя.
Дальше разбор по слоям: железо и происхождение модели, целочисленная арифметика вместо float, бюджет памяти, практические выводы. Оговорка про достоверность нужна сразу. Все детали взяты из одного поста, независимых подтверждений нет, скорость генерации и качество текста автор не приводит. Запуск на двух ядрах и тематическая модель для музыкальных рекомендаций пока остаются планами.
Что именно запустили на iPod и почему это нетривиально
Железо iPod Video 5.5G: PP5022, ARM7TDMI и отсутствие FPU
PortalPlayer PP5022 - система на кристалле, которая стояла в плеерах Apple пятого поколения. В чипе два ядра ARM7TDMI (автор отдельно упоминает планы задействовать оба, значит, второе ядро пока простаивает), частота 80 МГц, 64 МБ ОЗУ на всю систему.
Ключевое ограничение - отсутствие FPU. ARM7TDMI не умеет плавающую точку аппаратно: каждая операция с float превращается в вызов библиотечной подпрограммы, где одно умножение или сложение разворачивается в десятки инструкций. На 80 МГц, то есть примерно 80 миллионов тактов в секунду на всё сразу, включая чтение с диска, отрисовку меню и матричные умножения, места для float в горячем цикле нет.
Масштаб сравнения понятен без бенчмарков. Современные LLM крутят на ускорителях с десятками гигабайт памяти, а здесь 64 МБ делит прошивка, звук и модель, а тактовая частота ближе к миру микроконтроллеров, чем к настольным CPU.
Что такое llama2.c и TinyStories
llama2.c - компактная реализация вывода Llama-подобной модели на C: один исходный файл, без фреймворков и внешних зависимостей, с обучением и генерацией. Проект задуман как учебный: вся архитектура трансформера читается за вечер.
TinyStories - датасет и семейство моделей, обученных на коротких детских рассказах. Словарь и разнообразие текста там небольшие, поэтому даже модель на 15 млн параметров умеет связно продолжать простую историю. Именно такие модели и запущены на плеере.
Внутри llama2.c есть версия runq.c с int8-квантованием весов, её автор и взял за основу. Карпати к порту на iPod отношения не имеет: это независимый эксперимент энтузиаста с той же кодовой базой.
Почему LLM можно считать без плавающей точки
Основная работа при инференсе - умножение матрицы весов на вектор активаций и сложения, то есть длинная цепочка скалярных произведений. В int8 веса лежат как 8-битные целые с масштабом на группу, произведения накапливаются в 32-битных целых, а масштаб применяется в конце целочисленным умножением и сдвигом. FPU для такого пути не нужен.
Плавающая точка нужна в нескольких точках: экспонента в softmax и в сигмоиде внутри активации SwiGLU, обратный квадратный корень в RMSNorm, синусы и косинусы в позиционных кодировках RoPE. В посте явно раскрыты softmax и RMSNorm. Как обошлись с позиционными кодировками и активацией, автор не уточняет, и додумывать за него не стоит.
Каждое приближение добавляет ошибку, а слоёв много, поэтому ошибки накапливаются. О качестве вывода в посте ничего нет: ни примеров сгенерированного текста, ни сравнения с float-версией. Для TinyStories запас прочности выше среднего: короткие тексты, маленький словарь, редкие длинные зависимости, поэтому грубое квантование здесь переносится легче, чем на модели общего назначения.
Как int8 runq.c портировали на целочисленную арифметику
Ядро кейса в одном предложении: int8-версия runq.c переписана так, чтобы в вычислениях не осталось ни одной операции с плавающей точкой (источник). Работают три приёма: таблицы поиска для exp и softmax, целочисленный квадратный корень для RMSNorm и сам факт отказа от float на всём пути.
Lookup-таблицы для exp и softmax
Экспонента монотонна и на практике нужна в ограниченном диапазоне аргументов. Диапазон разбивают на отрезки, для каждого заранее считают значение и кладут в массив. Индекс получают из целочисленного аргумента сдвигом или умножением, и вместо вычисления функции просто читают элемент таблицы. Получается обмен вычислений на память: обращение к массиву стоит несколько тактов, вызов soft-float - намного больше.
softmax добавляет вторую часть: exp(x_i) делят на сумму всех exp(x_j). Числители берут из таблицы, сумму считают в целых числах, деление заменяют умножением на обратную величину, подобранную по той же логике. Так в целых числах остаётся вся операция.
Подводные камни тут предсказуемые. Значения на краях диапазона нужно ограничивать clamp-ом, иначе индекс выходит за границы массива. Таблица занимает ОЗУ, а 64 МБ общие с прошивкой и звуковым буфером. На хвостах распределения разрешение падает, и вероятности очень редких токенов отличаются от точных. Конкретных размеров таблиц в посте нет, как и формул пересчёта.
Целочисленный квадратный корень в RMSNorm
RMSNorm нормирует вектор по формуле y_i = x_i / sqrt(mean(x_j^2) + eps) * g_i, и корень здесь единственное место с плавающей точкой. Вместо float-версии работает целочисленный квадратный корень, о котором автор говорит одной строкой.
Конкретный алгоритм в посте не назван. В embedded-коде обычно берут либо побитовый метод (digit-by-digit), либо итерации Ньютона в целых числах, либо таблицу обратных корней с одной-двумя итерациями уточнения. Все три варианта дают результат за десятки тактов и не требуют FPU.
Практическая деталь, которая кусает при переносе: сумма квадратов по вектору быстро переполняет 32 бита. Перед корнем нужен нормирующий сдвиг, а после него сдвиг надо вернуть с компенсацией, иначе результат уедет на порядки. Точность корня в единицу младшего разряда для такой нормировки обычно достаточна, поскольку следующий слой всё равно квантуется.
Память: 17 МБ модели в музыкальном буфере
15 млн параметров в int8 - это около 15 МБ чистых весов. Файл модели занимает 17 МБ: остаток приходится на всё, что не сами веса. Плотность упаковки близка к теоретической, лишних копий в формате нет.
В Rockbox большая часть ОЗУ отведена под буфер, куда с диска читаются треки: плеер копит данные в памяти, чтобы реже раскручивать жёсткий диск и экономить батарею. Свободной памяти под модель практически нет, поэтому автор грузит её прямо с диска в этот музыкальный буфер.
Отсюда два следствия. Первое: музыка и модель несовместимы по времени, автор формулирует это с усмешкой - слушать треки, пока модель работает, нельзя. Второе: загрузка идёт с жёсткого диска, поэтому запуск плагина включает чтение 17 МБ с механики; таймингов в посте нет, но накопитель 2006 года быстрым не был.
17 МБ - только веса. Активации, KV-кэш и рабочие буферы добавляются сверху, и конкретных цифр автор не приводит. Для TinyStories контекст короткий, поэтому KV-кэш мал относительно весов, но при бюджете в 64 МБ ОЗУ на всю систему это всё равно тесно. Насколько важен тип кэша для памяти и скорости, видно на другом масштабе: в разборе запуска Qwen 3.8 27B на одной RTX 5090 отдельно разобраны int8 KV-кэш, разница между prefill и decode и методика честного замера.
Что это даёт на практике: уроки для локального запуска LLM
Три приёма из этого кейса переносятся на любое слабое железо: квантование весов в int8, отказ от float в горячем цикле, табличные приближения для нелинейных функций. Логика одна - заменить дорогую операцию целочисленной арифметикой или чтением из памяти, если память дешевле тактов.
В llama.cpp и ggml квантованные ядра с целочисленным накоплением давно стандарт, и там же видно, где кончается выигрыш: не каждый патч ускоряет инференс, часть даёт регресс на конкретных конфигурациях. Как это выглядит на практике, разобрано в материале про патчи и бенчмарки MoE-инференса в llama.cpp на RTX 4080.
Для владельца слабого ПК вывод прагматичный. Писать целочисленный инференс с нуля имеет смысл для встраиваемых устройств, ретро-железа и обучения: там каждый такт и каждый мегабайт видны. На десктопе быстрее взять готовый рантайм, чем повторять путь автора. И переносить чужие цифры на свой сетап нельзя: даже на близком железе результаты расходятся, что хорошо видно по замерам Qwen3.6-35B-A3B на Jetson AGX Orin 64GB, где 21 и 40 tok/s получены на одной и той же плате в разных условиях.
Планы про музыкальные рекомендации - отдельная весовая категория. Для анализа аудио нужны собственные модели, и на слабом железе это уже делают: в проекте Struna четыре нейросети локально разбирают mp3 в браузере, а вес моделей там около 22 МБ, сопоставимо с моделью на iPod. Разница в том, что браузеру доступны float-операции, а ARM7TDMI приходится обходиться целыми.
Ограничения кейса и что осталось за кадром
Достоверность материала ограничена форматом источника. Всё, что известно, взято из одного поста u/r0tlier0 от 1 ноября 2026 года (ссылка). Независимого подтверждения, повторной сборки или сторонних замеров нет.
- Скорость генерации, задержка на токен и время загрузки модели не указаны.
- Качество вывода не показано: нет ни примеров текста, ни сравнения с float-версией.
- Не уточнено, какие именно модели TinyStories проверялись, кроме модели на 15 млн параметров, и в каком объёме шло тестирование.
- Запуск на двух ядрах и тематическая модель для музыкальных рекомендаций описаны как намерения, а не как работающие функции.
- Как решены позиционные кодировки RoPE и активация, в посте не раскрыто.
Из этого списка следует простой вывод: кейс подтверждает сам факт запуска и набор приёмов, но не даёт чисел, по которым можно сравнивать подход с другими решениями.
Итог: кому и зачем нужен такой запуск
Ценность эксперимента в том, что он показывает инференс LLM как арифметику. Матричные умножения, нормировки и softmax можно переложить на целые числа и таблицы, и тогда модель поедет там, где нет ни GPU, ни FPU, ни гигабайтов памяти. Ограничение задаёт не архитектура трансформера, а бюджет тактов и ОЗУ.
Кому полезно разобраться: разработчикам встраиваемых систем, энтузиастам ретро-железа и тем, кто изучает квантование и целочисленные ядра изнутри. Здесь виден полный путь от int8-весов до конкретных замен для exp и sqrt. Кому не стоит тратить время: тем, кто просто хочет запустить LLM локально. Для этого есть готовые рантаймы с квантизацией, а плагин для iPod Video 5.5G остаётся демонстрацией и экспериментом, у которого нет ни замеров скорости, ни оценки качества.