docs(diarization): расширен отчет Ryzen-эксперимента
Зачем: - Сохранить полный ход проверки гипотез и исключить ненужный повтор старой матрицы. Что: - Добавлен ledger этапов W/M/Q/E/C с рецептами, числами и причинами отсева. - Зафиксированы правила переиспользования результатов и границы повторных прогонов. - Связана следующая end-to-end карта в задаче #45. Проверка: - uv run --no-sync pytest -q (389 passed, 2 skipped). - Codex taste-review и ai-text-lint: APPROVED.
This commit is contained in:
1 parent
38c99855e2
commit
249b970cc9
1 file changed
+171
-19
@@ -9,23 +9,23 @@ Production-профиль не менялся.
|
|||||||
|
|
||||||
На AMD Ryzen 7 8845H выполнен этап 5 эксперимента из
|
На AMD Ryzen 7 8845H выполнен этап 5 эксперимента из
|
||||||
[спецификации](../specs/2026-08-30-cpu-diarization-experiment.md) по единственному
|
[спецификации](../specs/2026-08-30-cpu-diarization-experiment.md) по единственному
|
||||||
кандидату C2 из [Intel-этапа](2026-08-31-cpu-diarization-intel.md). Этап 6
|
кандидату C2 из [Intel-этапа](2026-08-31-cpu-diarization-intel.md). Этап 6 не
|
||||||
остановлен до полных прогонов: победителя нет. C2 сохраняет baseline-рецепт
|
запускали: победителя нет. C2 сохраняет `window_shift_ratio=0.1`, Pyannote
|
||||||
диаризации, но выполняет embedding-вызовы через два outer
|
Segmentation 3.0 FP32, WeSpeaker ResNet34 LM FP32 и `FastClustering(0.89)`.
|
||||||
worker и одну общую ONNX Runtime session с общим intra-op пулом из восьми
|
Embedding-вызовы выполняют два outer worker через одну общую ONNX Runtime
|
||||||
потоков; `inter_op_threads=1`.
|
session с общим пулом из восьми intra-op потоков; `inter_op_threads=1`.
|
||||||
|
|
||||||
Изолированный A/B механизма shared-session дал ускорение 24,05%. Первичный A/B
|
Изолированный A/B механизма shared-session дал ускорение 24,05%. Первичный A/B
|
||||||
C2 показал 22,90%, поэтому кандидат прошел порог продолжения 10%, и для него
|
C2 показал 22,90%, поэтому кандидат прошел порог продолжения 10%, и для него
|
||||||
запустили пять чередующихся циклов. Они дали медиану 23,57% при MAD 0,62
|
запустили пять чередующихся циклов. Они дали медиану 23,57% при MAD 0,62
|
||||||
процентного пункта, то есть ниже итогового порога 30%; по одному Ryzen-кандидату
|
процентного пункта, то есть ниже итогового порога 30%; по одному Ryzen-кандидату
|
||||||
C2 итог был бы `stop`.
|
C2 итог был бы `stop`.
|
||||||
Полная воронка, однако, соответствует отдельному исходу `new map`: все шаги
|
|
||||||
окна W1-W4 потеряли кластер, а C1 с CAMPPlus + NME ускорилась на Intel на 33,65%,
|
Вся воронка дала `new map`. W1-W4 потеряли обязательное число кластеров. C1 с
|
||||||
но добавила 2 слова без говорящего и осталась без требуемой слуховой проверки.
|
CAMPPlus + NME ускорила Intel-прогон на 33,65%, но оставила два дополнительных
|
||||||
C1 на Ryzen не передавали, победителем она не считается; возвращать ее в матрицу
|
слова без говорящего; требуемую слуховую проверку не проводили и автоматической
|
||||||
без подготовленной приватной слуховой проверки нельзя, и автоматической оценкой
|
оценкой не подменяли. Поэтому C1 не передавали на Ryzen и не считаем победителем.
|
||||||
эта проверка не подменялась.
|
Вернуть ее в матрицу можно только после приватной слуховой проверки.
|
||||||
|
|
||||||
Все принятые ячейки прошли обязательное качество: `3 / 2 / 2` кластера,
|
Все принятые ячейки прошли обязательное качество: `3 / 2 / 2` кластера,
|
||||||
неизменный текст, `51 / 13 / 9` слов без говорящего, те же значения
|
неизменный текст, `51 / 13 / 9` слов без говорящего, те же значения
|
||||||
@@ -34,8 +34,120 @@ C1 на Ryzen не передавали, победителем она не сч
|
|||||||
Пиковый RSS C2 оставался в диапазоне 410,3-418,1 МиБ; OOM, активности swap и
|
Пиковый RSS C2 оставался в диапазоне 410,3-418,1 МиБ; OOM, активности swap и
|
||||||
линейного роста памяти не наблюдалось.
|
линейного роста памяти не наблюдалось.
|
||||||
|
|
||||||
Полные записи и пятикатегорийная слуховая приемка по правилам этапа 6 не
|
Полные записи и слуховая приемка по пяти категориям на этапе 6 не запускались.
|
||||||
запускались.
|
|
||||||
|
## Что именно проверяли
|
||||||
|
|
||||||
|
Отчет охватывает всю воронку: этапы 0-4 на Intel и этап 5 на Ryzen. На Intel
|
||||||
|
проверили шаг окна, модели эмбеддингов, счетчик говорящих, квантизацию, способы
|
||||||
|
параллельного исполнения и две комбинации. Таблицы ниже собирают этот путь в
|
||||||
|
одном месте. Подробные хеши и исходные идентификаторы ячеек остаются в
|
||||||
|
[Intel-отчете](2026-08-31-cpu-diarization-intel.md).
|
||||||
|
|
||||||
|
Intel-ячейки W/M/E/C были разведочными одиночными прогонами трех пятиминутных
|
||||||
|
фрагментов. Они показывают направление и причину отсева, но не дисперсию.
|
||||||
|
Исключение - соседняя пара W0/C2 под runtime guard. На Ryzen сначала выполнялась
|
||||||
|
одна диагностическая пара, затем первичная пара C2 и только после прохождения
|
||||||
|
порога - пять чередующихся циклов.
|
||||||
|
|
||||||
|
### Этап 0: пригодность механизмов
|
||||||
|
|
||||||
|
До дорогих CPU-ячеек проверили, что экспериментальный стенд вообще измеряет
|
||||||
|
задуманные механизмы, не теряя строки и не меняя пользовательский результат.
|
||||||
|
|
||||||
|
| Гипотеза | Что проверяли | Что получилось | Решение |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `Prepare/Finalize` | Подготовка один раз, кластеризация копии матрицы и финализация | Результат совпал со штатным `process()`; пропусков и дублей строк нет | Использовать в стенде |
|
||||||
|
| Счетчик eigengap | CAMPPlus и TitaNet на матрицах `531 / 414 / 440` строк | CAMPPlus дал `6 / 1 / 7`, TitaNet - `7 / 2 / 4` вместо `3 / 2 / 2` | Исключить |
|
||||||
|
| Счетчик NME | Те же шесть матриц без повторного embedding-инференса | Обе модели дали `3 / 2 / 2`; метки повторяемы, потерянных строк нет | Использовать для M2 и M3 |
|
||||||
|
| WeSpeaker S8S8 QDQ | Схема, opset, метаданные, динамические длины и загрузка через sherpa-onnx | Граф технически корректен; качество и скорость проверены отдельно в Q1 | Допустить к CPU-ячейке |
|
||||||
|
| Shared-session worker | Один и два worker на одном наборе prepared-входов | Строки, метки и интервалы совпали; гонок и нечисловых значений нет | Допустить E1/E2 |
|
||||||
|
|
||||||
|
Задача этапа 0 - подтвердить, что последующие CPU-ячейки сравнивают одинаковые
|
||||||
|
вычисления и используют исправный экспериментальный API. Скорость измеряли на
|
||||||
|
следующих этапах.
|
||||||
|
|
||||||
|
### Этап 1: можно ли считать меньше окон
|
||||||
|
|
||||||
|
Гипотеза: увеличить `window_shift_ratio`, сократить число segmentation-окон и
|
||||||
|
вместе с ними число embedding-заданий. Все варианты использовали Pyannote
|
||||||
|
Segmentation 3.0 FP32, WeSpeaker FP32 и текущий `FastClustering(0.89)`.
|
||||||
|
|
||||||
|
| Ячейка | Шаг | Окна по трем фрагментам | Embedding-задания | Время, с | Кластеры | Решение |
|
||||||
|
|---|---:|---|---|---:|---|---|
|
||||||
|
| W0 | 0,10 | `291 / 291 / 291` | `531 / 414 / 440` | 148,220 | `3 / 2 / 2` | baseline |
|
||||||
|
| W1 | 0,15 | `195 / 195 / 195` | `357 / 274 / 302` | 100,799 | `2 / 2 / 2` | исключена: потерян кластер |
|
||||||
|
| W2 | 0,20 | `146 / 146 / 146` | `264 / 206 / 222` | 76,127 | `2 / 2 / 2` | исключена: потерян кластер |
|
||||||
|
| W3 | 0,25 | `117 / 117 / 117` | `211 / 165 / 175` | 61,369 | `2 / 2 / 2` | исключена: потерян кластер |
|
||||||
|
| W4 | 0,50 | `59 / 59 / 59` | `105 / 82 / 89` | 31,291 | `1 / 2 / 2` | исключена: потеряны два кластера |
|
||||||
|
|
||||||
|
Скорость росла именно вместе с сокращением работы, но даже осторожный W1
|
||||||
|
нарушил обязательное качество на первой записи. Рабочим остался шаг `0.1`.
|
||||||
|
Комбинация C0 совпала бы с baseline, поэтому ее не запускали.
|
||||||
|
|
||||||
|
### Этап 2: можно ли удешевить модель эмбеддингов
|
||||||
|
|
||||||
|
Гипотеза: сохранить полный набор окон, но заменить WeSpeaker и при необходимости
|
||||||
|
счетчик говорящих. В M2 и M3 сохраняли `window_shift_ratio=0.1`, Pyannote
|
||||||
|
Segmentation 3.0 FP32 и последовательный инференс. Менялись модель эмбеддингов и
|
||||||
|
счетчик говорящих. Проценты ниже посчитаны относительно W0 148,220 с.
|
||||||
|
|
||||||
|
| Ячейка | Рецепт | Время, с | Изменение | RSS, МиБ | Кластеры | Решение |
|
||||||
|
|---|---|---:|---:|---:|---|---|
|
||||||
|
| W0 (рецепт M0) | WeSpeaker FP32 + `FastClustering(0.89)` | 148,220 | baseline | 362,6 | `3 / 2 / 2` | точка сравнения |
|
||||||
|
| M2 | CAMPPlus + NME + `FastClustering(N)` | 94,550 | -36,21% | 358,6 | `3 / 2 / 2` | самый быстрый, собрать C1 |
|
||||||
|
| M3 | TitaNet small + NME + `FastClustering(N)` | 107,205 | -27,67% | 511,9 | `3 / 2 / 2` | прошла, но медленнее и тяжелее M2 |
|
||||||
|
|
||||||
|
M2 и M3 прошли обязательное число кластеров. Окончательная диагностика M2
|
||||||
|
появилась в C1: purity выросла, но число слов без говорящего на первой записи
|
||||||
|
изменилось с 51 до 53. По спецификации это требует прослушивания отмеченных мест.
|
||||||
|
|
||||||
|
### Этап 3: квантизация и исполнение эмбеддингов
|
||||||
|
|
||||||
|
Для QDQ проверяли, даст ли INT8 выигрыш старому Intel без VNNI. Q1 и E1-E3
|
||||||
|
сохраняли `window_shift_ratio=0.1`, Pyannote Segmentation 3.0 FP32 и текущий
|
||||||
|
`FastClustering(0.89)`. Q1 меняла модель WeSpeaker, E1-E3 - только топологию
|
||||||
|
исполнения FP32-модели. Во всех вариантах `inter_op_threads=1`; E1-E3 использовали
|
||||||
|
общий бюджет четырех физических ядер.
|
||||||
|
|
||||||
|
| Ячейка | Рецепт | Время, с | Изменение к W0 | RSS, МиБ | Кластеры | Решение |
|
||||||
|
|---|---|---:|---:|---:|---|---|
|
||||||
|
| Q1 | WeSpeaker S8S8 QDQ, sequential | 177,537 | +19,78% | 367,7 | `2 / 2 / 2` | исключена: медленнее и потерян кластер |
|
||||||
|
| E1 | 2 outer worker, одна session, общий pool 4 | 139,219 | -6,07% | 398,6 | `3 / 2 / 2` | передать как аппаратный кандидат |
|
||||||
|
| E2 | 4 outer worker, одна session, `intra_op=1` | 152,167 | +2,66% | 551,2 | `3 / 2 / 2` | исключена по времени и памяти |
|
||||||
|
| E3 | 4 отдельные session, `intra_op=1` | 159,038 | +7,30% | 732,3 | `3 / 2 / 2` | отрицательный контроль подтвердился |
|
||||||
|
|
||||||
|
E3 измерялась составным интервалом на заранее подготовленных заданиях, поэтому
|
||||||
|
ее wall time нельзя сравнивать с `process()` так же строго, как E1/E2. Для
|
||||||
|
решения хватило отрицательного результата одновременно по времени и памяти.
|
||||||
|
|
||||||
|
TitaNet batch проверили отдельно на тех же трех матрицах:
|
||||||
|
|
||||||
|
| Контроль | Строк | Batch 1, с | Batch 4, с | Число кластеров | Метки строк совпали |
|
||||||
|
|---:|---:|---:|---:|---:|:---:|
|
||||||
|
| 1 | 531 | 27,175 | 37,588 | 3 | нет |
|
||||||
|
| 2 | 414 | 25,871 | 32,443 | 2 | нет |
|
||||||
|
| 3 | 440 | 22,877 | 28,565 | 2 | нет |
|
||||||
|
|
||||||
|
Batch 4 сохранил число кластеров, но оказался медленнее batch 1, поменял метки
|
||||||
|
строк на всех трех матрицах и дал максимальный дрейф эмбеддингов `0,277-0,317`.
|
||||||
|
Ветвь остановили до отдельной CPU-ячейки. SHA-256 закрытого batch-result:
|
||||||
|
`f12bfdb5cadf80c62871c0725eac744a99825cb5d06b70fcf11e4e538ff6df72`.
|
||||||
|
|
||||||
|
### Этап 4: комбинации перед Ryzen
|
||||||
|
|
||||||
|
Полного декартова перебора не было. C0 совпала с baseline; из оставшихся
|
||||||
|
собрали самый быстрый модельный вариант C1 и переносимый аппаратный вариант C2.
|
||||||
|
|
||||||
|
| Комбинация | Точный рецепт | Время, с | Ускорение | RSS, МиБ | Диагностика | Решение |
|
||||||
|
|---|---|---:|---:|---:|---|---|
|
||||||
|
| C1 | `0.1` + Pyannote Segmentation 3.0 FP32 + CAMPPlus + NME + `FastClustering(N)` + sequential | 98,347 | 33,65% | 399,5 | `3 / 2 / 2`; purity выше; `+2` слова без говорящего | не передавать без слуховой проверки |
|
||||||
|
| C2 | `0.1` + Pyannote Segmentation 3.0 FP32 + WeSpeaker ResNet34 LM FP32 + `FastClustering(0.89)` + 2 outer worker + 1 shared session + pool 4 | 140,632 | 4,32% | 406,0 | точное совпадение с соседним W0 | передать на Ryzen |
|
||||||
|
|
||||||
|
У C1 процент считается от разведочного W0 148,220 с. У C2 был соседний W0
|
||||||
|
146,978 с под тем же runtime guard. C2 не достигла Intel-порога продолжения,
|
||||||
|
но shared-session заранее считалась аппаратной гипотезой: Ryzen имеет восемь
|
||||||
|
физических ядер и другой ISA, поэтому спецификация требовала отдельный A/B.
|
||||||
|
|
||||||
## Handoff и воспроизводимость
|
## Handoff и воспроизводимость
|
||||||
|
|
||||||
@@ -53,10 +165,10 @@ C1 на Ryzen не передавали, победителем она не сч
|
|||||||
| SHA-256 Ryzen-wheel | `baaaa2532606f1e1411e5c84655afa70107ad4b1676420953f5e67233c46a484` |
|
| SHA-256 Ryzen-wheel | `baaaa2532606f1e1411e5c84655afa70107ad4b1676420953f5e67233c46a484` |
|
||||||
|
|
||||||
Входная Intel-капсула прошла полную проверку: schema v3, 199 файлов,
|
Входная Intel-капсула прошла полную проверку: schema v3, 199 файлов,
|
||||||
QDQ-артефакт доступен, предупреждений нет. Ryzen-manifest без изменений закрепил
|
QDQ-артефакт доступен, предупреждений нет. Ryzen-manifest без изменений
|
||||||
из Intel-капсулы handoff, артефакты, контрольные записи, calibration, QDQ, патч,
|
зафиксировал данные Intel-капсулы: handoff, артефакты, контрольные записи,
|
||||||
версии runtime и интервал RSS. Baseline и candidate каждой запускаемой
|
calibration, QDQ, патч, версии runtime и интервал RSS. Рецепты baseline и
|
||||||
combination-пары совпали с переносимыми Intel-рецептами.
|
кандидата во всех запущенных парах совпали с переносимыми Intel-рецептами.
|
||||||
|
|
||||||
Ryzen-manifest, сырые результаты, рабочие артефакты стенда, guard-свидетельства
|
Ryzen-manifest, сырые результаты, рабочие артефакты стенда, guard-свидетельства
|
||||||
и журналы сохранены в закрытой папке Яндекс Диска. Чтобы восстановить
|
и журналы сохранены в закрытой папке Яндекс Диска. Чтобы восстановить
|
||||||
@@ -94,7 +206,7 @@ Ryzen-manifest отдельно связывается с handoff и входа
|
|||||||
температурный датчик или аппаратные лимиты мощности. Температура
|
температурный датчик или аппаратные лимиты мощности. Температура
|
||||||
записана как недоступная; это ограничивает тепловой guard;
|
записана как недоступная; это ограничивает тепловой guard;
|
||||||
- нативные WSL-интерфейсы не отдали supply, platform profile и throttle count,
|
- нативные WSL-интерфейсы не отдали supply, platform profile и throttle count,
|
||||||
поэтому для принятых ячеек стенд взял override
|
поэтому для принятых ячеек использовали override
|
||||||
`LOCAL_TRANSCRIBER_RUNTIME_GUARD_JSON`, заполненный проверенными Windows-фактами:
|
`LOCAL_TRANSCRIBER_RUNTIME_GUARD_JSON`, заполненный проверенными Windows-фактами:
|
||||||
AC, `balanced`, turbo, power policy, нулевая подкачка, отсутствие throttling.
|
AC, `balanced`, turbo, power policy, нулевая подкачка, отсутствие throttling.
|
||||||
До и после принятых пар Windows-проверка подтверждала AC, неизменный `balanced`
|
До и после принятых пар Windows-проверка подтверждала AC, неизменный `balanced`
|
||||||
@@ -134,6 +246,44 @@ E1 и C2 сохранили все обязательные и диагност
|
|||||||
медиана недобрала 6,43 процентного пункта. На Intel тот же механизм давал только
|
медиана недобрала 6,43 процентного пункта. На Intel тот же механизм давал только
|
||||||
4,32%; Ryzen ускоряет shared-session заметнее, но недостаточно для `go`.
|
4,32%; Ryzen ускоряет shared-session заметнее, но недостаточно для `go`.
|
||||||
|
|
||||||
|
## Что уже не нужно прогонять заново
|
||||||
|
|
||||||
|
Полный replay этапов 0-5 для следующей гипотезы не нужен. Результаты закреплены
|
||||||
|
публичными агрегатами, хешами и закрытой капсулой.
|
||||||
|
|
||||||
|
| Результат | Что можно переиспользовать | Когда повтор действительно нужен |
|
||||||
|
|---|---|---|
|
||||||
|
| W1-W4 | На текущей Pyannote-модели увеличение шага теряет кластер раньше порога скорости | Изменилась segmentation-модель, логика сборки окон или обязательный quality gate |
|
||||||
|
| M2/M3 | CAMPPlus и TitaNet с NME сохраняют `3 / 2 / 2`; M2 быстрее и экономнее | Изменилась модель, счетчик, clustering или контрольные входы |
|
||||||
|
| Q1 | Этот S8S8 QDQ-граф на Intel медленнее FP32 и дает `2 / 2 / 2` | Новая калибровка, формат квантизации, модель или runtime |
|
||||||
|
| E2/E3 | Больше worker и отдельные session не окупились при прежнем бюджете потоков | Изменилась топология session, runtime или бюджет ядер |
|
||||||
|
| E1/C2 на Ryzen | Для точного рецепта shared-session медиана равна 23,57%, качество и память проходят | Изменилась реализация механизма, runtime, машина или режим питания |
|
||||||
|
| C1 | Замер скорости уже есть; открыт только диагностический слуховой gate | Сначала прослушать подготовленные места; новый CPU-замер нужен лишь после положительного решения |
|
||||||
|
|
||||||
|
Есть три разных вида проверки, и они не заменяют друг друга:
|
||||||
|
|
||||||
|
1. `--validate-only` сверяет commit, схему, хеши, handoff и план. Модели он не
|
||||||
|
запускает.
|
||||||
|
2. `uv run pytest` проверяет код стенда на mock-данных. Полный Python-suite перед
|
||||||
|
PR нужен, но он не повторяет аудиозамеры и не скачивает модели.
|
||||||
|
3. Измерительная ячейка запускает реальные модели. Для новой гипотезы нужен
|
||||||
|
только затронутый минимальный срез, один совпадающий baseline и первичный A/B.
|
||||||
|
Пять циклов и полные записи нужны лишь кандидату, прошедшему записанные пороги.
|
||||||
|
|
||||||
|
## Что осталось неизвестным
|
||||||
|
|
||||||
|
- C1 не получила слухового решения. Из автоматических метрик нельзя вывести,
|
||||||
|
допустимы ли два дополнительных слова без говорящего.
|
||||||
|
- На Ryzen не опубликовано разложение wall time на segmentation, embeddings,
|
||||||
|
clustering и orchestration. По общему времени нельзя надежно назвать следующий
|
||||||
|
доминирующий компонент.
|
||||||
|
- Полные записи не запускались: C2 не достигла порога, а C1 не дошла до Ryzen.
|
||||||
|
- Температурный датчик в WSL и Windows недоступен. Внешняя проверка питания и
|
||||||
|
throttling снижает риск дрейфа, но не заменяет измерение температуры во время
|
||||||
|
каждой ячейки.
|
||||||
|
- Эксперимент проверял локальные замены внутри прежнего каскада. End-to-end
|
||||||
|
архитектуры в эту матрицу не входили.
|
||||||
|
|
||||||
## Индекс публичных доказательств
|
## Индекс публичных доказательств
|
||||||
|
|
||||||
Хеши связывают обезличенные агрегаты с приватными JSON-результатами и не
|
Хеши связывают обезличенные агрегаты с приватными JSON-результатами и не
|
||||||
@@ -160,7 +310,9 @@ E1 и C2 сохранили все обязательные и диагност
|
|||||||
диагностическим слуховым gate: сокращение окон и цены эмбеддинга уперлось в
|
диагностическим слуховым gate: сокращение окон и цены эмбеддинга уперлось в
|
||||||
качество раньше итогового порога.
|
качество раньше итогового порога.
|
||||||
4. По правилу спецификации следующий шаг - отдельная карта end-to-end
|
4. По правилу спецификации следующий шаг - отдельная карта end-to-end
|
||||||
диаризации; этот отчет ее не открывает и новых замеров не назначает.
|
диаризации, заведенная как
|
||||||
|
[задача #45](https://git.dementev.space/ddmitry/local-transcriber/issues/45).
|
||||||
|
Ее гипотезы и замеры относятся к отдельному эксперименту.
|
||||||
5. Полные записи и Ryzen-слуховая приемка не требуются без победителя.
|
5. Полные записи и Ryzen-слуховая приемка не требуются без победителя.
|
||||||
6. Production-профиль, CLI, конфигурационный контракт и модель по умолчанию
|
6. Production-профиль, CLI, конфигурационный контракт и модель по умолчанию
|
||||||
остаются без изменений.
|
остаются без изменений.
|
||||||
Reference in new issue
Block a user