Обновить
256K+

DIY или Сделай сам

Для тех, у кого руки растут из нужного места

594,61
Рейтинг
Сначала показывать
Порог рейтинга

TPU на FPGA размером с M.2 SSD : 48 ГБ памяти и до 62 токенов/с на FPGA?

После экспериментов с openTPU и запуска BitNet на старой Kintex-7 за $50 задумался: а что, если сделать собственный TPU в формфакторе M.2 ?

AMD недавно представила Kintex UltraScale+ Gen 2. У старшей 2KU050P довольно интересные характеристики:

  • 1 872 DSP

  • 50,9 Мбит внутренней памяти

  • 6 контроллеров LPDDR5X

  • До 102,4 ГБ/с теоретической пропускной способности памяти

Последнее особенно интересно. При генерации LLM часто упираемся не в вычисления, а в скорость чтения весов из памяти.

Параллельно рассматриваю и другие варианты: Kintex UltraScale+ XCKU5P и Kintex UltraScale XCKU040/XCKU060. У них нет таких встроенных контроллеров LPDDR5X, поэтому придётся использовать DDR4 и отдельно рассчитывать пропускную способность.

Набросал концепт KEDR-M.2:

  • FPGA 2KU050P

  • Плата 31 × 80 мм с разъёмом M.2 M-key (ширина нестандартная)

  • 3 × LPDDR5X x64 по 16 ГБ = 48 ГБ

  • 6 каналов памяти x32

  • openTPU с целевой матрицей 64 × 48

  • PCIe Gen4 x4

Посчитал теоретический предел скорости генерации.

Если взять 102,4 ГБ/с и предположить 70% эффективности использования памяти, получим около 71,7 ГБ/с.

Например, для Bonsai 8B с размером весов 1,15 ГБ это даёт около 62 ток/с, а для Qwen3-8B Q4_K_M (5,03 ГБ) - около 14 ток/с.

Здесь только теоретические пределы по пропускной способности памяти при условных 70% эффективности, а не результаты измерений. Реальная скорость будет зависеть от вычислительного ядра, KV-cache и других накладных расходов.

Самой платы тоже пока нет - это концепт. Разводку LPDDR5X, питание, тепловой режим и размещение FPGA на такой площади ещё предстоит проверить.

FPGA позволяет адаптировать железо непосредственно под формат модели.

Что думаете на счет такой платы? Что я упустил в расчётах? - конечно же цена сие добра по сравнению с готовыми GPU)

Продолжу публиковать эксперименты с FPGA и собственными AI-ускорителями здесь, на Хабре.

Теги:
+9
Комментарии6

Если не можешь читать быстрее - читай меньше! BitNet 2B на FPGA за $50: 17 токенов/с - в 1,4 раза быстрее Qwen3.5-2B. (КЕДР)

Идею попробовать BitNet мне подсказал @ripandtear в комментариях к первой статье. Тогда я ответил, что в openTPU нет поддержки тернарных весов и придётся дорабатывать архитектуру.

Прошло чуть больше двух недель, возвращаюсь с результатом :)
Поддержку добавил, модель запустилась.

В предыдущем эксперименте всё упёрлось в DDR3: Qwen3.5-2B выдавал на openTPU 12,5 токена в секунду, а память была загружена на 92-96% от пика. Матрица из 512 умножителей при генерации токенов большую часть времени простаивала - ей просто не хватало данных.

Как гласят древние сказания мудрецов и магов:
Если не можешь читать быстрее, читай меньше.

Проникся дзеном и решил попробовать BitNet b1.58 2B4T от Microsoft.

В отличие от обычных моделей, веса у неё тернарные: -1, 0 и +1. Теоретически для их представления достаточно 1,58 бита на вес против четырёх у FP4-версии Qwen. Реальный объём зависит от упаковки, но для платы, которая упирается в память, уменьшение весов может оказаться важнее скорости арифметики.

Железо всё то же:

  • FPGA: Xilinx Kintex-7 XC7K480T на списанной Inspur YPCB-00338;

  • Память: 2 × 2 ГБ DDR3-1066;

  • Подключение: к ноутбуку через USB4-бокс, PCIe Gen2;

  • Ускоритель: openTPU, прошивку пересобрал на 137,5 МГц с поддержкой BitNet (во второй части было 133,33 МГц).

Задал модели вопрос с подвохом:

Why can a tiny FPGA run a 2-billion-parameter language model? Explain the trick in simple terms.

Ответила связно: про квантование, параллельные вычисления и работу с памятью. Про главный трюк - собственные тернарные веса - скромно промолчала :)

Результаты

BitNet b1.58 2B4T:

  • Генерация: ~17 ток/с

  • Обработка промпта: ~47 ток/с

  • Время до первого токена: 0,57 с

  • Частота FPGA: 137,5 МГц

Qwen3.5-2B (FP4), предыдущий эксперимент:

  • Генерация: ~12 ток/с

  • Частота FPGA: 133,33 МГц

Обе модели запускались на одной плате Kintex-7 с DDR3, без GPU и облака.

Итого: BitNet показал скорость генерации в 1,38 раза выше, чем Qwen3.5-2B.

Честно об ограничениях. Для BitNet это один запуск, а у Qwen - медиана из пяти. Частота ядра чуть выше, промпты разные. Так что 1,4× - это ориентир, а не строгий бенчмарк.

Но порядок сходится с арифметикой. Память и здесь загружена так же, как у Qwen, на каждый токен читается около 0,9 ГБ против 1,285 ГБ у Qwen. Как раз примерно в 1,4 раза меньше. Выигрыш даёт не магия тернарных вычислений, а то, что весов просто меньше.

На этом эксперименты не заканчиваются. Хочу проверить, сколько ещё можно выжать из старого Kintex-7 с DDR3, прежде чем переходить на более современное железо.

А о том, что именно пришлось изменить в openTPU для поддержки BitNet, напишу отдельно. Покажу архитектуру тернарных вычислений, изменения, ссылки на репозиторий, результаты и то, как всё это работает внутри FPGA.

Пока главный результат - BitNet 2B работает на старой плате за $50 и генерирует 17 токенов в секунду.

И это ещё не предел :)

Впереди новые эксперименты, разбор архитектуры openTPU, YOLO, VLA, Diffusion и попытки выжать из старого железа всё, на что оно способно. Некоторые уже удалось запустить на FPGA, но там ещё хватает проблем, которые нужно решить.

Если интересно, что из этого получится (КЕДР), подписывайтесь на мой блог на Хабре, чтобы не пропустить продолжение.

Может, соберёмся и выпустим собственную FPGA-плату для экспериментов со своим TPU и КУЧЕЙ памяти. А там, глядишь, и до своего ЧИПа КЕДР дойдём.

Дейл пока подождёт :)

Теги:
+10
Комментарии0

Монетизация Налогового кодекса и "цифровая крепость": куда уходит открытость гос-API?

В предыдущем посте https://habr.com/ru/posts/1079618/ был рассказ, как сделать бесплатную замену фирменному сервису 1С:Контрагент. Сразу после этого начали происходить события предсказанные заранее и карму кто-то обнуляет, поэтому, думаю, здесь мне тоже не долго осталось - читааают ...

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

Предыдущий пост получился слишком длинный и не "влез" в формат поста. Это его продолжение вторая и третья части.

В процессе работы с DaData меня накрыл один философский вопрос.

Парадокс осмотрительности

ФНС требует от бизнеса "должной осмотрительности" при выборе контрагентов. Вы обязаны проверить, существует ли фирма, не является ли она "однодневкой", не участвует ли в цепочках и т.д. Это требование закона (в трактовке ФНС). И тут возникает главный парадокс: данные ЕГРЮЛ и ЕГРИП по определению являются открытыми, но доступ к ним через API ФНС платный и, соответственно, требует авторизации.

Как так-то? Почему государственная структура "торгует" данными, которые сама же требует проверять по открытым источникам? Кто получает эту плату? Мы оказываемся в ситуации, когда нас фактически вынуждают покупать услуги у налоговой, чтобы соблюсти требования этой же налоговой. Что это - какая-то новая "монетизация Налогового кодекса"?

От открытого мира к цифровой крепости

Глядя на всё это, я вспоминаю, как было лет 10-15 тому назад. В те времена, напомню, фирма 1С пыталась сделать платную автоматическую загрузку курсов валют в типовых конфигурациях. С этой целью вместо использовавшегося сервиса РосБизнесКонсалтинга, был открыт аналогичный на сервере 1c.ru, но с логином/паролем от "диска 1С:ИТС" (платный сервис фирмы 1С Инженерно-Техническое Сопровождение - требуется для всех типовых конфигураций, кроме базовых, ~ от 1500-3000 / в месяц). Добавлена новая обработка, а старая, хотя и осталась в конфигурации, была удалена из всех меню и автозапусков, а для ее запуска нужно было пройти "квалификационный тест юзера" на опытность - лохи вообще думали, что ее удалили из конфигурации. По сути, одна прокладка была заменена другой, поскольку, ни РБК, ни Желтая фирма курсы валют не формируют - это прерогатива ЦБ РФ.

Каюсь, это моя разработка обломала тогда им этот кайф. Это была бесплатная разработка, которая брала данные напрямую по API сервера ЦБ РФ, минуя все прокладки. Описание API ЦБ РФ было открытым, подробным и доступным. Разработка даже получила функционал, которого не было в типовых конфигурациях - автоматический ввод в справочник новых валют со всеми кодами и названиями, диаграммы курсов за выбранный период и еще пару приколов для программистов:

Дело в том, что т.н. отчеты/обработки в 1С 7.7 могут иметь не только форму, но и таблицу прикрепленную к ней (там и рисовались диаграммы и другая полезная информация, кстати, а вы знаете почему 9 ноября назван Днём изобретателя в немецкоговорящих странах? - каждый хабровец обязан это знать имхо). "Задать" привязку таблицы к форме можно только на этапе конфигурирования - обработка может быть или с таблицей или без. Мне "удалось" штатным способом менять эту опцию в пользовательском режиме (в режиме Предприятие). И еще один трюк для разработчика: если добавить мою загрузку курсов в любую типовую конфигурацию, она заменит типовую загрузку, не меняя ни одного байта типовой конфигурации и новый релиз не может это отменить и вернуть платность.

скрин всех загрузок курсов валют, запущенных одновременно
скрин всех загрузок курсов валют, запущенных одновременно

Тогда государство (в лице ЦБ РФ) предоставляло инструменты для прозрачности и автоматизации. Сегодня всё изменилось.

Яркий пример - бывший ФСС. После поглощения ПФРом и превращения в СоцФонд (СФР), они полностью закрыли данные о формате электронных листов нетрудоспособности. Этот формат и описание шлюза ФСС всегда были в открытом доступе. Мало того что они помешались на многоуровневом шифровании при "диалоге" по API, так еще и засекретили сами протоколы. Мы перешли от концепции "Государство как сервис" к концепции "Государство как закрытая крепость".

Теги:
+4
Комментарии4

«Хабр Торт» на STM32H750

Купил на одном из маркетов платку STM32H750VBT6-0.96 Core Board от WeAct Studio. Контроллер довольно мощный, 480MHz, много всяких примочек, TFT дисплей 0.96. Интересно было какими минимальными усилиями хоть что‑то с ней сделать бесплатно, то есть на бесплатных аккаунтах ИИ.

С кубом от ST не хотелось связываться, там даже vpn не помогает вроде как, да и кода там больше, чем в Ардуино среде — для бесплатных аккаунтов ИИ это важно. Поспрашивал ИИ какую среду выбрать. Посоветовали, если именно для STM32H750, то расширение PlatformIO в VS Code в среде Arduino Framework подходит, поддержка комьюнити солидная. Устанавливаю Vs Code, PlatformIO, дальше похоже без vpn никак, — не вопрос, ну да ладно.

Спрашиваю первую попавшуюся элэлэмку, кажется чатжпт, сделай код platformio.ini и main.cpp, чтобы светодиод мигал на этой плате, подключенной к компьютеру через ST‑LINK V2. Очень простой код, эти два файла переношу в проект, клацаю на значке Build, потом Upload — светодиод мигает. Потом его же спрашиваю — А слабо Вольдемару в фонтан нырнуть? Сделай код, чтобы на дисплее текст отображался «Habr Tort!». Только не лазай где попало, а сразу на гитхабе под эту конкретную плату ищи инфу. Нашел. Код прилагается. Habr Tort!

platformio.ini

[env:weact_mini_h750vbtx]
platform = ststm32
board = weact_mini_h750vbtx
framework = arduino
upload_protocol = stlink
monitor_speed = 115200
lib_deps =
    adafruit/Adafruit GFX Library
    adafruit/Adafruit ST7735 and ST7789 Library

main.cpp

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>

// WeAct STM32H750VBT6 0.96" ST7735 TFT

#define TFT_SCLK PE12
#define TFT_MOSI PE14
#define TFT_CS   PE11
#define TFT_DC   PE13
#define TFT_RST  -1       // Display uses system reset
#define TFT_LED  PE10     // Backlight

// Software SPI
Adafruit_ST7735 tft(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

void setup()
{
    // Backlight ON
    // PE10 is active-low on this board
    pinMode(TFT_LED, OUTPUT);
    analogWrite(TFT_LED, 0);

    // Initialize the 80x160 ST7735 display
    tft.initR(INITR_MINI160x80_PLUGIN);

    // SPI speed
    tft.setSPISpeed(40000000);

    // Landscape
    tft.setRotation(1);

    // Clear screen
    tft.fillScreen(ST77XX_BLACK);

    // Display text
    tft.setCursor(20, 30);
    tft.setTextColor(ST77XX_WHITE);
    tft.setTextSize(2);
    tft.println("HABR TORT!");
}

void loop()
{
}
Теги:
Всего голосов 7: ↑3 и ↓4+1
Комментарии2

Открытый проект esp32-c3-adblock позволяет запустить блокировщик рекламы на плате ESP32-C3. Устройство берёт питание из USB-порта роутера, а к сети подключается по Wi-Fi. После прошивки и настройки нужно указать этот элемент как DNS-сервер, чтобы появилась возможность блокировать обращения к рекламным доменам за 10 мс. Внутри гаджета 400 КБ ОЗУ и 4 МБ флеш-памяти. Чтобы вместить список блокировок, разработчик хранит короткие цифровые отпечатки адресов, чтобы 537 тыс. доменов занимали менее 50 КБ.

Теги:
Всего голосов 4: ↑4 и ↓0+6
Комментарии3

В продолжение предыдущего поста.

Принёс продукт другу – тренеру фехтовального клуба – на обкатку и получил ответ: "Выглядит здорово, но мы на счёт не спаррингуем". Поэтому в списке приоритетов вверх поднялся турнирный режим.

В бэклоге-то он был сразу, но было непонятно, с какого боку вообще подходить: штука масштабная, новые сущности, доменная логика... не то, что сложная, но требует массы слов для описания. Но глаза боятся – агенты делают. В итоге справился за 3 вечера.

В первый – просто в режиме диалога разгонял с агентом бизнес-требования. Начал буквально с такого запроса:

Хочу турнирный режим: регистрация, проведение, итоги, с поддержкой таких-то турнирных режимов. Что тебе ещё надо знать – задавай вопросы?

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

Во второй – превращал бизнес-требования в ТЗ. Опять же, моё участие свелось к ответам на вопросы, и то, в основном для краевых случаев: основные сценарии были уже описаны.

Ну а в третий вечер я просто смотрел, как агент идёт по шагам ТЗ и делал проверку работоспособности после каждого большого этапа. Плюс небольшой UI тюнинг в конце, уже поверх готовой функциональности.

Понесу теперь по клубам уже с новой функциональностью) А чтобы не разъяснять каждый раз, что там и как, собрал ещё и страничку с инструкцией и скринами: https://fencing-scorer.konbo.me/help.html

Теги:
Всего голосов 2: ↑1 и ↓1+2
Комментарии0

pear-crypt: клиентское шифрование

pear-crypt — небольшая TypeScript-библиотека, которая шифрует на клиенте и больше ничего не делает. На входе — пароль, PIN или Recovery Code, на выходе — ciphertext, который можно положить хоть в S3, хоть в Postgres. Пароль в этот blob не зашит.

Лицензия MIT. Из зависимостей только hash-wasm: нативного Argon2id в браузере нет. AES-256-GCM и HKDF-SHA256 берутся из Web Crypto, без велосипедостроения.

Почему бы не собирать самому?

Типичный сценарий: сгенерить мастер-ключ, обернуть его паролем, тем же ключом зашифровать файл и отдельно мету. Если каждый раз клеить это из crypto.subtle, через год уже не вспомнить, был ли AAD, какой длины nonce и куда делась salt.

Здесь wire-format зашит в спеке и в тестовых векторах. Поменять раскладку байтов «чуть-чуть» нельзя: старый ciphertext просто перестанет открываться.

Под капотом

Мастер-ключ — 32 случайных байта. В открытом виде наружу не светится: только внутри AES-GCM-обёртки. Ключ обёртки получается из секрета через Argon2id: 32 МиБ памяти, два прохода, без раскладки на несколько ядер. Параметры KDF лежат в JSON рядом с nonce и ciphertext, чтобы было видно, чем именно заворачивали.

Дальше HKDF с пустой солью режет мастер-ключ на домены. В info зашито, для чего ключ: файл или метаданные. Строка вида pear-keep-file:{uid} — это и есть domain separation. Файл и его имя одним ключом не вскрываются: это разные info.

Сам файл — кадр версия | nonce 12 байт | ciphertext и GCM-тег. AAD pear-keep-file:{uid}:{bindAt} привязывает blob к идентификатору и поколению содержимого. Подменили uid или bindAt — тег не сойдётся, расшифровки не будет.

Метаданные — тот же кадр, другой ключ и JSON внутри: подпись, комментарий, время, etc. Recovery Code — 25 символов из алфавита без сомнительных похожих, группами по пять. Им заворачивается тот же мастер-ключ, но отдельно от пароля: пароль забыл — ищи бумажку с кодом.

Как проверяется, что байты не разъехались

В репозитории лежат docs/crypto/SPEC.md и JSON с векторами. Тесты бьют не только в прямую «зашифровал и тут же расшифровал», но и в зафиксированный ciphertext. Покрытие держится выше 90%. Поменяли src/ — пересобрали векторы через npm run export:vectors и закоммитили вместе с кодом. Иначе спецификация и реализация тихо разъедутся.

Чего в комплекте нет

Библиотека не решает, куда класть ciphertext, как устроен логин и когда блокировать сессию. Длину PIN тоже не проверяет. И кофе не варит.

Ошибки — PearKeepCryptoError с машинным кодом: wrongPassword, cannotDecryptMetadata и дальше по списку. Человеческого текста ошибок нет и не будет. Как и i18n.

Итого

Обернуть мастер-ключ, зашифровать контент и мету и не таскать раскладку байтов в голове — вот и весь контракт. Спека, векторы и код смотрят в одну сторону: сдвинули кадр, тесты покраснеют раньше, чем это заметит пользователь. Куда класть готовый ciphertext и как пускать человека внутрь — уже забота приложения.

Теги:
Всего голосов 3: ↑3 и ↓0+5
Комментарии0

Неисповедимы пути ©
Как проектирование ЧПУ станков довело
до церковнославянского справочника.
И неясно, куда занесет ещё.

Церковнославянский справочник
Церковнославянский справочник

Я инженер. Работаю с достаточно сложными проектами в нефтянке
в роли СТО да проектного менеджера с упором на технические вопросы.
Всякое там ТОиР, стройка, проектирование, производство, КиП и тому подобное

Как частный личный проект с год назад с товарищами
задумали и начали делать 3–4 осевые ЧПУ станки небольших форматов.
Итогом добрались до церковнославянского сайта‑справочника и нейросеток.
Грабли банальные, если оглядываться назад и, видимо,
для многих «в теме» очевидные. Но мы по ним
оттоптались знатно. Думаю — будет еще много

Логика странная, но есть.
1. Для отработки конструкционных решений — нужно делать тесты.
Для наших ЧПУ — что‑то с большим количеством мелких элементов,
достаточно объемное и сложное. При этом недорогое и, чтоб не в мусор,
если получается что‑то приятное. Ибо обидно выкидывать.
Случайно наткнулись на православные иконы из дерева.
Подходит. Пробуем. Для отработки нюансов с ЧПУ оказалось шикарно.

2. Проект нежданно расширился в сторону производства икон. Ибо интересно.
Наловили кучу факапов и тонкостей с материалами, фрезами, химией.
Будучи агностиками по сути, реально получаем удовольствие. Факт.
Выяснилось, что тут свой большой объемный и непростой мир. Забавно.
Кардинально пересмотрели некоторые инженерные решения по станкам. Cool

3. Проект расширился в сторону 3D моделирования.
Выяснили, что 3D моделей хороших мало. При том количестве разного,
что «в интернетах есть» — реально качественного и достойного очень немного.
Есть свои тесные сообщества со своими правилами и ценами,
репутацией, рейтингами и «чужим входа нет».
Нейросетки не катят, как оказалось. Увы. «Все ручками».
Поэтому жесткая и очень ресурсная наработка опыта
работы с моделированием трехмерного разного.

4. Проект расширился снова, теперь в програминг для станков. Оказалось,
что есть глобальная разница в G‑code для станка по разному сделанного.
Одна и та‑же модель на одном железе дает кратно разные результаты.
Итогом курсы, обучение, тесты, бессонные ночи и в 2 раза меньше
машинного времени при сильно лучшем результате на той‑же «базе»
Ибо 28 часов работы станка на одно изделие, и 15 таки
существенная разница по всем понятиям.

5. И снова проект расширился. Теперь в сторону информационную.
При всей «банальности» иконы как объекта, нашлась уйма нюансов.
Оказалось, что все сильно непросто в части надписей, шрифтов,
расположений элементов и тому подобных «мелочей». И даже
в епархиях часто спорят и не знают, как «правильно» и «нужно».
Итогом — сайт‑справочник, с надписями, словарем, шрифтами,
написанием и кучей новых (для нас) знаний о старославянском.

6. И снова расширение. Потому что моделей уже сотни,
вариантов куча, программы разные, фото‑видео копятся.
Нужно это все каким‑то образом хранить, холить и лееять.
Да и показывать надо порой выбранные вещи, что уже сложно
в части оперативного поиска да выборки. Банальные каталоги
где‑то на облаке не рабочее решение. Увы.
И снова в помощь codex да grok, и снова
очередной проект, теперь хранилища.

Зачем пишу?
Поделиться очередной иллюстрацией того,
как жизнь порой разворачивается в странные
и забавные проекты, задачи, решения, контакты.
Как относительно простой проект вдруг превращается
превращается, превращается в шорты © в какую‑то экосистему,
и укапывание в неизвестные досель области знаний.





Теги:
Всего голосов 5: ↑5 и ↓0+6
Комментарии0

Открытый проект KeyForge3D позволяет преобразовать фотографию ключа в файл для 3D-печати. Приложение выделяет контур ключа, добавляет ему толщину и сохраняет результат в STL для дальнейшей печати. Система работает локально без нейросетей и подписок — внутри обычный OpenCV.

Теги:
Рейтинг0
Комментарии1

Школьница Светлана под руководством двух инженеров - меня и ее отца - освоила концепции трех технологий проектирования схем и теперь демонстрирует их на этом видео:

1. Сборка цифровых схем на макетной плате с микросхемами малой степени интеграции. Этот метод старинный, изобретен еще в 1968 году, но и сейчас годен для обучения школьников начиная с детсада (мы вчера видели как 6-летний понял функциональность логического элемента XOR). Светлана показывает на видео схему с ALU которую она собрала.

2. Синтез схем из кода на языке описания аппаратуры SystemVerilog с реализацией в микросхемах реконфигурируемой логики FPGA. Этот способ широко применяется для прототипирования, специальных приложений (например в космических ракетах SpaceX и Blue Origin) и обучения студентов (см. напр. курс MIT 6.111).

3. Синтез для микросхем ASIC. Этот способ применяется последние 35 лет для всех массовых устройств. Смартфон который вы держите в руках - это несколько ASIC-ов и окружающая их периферия.

Светлана будет присутствовать на Zoom-звонке на русской части лекций, которые будет читать наш коллега из Грузии Леваном Чагелишвили, где мы покажем плату TinyTapeout в действии. Вы можете подключиться по линку

https://bit.ly/yuri-panchul-zoom

Chip Designed in the Country of Georgia: ASIC design flow and prototyping on FPGA

Чип спроектированный в Грузии: разбор маршрута проектирования для ASIC и прототипирования на FPGA

Пятница 18 сентября, 8 am по Калифорнии, 19.00 по Тбилиси, 18.00 по Москве: лекция на английском.

Cуббота 19 сентября, 8 am по Калифорнии, 19.00 по Тбилиси, 18.00 по Москве: лекция на русском.

Воскресенье 20 сентября, 8 am по Калифорнии, 19.00 по Тбилиси, 18.00 по Москве: лекция на грузинском.

Ждем вас на лекции!

Теги:
Всего голосов 10: ↑10 и ↓0+13
Комментарии0

🤡 Новый фреймворк на NodeJS

Это не draft, а работающий код из прода. Посмотрите код сервиса, код http контроллера и код декларации

Шутки шутками, а существующие реализации DI на ноде либо перегружены, либо используют декораторы, для которых нет единого стандарта у старого и нового кода.

import { provide, inject } from "di-kit";

export class WalkerLogicPublicService {

  private readonly loggerService = inject<LoggerService>("loggerService");

  ...

}

...

provide("loggerService", () => new LoggerService());

Вот почему нельзя просто вот так? Никаких минусов нет, выносите типы в enum, создавайте изолированные пространства имен.

import { createActivator } from "di-kit";

export const { init, inject, provide } = createActivator("separate-scope");
Теги:
Всего голосов 6: ↑6 и ↓0+8
Комментарии0

Ближайшие события

В ошалевшую от безделья голову пришла шальная мысль — может ли современный уважающий себя в меру упитанный человек прожить на голом ядре Linux, coreutils, пачке элементарных консольных мастхэв и нескольких консольных же баловст для приятственного времяпрепровождения?

Пораскинув в хорошем смысле мозгами, сделал такую подборку:

  • Основа — linux, linux-firmware, grub, runit, coreutils, util-linux, kmod, shadow, kbd

  • Сеть — iproute2, dhcpcd, ca-certificates

  • Окружение — kmscon/fbterm, tmux, nerd-fonts, mc

  • Мастхэв: sudo, file, procps-ng, neovim, git, wget, openssh, openssl, gcc, make, glibc, tar, zstd, unzip, less, grep, sed, awk, findutils, man-db, man-pages

Если немножко додать жиру, то — yazi, neomutt, lynx/w3m, newsboat, alsa-lib, alsa-utils, mpv.

Наверняка чего-то упустил / чего-то захочется ещё. Но такова природа человека… Иначе до пятидесятого гнома мы бы не дошли.

Вот. На следующих выходных попробую себе устроить GUI-детокс и геморрой на свою соскучившуюся пятую точку (см. начало про безделье). Посмотрю, чего реально не хватает современному в меру упитанному человеку для жизни.

И распивая чаи со спиртом (опционально), буду читать здесь холивары о гноме и кедах 😁

Теги:
Всего голосов 5: ↑5 и ↓0+7
Комментарии11

Пост выходного дня посвящу не столько профессиональным делам, сколько хобби)

Я занимаюсь фехтованием (HEMA, рапира) - и перед соревнованиями мы проводим спарринги по всем правилам, с таймером и подсчётом очков. Ещё в прошлом году я решил упростить работу судьи, собрал в Lovable простое одноэкранное веб-приложение, и испытал его на ближайшей же тренировке.

Приложение показало себя отлично, но - оно было всё-таки слишком одноразовое. Посмотрев на записи в тетради тренера, я решил довести-таки его до ума, и на прошлой неделе собрал новую версию.

К счётчику очков/таймеру добавились:

  • ростер бойцов (уже на отдельном бэкенде);

  • хранение истории боёв;

  • статистика.

То есть вырос уже MVP для небольших клубов. И на этом я не останавливаюсь, планов ещё много)

Если меня вдруг читают фехтовальщики (а может и не только) - предлагаю оценить результат самостоятельно, поделиться с друзьями и накидать обратной связи (любая будет ценной!)

https://fencing-scorer.konbo.me 

Это по-прежнему веб-приложение, не требует установки. Но свёрстано сразу под телефоны, чтобы было всегда под рукой. Чтобы просто считать очки в спаррингах регистрация не требуется (она нужна только для истории и статистики) - можно просто нажать на "Быстрый бой" внизу.

Теги:
Всего голосов 3: ↑2 и ↓1+3
Комментарии0

Погонял llama.cpp на пяти NVIDIA CMP 90HX и сравнил layer split с tensor split.

Конфигурация:

  • 5 × NVIDIA CMP 90HX по 10 ГБ

  • суммарно llama.cpp видит 49 383 MiB VRAM

  • 4 карты подключены по PCIe x8

  • 1 карта подключена по PCIe x4

  • применен rejoin15

  • модель - Qwen3.8-27B-Heretic

  • квант - Q8_0

  • размер GGUF - 26.62 GiB

  • параметров - 26.90B

  • llama.cpp build e107984

  • распределение по GPU - 1/1/1/1/1

  • все слои загружены на GPU

  • KV cache - F16, тоже на GPU

  • Flash Attention - auto

С tensor split картина получилась довольно интересная.

На пустом контексте генерация выросла с 23.76 до 31.93 tok/s. Это примерно +34%.

На 32K контекста - с 22.15 до 31.06 tok/s, то есть уже около +40%.

Для чистой генерации tensor split реально быстрее.

Но есть обратная сторона - prompt processing просел очень сильно.

На пустом контексте:

  • Layer - 1992.67 tok/s

  • Tensor - 268.46 tok/s

На 32K:

  • Layer - 1457.97 tok/s

  • Tensor - 246.84 tok/s

То есть обработка входного контекста в tensor split получилась примерно в 6-7 раз медленнее.

На 64K tensor-тест дальше не пошел - модель выгрузилась из памяти. Причину пока отдельно не разбирал, поэтому данные для tensor на 64K, 96K и 128K не привожу.

Layer split при этом нормально прошел весь тест до 128K.

Скорость генерации по мере заполнения контекста:

  • 0K - 23.76 tok/s

  • 32K - 22.15 tok/s

  • 64K - 20.75 tok/s

  • 96K - 19.53 tok/s

  • 128K - 18.44 tok/s

То есть даже при 128K контекста dense-модель на 26.9B параметров в Q8 все еще работает со скоростью около 18.4 tok/s.

Prompt processing тоже падает постепенно, без резкого провала:

  • 0K - 1992.67 tok/s

  • 32K - 1457.97 tok/s

  • 64K - 1136.52 tok/s

  • 96K - 916.35 tok/s

  • 128K - 724.86 tok/s

Для обычного чата tensor split может быть интересен, если контекст короткий, а ответы длинные. Там прирост с 24 до 32 tok/s ощущается.

Но если чат уже большой и модель каждый раз должна перерабатывать много входных токенов, выгода быстро начинает пропадать из-за очень медленного prefill.

Для кодового агента вроде Hermes я бы оставил layer split.

Агент постоянно читает файлы, получает куски исходников, и добавляет все это в контекст. В таком режиме скорость обработки входа важнее, чем дополнительные 8 tok/s на генерации.

Плюс layer split у меня стабильно работает вплоть до 128K, а tensor пока отвалился уже при переходе к 64K.

Итог пока такой:

  • короткий чат и длинные ответы - tensor split может быть быстрее

  • длинный чат - уже спорно

  • кодовый агент и большие проекты - layer split выглядит намного практичнее

Сами CMP 90HX тоже порадовали. Qwen3.8-27B dense Q8 дает около 24 tok/s на пустом контексте и около 18.4 tok/s на 128K.

После того как выкрутил вентиляторы на 100%, самая горячая карта держится примерно на 65 градусах.

Теги:
Всего голосов 3: ↑2 и ↓1+4
Комментарии6

Наконец мой мессенджер прошёл тест в Google Play . За время тестирования он научился совершать звонки по udp. Это позволило по udp получать не только голос, но и пинок от сервера на проверку сообщений в реальном времени. Осталось придумать как без внешних сервисов, вроде FCM, не засыпать вместе с системой и не давать андроиду прибить процесс приложения, чтоб принять udp пендаль в любое время. Так как мессенджер ориентирован на пользователей роутеров Mikrotik, на роутер и была возложена такая задача. Не давать телефону спать :). В качестве энергетика будет выступать DHCP Lease. В приложении я подписываюсь на изменения параметров сети, и выполняю задачу в обычном executor.

private void registerNetworkCallback() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(@NonNull Network network) {
                    isNetworkActive.set(true);
                    if (userId > 0) {
                        tickUdp();
                        startDownloadNewMsg(true);
                    }
                    offlineHandler.removeCallbacks(resetStatusesRunnable);
                    Log.d(LOG_TAG, "Network: WiFi Connected. " + network);
                }

                @Override
                public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {
                    Log.d(LOG_TAG, "LINK CHANGED DNS=" + linkProperties.getDnsServers());
                    if (userId > 0 && isNetworkActive.get()) {
                        tickUdp();
                        startDownloadNewMsg(true);
                    }
                }

                @Override
                public void onLost(@NonNull Network network) {
                    isNetworkActive.set(false);
                    offlineHandler.postDelayed(resetStatusesRunnable, 15000);
                    Log.d(LOG_TAG, "Network lost. Scheduled offline reset in 15s...");
                }
            });
        }
    }

который тригерится в том числе и на изменение списка DNS серверов. В роутере я указываю время аренды DHCP для подключённых устройств 6 минут. Соответственно устройства будут обновлять аренду каждые 3 минуты. С таким же интервалом 3 минуты, скриптом меняем список DNS серверов для локальной сети.

:local netId [/ip dhcp-server network find address="192.168.88.0/24"];
:local currentDns [/ip dhcp-server network get $netId dns-server];
:if ($currentDns = "192.168.88.1,8.8.8.8") do={
    /ip dhcp-server network set $netId dns-server="192.168.88.1,8.8.4.4";
} else={
    /ip dhcp-server network set $netId dns-server="192.168.88.1,8.8.8.8";
}

Этих трёх минут вполне хватает чтоб не заснуть, и пингануть разочек сервер для прогрева udp порта.

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

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Собирайся, народ, кто в настолку играть идет. Как я делал прототип настольной игры на компьютере

Или: почему Яндекс Таблицы для меня стал игровым движком

Кратко об игре

«Война киборгов» — это настольная игра в стиле GTA и киберпанк для 2–6 игроков. Вы собираете своего персонажа по частям (руки, ноги, тело, голова), прокачиваете автомобиль и боевого питомца, используете 6 уникальных локаций (Арена, Автодром, Лаборатория, Оружейная, Логово, Свалка), сражаетесь на кубиках и пытаетесь первым вернуться на базу до того, как сработает электромагнитная бомба. Партия занимает 30–40 минут, правила объясняются за 5 минут.

Зачем нам Яндекс Таблицы

Мы уже 8 месяцев тестируем игру, отыграли больше 200 партий, отточили механики, сделали дизайн коробки. Но до печати тиража ещё нужно дойти, а играть хочется уже сейчас. Поэтому мы сделали цифровой прототип в Яндекс Таблицах. Да-да, в обычных таблицах.

Вот как это выглядит:

  • Карта игрового поля — разбита на клетки, по которым двигаются игроки.

  • Карточки персонажей — у каждого свой киборг со слотами для деталей.

  • Справочная таблица — чтобы не держать правила в голове.

  • Рубашки карт — отдельные картинки, которые лежат сверху и переворачиваются при взятии карты.

Всё почти как в настоящей настолке: вы видите поле, перемещаете фишки, бросаете виртуальный кубик, открываете карты. Никаких скучных цифр — только карта, персонажи и механики.

Что я хочу сделать

Я планирую:

  1. Провести тренировочные игры — чтобы желающие могли попробовать, освоиться и понять механику.

  2. Организовать турнир — когда все освоятся, устроим соревнование.

  3. Стримить все игры — каждый матч будет транслироваться, чтобы зрители тоже могли участвовать и следить за происходящим.

Что нужно от вас

Если вы хотите стать тестером или участником турнира:

  • Подпишитесь на наших ботов.

  • У вас должны быть наушники и микрофон — для общения и координации.

Как записаться

Для записи на игры я использую Telegram-бота и бота в MAX. Там вы сможете:

  • Выбрать удобное время для игры.

  • Увидеть расписание.

  • Получить уведомления о начале.

Все игры будут бесплатными — это возможность увидеть игру до релиза, повлиять на её финальную версию и просто интересно провести время.

Почему вам стоит участвовать

  • Вы увидите игру до релиза — одними из первых.

  • Сможете повлиять на финальную версию — ваши отзывы помогут сделать игру лучше.

  • Это просто интересно — посмотреть, как работает «GTA на столе» в цифре.

  • Это бесплатно — мы не берём деньги за участие.

Дальнейшие планы

После серии тренировочных игр мы:

  • Составим турнирные таблицы.

  • Определим расписание.

  • Проведём полноценный турнир с победителями и призами.

Все игры будут стримиться — так что даже если вы не участвуете, вы сможете смотреть и болеть за своих.


Telegram-бот — https://t.me/voina_kiborgov_bot
MAX-бот — https://max.ru/id332760632995_2_bot

Теги:
Всего голосов 4: ↑2 и ↓2+2
Комментарии0

Апгрейд контроллера Xbox 360 стиками с TMR датчиками

Энтузиаст оснастил контроллер Xbox 360, спроектированный больше двадцати лет назад, современными TMR (туннельными магниторезистивными) датчиками.

Для этого нужно только...

  • взять модули Ginfull для контроллера Xbox 360 с датчиками на эффекте Холла (датчики выкинуть);

  • взять TMR датчики для использования с механизмом ALPS, например, от той же Ginfull;

  • прифранкенштейнить TMR датчики к механизму;

  • ???

  • Profit

Теги:
Всего голосов 3: ↑2 и ↓1+4
Комментарии0

Разведка боем: Скрытая карта режимов 8BitDo Zero v1 и прошивка по воздуху через Linux

Короткая заметка для тех, кто ковыряет ретро-железо. Стояла задача: использовать микро-геймпад 8BitDo Zero 1-го поколения (Bluetooth 2.1) для специфического HID-ввода, изменив раскладку “намертво” внутри устройства.

Официальный софт под Windows давно заброшен, поэтому ремап делался по воздуху через Linux (RFCOMM). В процессе удалось полностью разобрать структуру конфигурационного пакета, отправляемого контроллеру.

Структура KEYMAP-пакета

При отправке команды +KEYMAP; геймпад принимает массив, где блоки идут друг за другом в зависимости от режима удержания кнопок при включении (по 12 байт на режим в аппаратном порядке: Вверх/Вниз/Влево/Вправо/Select/Start/B/A/X/Y/L/R):

  1. START — Режим стандартного джойстика (Usage Page 0x09)

  2. R + START — Режим PC-джойстика

  3. START + B — Стандартная клавиатура (Usage Page 0x07), выдает стрелки (52 51 50 4f) и Enter/Esc (28/29).

  4. START + B + R — Расширенная клавиатура.

  5. START + A — Режим iCade (раздельные HEX-коды на Press и Release).

  6. START + X — Скрытый сервисный/Emu-Touch режим прошивки (0F 0E 0D 0C...).

  7. Shutter (Селфи-пульт) — Комбинированный режим. Позволяет сочетать стандартные кнопки клавиатуры (Page 0x07) и мультимедиа-коды Consumer Page 0x0C (Громкость: 80/81, Яркость: 6F/70, Снимок: 65).

Как шить (Пайплайн в 3 окна)

  1. В первом окне терминала поднимаем RFCOMM-канал на 1-м L2CAP канале геймпада: sudo rfcomm connect 0 [MAC_АДРЕС] 1

  2. Во втором окне правим HEX-массив и инжектируем его Python-скриптом напрямую в /dev/rfcomm0 (скрипт прикреплен ниже). Контроллер должен вернуть успешную сигнатуру 0e0100a6.

  3. В третьем окне контролируем прохождение пакетов через sudo btmon.

В конце пакета обязательно должны идти маркеры валидации aa 55 aa 55, иначе чип отвергнет прошивку. Мне удалось успешно собрать кастомный Shutter-режим, внедрив туда нужные клавиатурные скан-коды (30 и 40) рядом с системными. Код скрипта прилагаю.

import serial
import time

# Настройки порта
PORT = '/dev/rfcomm0'

# Ваши данные для записи (с 07 07 07 07)
DATA = b'\x00\xa6WR+KEYMAP;\x00\x00\x64\x00\x00\x00\x00\x00\x1a\x1b\x11\x10\x13\x14\x16\x17\x01\x01\x01\x01\x1a\x1b\x11\x10\x13\x14\x16\x17\x52\x51\x50\x4f\x28\x29\x4d\x4e\x4a\x4b\x0e\x10\x13\x14\x15\x04\x1b\x1c\x18\x05\x16\x17\x19\x1a\x1a\x1b\x04\x07\x0f\x12\x0b\x18\x0d\x1c\x0e\x0c\x08\x1d\x14\x06\x19\x0a\x15\x09\x11\x17\x13\x10\x0f\x0e\x0d\x0c\x09\x00\x08\x07\x05\x06\x04\x03\x52\x51\x50\x4f\x28\x29\x4d\x4e\x4a\x4b\xea\xe9\xaa\x55\xaa\x55'

try:
    print(f"--- Попытка открыть {PORT} ---")
    # Открываем порт с таймаутом 2 секунды
    with serial.Serial(PORT, baudrate=115200, timeout=2) as ser:
        print("Порт открыт. Отправка данных...")
        ser.write(DATA)
        ser.flush()  # Гарантируем отправку всех байт
        
        print("Данные отправлены. Ждем подтверждения от геймпада...")
        response = ser.read(16) # Читаем ответ
        
        if response:
            print(f"ОТВЕТ ПОЛУЧЕН (HEX): {response.hex()}")
            if "0e0100a6" in response.hex():
                print("УСПЕХ: Геймпад подтвердил запись ремапа!")
            else:
                print("ВНИМАНИЕ: Ответ получен, но он не похож на стандартное подтверждение.")
        else:
            print("ОШИБКА: Геймпад ничего не ответил (таймаут).")

except Exception as e:
    print(f"КРИТИЧЕСКАЯ ОШИБКА: {e}")
Теги:
Всего голосов 4: ↑4 и ↓0+6
Комментарии0
1
23 ...