Постов было мало и все еще будет мало некоторое время, причин 2:
1. Тут
https://t.me/learning_stones/873 были собраны лайки и поэтому пишется "записка", которая уже разрослась в огромный документ. Вот небольшой форшадоуинг какие трюки и вещи разбираются, после прочтения каждый может пойти в Jane или Citadel на 800к бачей в год, вся "книжка" будет разумеется на англе:
- Дескриптор TMA живет в своем мире. Тензорный юнит читает его один раз, в момент issue, и дальше ему все равно, что с ним происходит. Поэтому дескриптор можно менять прямо во время трансфера, и поэтому же обычные store плюс __threadfence до него не доходят: generic-прокси и tensormap-прокси это два разных адресных пространства когерентности. Без cp_fenceproxy и fence.proxy.tensormap юнит будет продолжать читать старый дескриптор. Отсюда весь протокол mutable tensor map в CUTLASS и вся боль с кольцами дескрипторов для grouped GEMM.
- Готовность загрузки это не свойство памяти, а свойство scoreboard-барьера, который ptxas на нее повесил. Идея "грузи по 32 бита, и тот, кому нужно только первое слово, стартует раньше" упирается в то, что имен барьеров шесть. Внутри цикла компилятор вешает на все загрузки одно, так что консумер первого слова ждет последнее. Анрольнутый код получает отдельные имена, и тогда узкие загрузки действительно выигрывают. Контрол-коды Blackwell декодируются из вывода cuobjdump, и по ним видно, где именно компилятор решил за вас.
- Contended-атомики зависят от адреса счетчика. При том же коде и числе лейнов все решает то, где внутри килобайта лежит массив: на +512 байт вдвое быстрее, чем на +0, а адрес от cudaMalloc зависит от предыдущих аллокаций. Плюс warp-агрегация через match.any: один атомик на варп вместо 32, до 20x на плохом распределении экспертов и ноль выигрыша на хорошем. И счетчик L1 в ncu, который считает не "сколько атомиков слилось", а сколько проходов по тегам сделала линия.
- Combine в MoE без атомиков. Вместо scatter, где каждая строка эксперта делает atomicAdd в выход своего токена (атомики, memset, случайный порядок сложения, результат плавает в последних битах), каждый токен собирает свои k строк сам, в фиксированном порядке, и пишет один раз. Детерминированно до бита, в три раза быстрее, в SASS ни одного RED. И как общее правило: reduction делает владелец результата, а не источник данных.
- Consumer Blackwell (sm_120) умеет больше, чем написано, и меньше, чем кажется. gather4 из PTX 9.x, который по документации доступен только на датацентровых чипах, на 5090 собирается и исполняется в форме .shared::cta. А .multicast::cluster собирается с одним лишь advisory, но нативная инструкция выполняется только для маски 0x1 и только без кластерного запуска. Все остальное превращается в вызов рантайма в десятки тысяч раз дороже.
2. Автор
сошел с ума делает планировщик для больших и сложных графов, см картинку, когда доделает - непонятно