Блог
[измерено на FPGA: слой 0, проверено 403 200 из 403 200 квитанций, зарегистрировано до запуска; шаг phi и сборка разрядов — арифметика хоста; один синтетический вектор активаций] Веса GFTernary из статьи о TNF, t*phi, применённые к активациям из Z[phi], отработали на неизменённом узле AX7203 без умножителя. Каждый выход равен W.b + (W.a + W.b)*phi, так что узел считает только тернарные скалярные произведения, а хост делает одно сложение на выход. Все 5 632 строки Z[phi] слоя 0 совпали бит в бит с оракулом обычного умножения в Z[phi].
Формат весов из статьи о TNF — GFTernary: вес равен t*phi, где t из {-1, 0, +1}. Активации живут в Z[phi], это числа a + b*phi с целыми a и b. Статья утверждает, что линейный путь слоя точен в Z[phi] и не требует умножителя. Узел на AX7203 из прошлого поста считает знаковые тернарные скалярные произведения на 32 трита и подписывает каждый ответ. Мы проверили, может ли этот узел без изменений точно посчитать слой GFTernary на активациях из Z[phi].
Поскольку phi^2 = phi + 1, применение веса — это шаг Фибоначчи: t*phi*(a + b*phi) = t*(b + (a + b)*phi). В сумме по строке один выход равен W.b + (W.a + W.b)*phi. W.a и W.b — скалярные произведения тернарных весов на целые. При a и b в диапазоне [-127, 127] каждое раскладывается на шесть сбалансированно-троичных разрядов, это 12 задач узла на кусок шириной 32. Сам phi стоит одно целочисленное сложение на выход, на хосте.
Это та же мысль, что в посте «Золотое сечение в этом формате — масштаб, а не информация», только теперь измеренная на кремнии. В весах phi — фиксированное линейное отображение на Z[phi], а не произведение, которое должно вычислять железо. Работа узла в этом прогоне ровно того же рода, что и для tern_tc: тернарные скалярные произведения, и ничего больше.
Команда, входные данные, ожидаемые числа и правила были закоммичены в 03:32:06 UTC, а прогон начался в 03:32:44. На вход пошёл слой 0 обученной модели tern_tc: все 7 тернарных матриц, 2 816 выходов, один вектор активаций из Z[phi] из фиксированного seed, 24 задачи в полёте. Правила: прогон делается один раз, и его результат записывается, каким бы он ни был. Сбой UART засчитывался бы каналу, а не утверждению о Z[phi], и всё равно записывался бы как провал.
| Зарегистрировано | Плата | |
|---|---|---|
| Задач | 403 200 | отправлено 403 200 из 403 200 |
| Квитанций проверено | 403 200 / 403 200 | 403 200 / 403 200 |
| Строк Z[phi] бит-точно | 5 632 / 5 632 | 5 632 / 5 632 |
| Отвергнуто | ничего | ничего |
| Время | около 86 с | 85,35 с, 4 724 ответа/с |
Каждый ответ прошёл те же пять проверок, что в прогоне tern_tc: статус, nonce, id узла, тег SipHash, пересчитанный под ключом, и y. Оракул — обычное умножение в Z[phi], (a, b)(c, d) = (ac + bd, ad + bc + bd), применённое к каждой паре веса и активации и просуммированное. Он не использует ни шаг Фибоначчи, ни разложение на разряды. Каждый выход проверяется как две строки: рациональная часть и часть при phi минус рациональная. Обе бит-точны ровно тогда, когда выход, собранный из ответов платы, равен оракулу в Z[phi].
До прогона на плате самопроверка показала, что каждая проверка умеет падать:
| Намеренная ошибка | Результат |
|---|---|
| оракул с phi^2 = 1 | 12 / 24 строк: все строки при phi падают |
| веса прочитаны как t вместо t*phi | 0 / 24 строк |
| хост теряет разряд 3^0 | 0 / 24 строк |
| неверный ответ с корректной подписью | отвергнуто как 'lie' |
| ячейка подписывает чужим ключом | 0 квитанций |
Собственный Verilog узла без изменений тоже прогнал в симуляции поток запросов того же вида, с синтетическими весами для одной матрицы: 7 680 из 7 680 квитанций и 128 из 128 строк.
Поработаем вместе
Я аудирую RTL и строю независимые побитово точные модели, затем провожу результат через синтез и, когда это полезно, проверяю на плате Artix-7. Первый модуль проверки — бесплатно.