Обновить

Комментарии 51

то мы буквально имеем в виду, что электрический сигнал проходит по металлическому проводнику длиной в несколько миллиметров или сантиметров. И это тоже расстояние, пусть и ничтожное по человеческим меркам, но при тактовой частоте 3–4 ГГц оно уже имеет значение, просто потому что за один такт электрон в идеальных условиях будет проходить всего 10 сантиметров, а в металлическом проводнике на кристалле и того меньше.

Строго говоря - неправильно. Для медного проводника сечением 1мм2 и токе 1А скорость направленного движения электронов 0.073 мм/сек. Понятно, что на самом деле имелась ввиду скорость распространения электромагнитного поля.

Благодарю, поправил на сигнал, так будет корректнее.

@dalerank скажите, вы написали две как я понимаю фундаментальные причины, препятствующие созданию кэша L5 - это физическое ограничение скорости света (сигнал просто не успевает дойти) и сложности с когерентностью данных между ядрами (протоколы типа MESI). А как вы считаете, какой из этих факторов станет непреодолимым барьером раньше при попытке масштабирования кэш-памяти? И возможно ли, что развитие 3D-компоновки чипов или переход к новым протоколам когерентности (например, с директориями вместо широковещательного снупинга) сможет сдвинуть этот барьер в обозримом будущем?

Я вообще без понятия, честно. Вижу это только со стороны кода, и только когда это вызывает проблемы и баги, а в остальное время стараюсь писать стандартный код, который бы не приводил к таким проблемам и багам, но не всегда получается Ж)

спасибо!

А я бы сказал наоборот, что кэшей уже слишком много.

Появление кэша вообще в 386 и перенос его на камень в 486 – понятно, заметно, отлично.

Появление L2 – хорошо, но появляются нюансы.

Появление L3 систематически лет тринадцать назад я встретил некоторым скепсисом "будут ещё хуже код писать"...

"путь электрона" остался в следующем абзаце.

И тогда же компиляторы (в первую очередь Borland C++) начали применять такое понятие как локальность данных, оптимизируя размещение переменных и порядок объявлений в структурах и стараясь уложить горячие поля рядом

Это бьёт по ABI ведь... Сейчас в плюсах такое запрещено, а объявление структуры однозначно задаёт оффсеты полей.

Ну дядя Борман был известным приколистом в этом плане, на его багах я застал -Og, когда внутри функции делалась подфункция если некоторые части были одинаковые. И я бы никогда не знал про эту дичь если бы не странные краши, которые она порождала. Или -Ov, который пытался выносить переменные и инваринты из циклов. Или "фантастический" -Ob режим, который умел склеивать функции под капотом, что тоже добавляло отладки в ночи.

Суть не в том, что компилятор меняет порядок полей (он этого не делает), а в том что программисты начали сами группировать горячие поля в начале структуры, чтобы влезать в 64 байта

У IBM вроде бы есть ~динамический L2/L3 cache.

Также интересно, как себя проявляет в разных реальных задачах Xeon Max

(академический интерес в обоих случаях ))

Хеоны у меня были в руках очень давно, но в числомолотилках, да еще под ICC скомпиленых они уделывали AMD и обычные гражданские версии не то, что на проценты - в разы в некоторых случаях, на GCC результаты были сильно скромнее. Но, это было в 2008.

4 stacks of HBM2e, 64 gigabytes of ultra-high-bandwidth in-package memory and over 1GB of HBM capacity per core...

...ought to be enough for anybody?)

И не только в 2008. В 2025 так же. Что торч, что сьютспарс, что всякие оптимизаторы юзающие мкл, работает на них сильно быстрее.

Это та Intel MKL, которая при несоответствии CPUID == "GenuineIntel" специально использует медленный SIMD? (Ответ: да)

MKL_CBWR вам в помощь.

Устриц сьел где то с тонны две.

IBM в своих мейнфреймах серии z исторически использовала нестандартные иерархии памяти с бо́льшим числом уровней, чем принято в x86-мире

К слову, IBM давно экспериментирует с нестандартными иерархиями памяти. Любопытный пример - IBM 2361 (конец 1960-х, архитектура System/360). Это блок расширения ОП, который адресуется так же, как и "основная" ОП, но медленнее неё (8 мкс вместо 750 нс на Model 65).

Говоря о времени распространения сигнала можно вспомнить борьбу Seymour Cray за компактность процессора его суперкомпьютеров.

И это тоже расстояние, пусть и ничтожное по человеческим меркам, но при тактовой частоте 3–4 ГГц оно уже имеет значение

Да, как-то задумался, что при тактовой частоте 3ГГц за один такт луч света успевает преодолеть 10 см.

С лучом света вы правы. А вот на печатной плате из текстолита FR4 сигналы распространяются примерно вдвое медленнее.
(Это очень грубо, без учёта частоты и соседних слоёв / дорожек)

Размышления:

До всех кризисов память стоила копейки, казалось бы почему не воткнуть 64 gb в жесткий диск в кэша, но даже серверные решения даже близко не имели такого кэша. Почему, причина не техническая,а финансовая.

По теме статьи мнение:

С кэшем процессора, далеко не все решения имеют техническую составляющую, очень часто решение имеет даже не экономическую, а маркетинговую составляющую.

Были SSHD, но беглая гуглежка показывает, что больше их никто не выпускает, значит что-то пошло не так.

Строго говоря, флеш-память в современных жестких дисках, всё же, встречается

Пристально следил за прогрессом SSHD в свое время. Тесты показывали, что выигрыш был заметен далеко не на всех задачах, а стоили гибриды ощутимо дороже обычных HDD. Потребители проголосовали кошельком - в пользу «чистых» SSD, которые как раз переживали маленькую революцию с контроллерами SandForce.

есть такое, у знакомых на билдферме стоит пара Samsung PM9AX c 16гб кеша, но скажу что кардинально они картину не меняют, снижение времени сборки билда не стоит этих денег. Сам диск стоит как самолет и потом оказалось что дешевле было докупить 128Гб оперативки и развернуть в ней временный диск.

Так это SSD 7Тб/с, там другие ограничения будут в реальной жизни. Я же говорил про то, что берем тормознутый HDD, добавляем большой кэш, для определенных применений получаем решение - горячие данные всегда в кэше, а холодные на HDD. Сейчас время этого решения наверное уже ушло, но лет 15 оно вполне было себе актуально при нормальной реализации, а не как в свое время делали SSHD (редкостное поделие).

Fusion Drive от эппл передаёт привет. Там ровно эта идея реализована имеющимися на тот момент аппаратными средствами - ссд на 32-64 ГБ плюс хдд на 500 ГБ в рамках одного раздела. Горячие данные на ссд, холодные на хдд...

Финансовая составляющая там в том, что контроллер диска, способный адресовать и менеджить 64Гб кэша с нормальным алгоритмом вытеснения, стоил бы как сам сервер)

почему не воткнуть 64 gb в жесткий диск

Потому что ОС и так кэширует работу с диском. При этом 64гб памяти в компьютере стоят в разы, если не на порядок, дешевле, чем встроенная в диск память со всем прилагающимся обвесом.

Потому что есть риск 64 ГБ буфера сразу потерять при отключении электричества. А так, всякие ухищрения по этому направлению ложится на вендоров СХД и tiered storage по желанию сделают.

Про MESI протокол упомянули вскользь, а ведь именно накладные расходы на когерентность снупинга убивают масштабирование кэшей больше чем на 8-16 ядер

Это не было темой статьи. Я вам больше скажу, обычный (широковещательный) snooping MESI нормально работает только на 2-4 ядрах. Если интересно больше технических деталей то можно вот это почитать (https://habr.com/ru/articles/689310/), на 6–8 накладные расходы уже соизмеримы и превышают время работы с переменной в L2. Но все зависит от паттерна работы, если вся работа в пределах одного ядра то проблем не будет, проблема начинается там, где есть write-sharing, когда несколько ядер пишут в одни и те же или соседние кэш-линии. Но даже на двух ядрах можно подложить себе граблей с false sharing, если два потока пишут в разные переменные, которые случайно лежат в одной кэш-линии. И тогда с точки зрения MESI они делят одну линию, и каждая запись одного ядра инвалидирует кэш другого, хотя логически данные вообще независимы. Это классическая грабля при написании многопотока, еслиatomic counter1 и stomic counter2 лежат рядом в структуре, то они почти гарантированно окажутся в одной кешлинии и будут постоянно пинговать друг друга между ядрами, но увидите и почините вы это очень не скоро, если увидите вообще.

У ЦП reorder buffer 300+ микроинструкций, задержка на чтение RAM около 60нс, на 5ГГц это 300 тактов. Так что в идеальном случае память прочитается даже без кэшей.

В некоторых случаях кэши даже вредны, например memcpy при копировании более 2Мб включает некэшируемое копирование, иначе на заполнение кэшей тратится в 3 раза больше времени.

Не понял как кэш L1D может не требовать согласования с другими ядрами. Вот есть разделяемая переменная x и один поток, выполняемый на ядре 1, будет в нее писать, а другой - на ядре 2 из нее читать. Потоку 1 повезло и x попала в L1D. Я знаком с понятием store-буфера и что записи не обязательно должны вообще сразу попасть в кэш, если у нас нет write-барьера, но в какую именно кэш?

x=1;
smp_wmb();

Значит ли это, что после барьера x будет вытолкнута в L2, чтобы гарантированно стать доступной другим ядрам?

Нет, барьеры не выталкивают данные в L2, как вы выразились. smp_wmb() просто инструкция упорядочивания, которая гарантирует что все записи до барьера станут видны другим ядрам раньше записей после барьера. Это понятие только об относительном порядке видимости, и физические если вы откроете годболт там будет чтото вроде mfence или lock xchg, и все отложенные записи из store-буфера коммитятся в L1D конкретного ядра, а вот полетят ли они дальше в L2 вопрос. Ядро просто пометит свою копию как Invalid. Более того, L1D ядра1 может вообше отдать линию напрямую ядру2 через HITM, минуя L2, и изменения там появятся только когда ядро3 придет за этими данными, но там тоже есть особенности работы на старых Intel/Amd до 15года

НЛО прилетело и опубликовало эту надпись здесь

Если взять весь кэш современного CPU, что-то около 2Мб

Вы один нолик, как минимум, потеряли

Большое спасибо автору - видно, что человек глубоко разбирается и сильно напрягался, чтобы сделать текст более доступным.
Мне когда-то умные люди объясняли эту идею через ту же метафору «шкаф-ящик-коробка», но немного с другой стороны. Суть в балансе скорости, цены и физики. Регистры процессора - это «коробка» прямо в руках: мгновенный доступ, но если попытаться сделать ее объемом побольше, то критически увеличится размер кристалла, упадет выход годных, и все это будет стоить непомерно дорого. Оперативка - «шкаф»: вместительный и дешевый, но медленно и далеко. Разница в скорости между ними всегда измерялась в порядках. Сейчас: 2-3 порядка.

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

именно поэтому доступ к нему требует координации через протокол когерентности

Доступ к L3 не требует никакой координации. Но L3 выступает той самой шиной, по которой эта когерентность обеспечивается, да. Но когерентность обеспечивается между L1, L2 кэшами, при этом сам L3 кэш точно такая же коробка с игрушками. С той лишь разницей, что рядом стоит дядя с журналом и записывает кто и что оттуда взял/положил.

А как быть с гигантскими чипами, размером с кремниевую пластину (типа Церебрас и подобные)?

Как они решили проблему с огромными массивами памяти прямо на чипе?

Как они решили проблему с огромными массивами памяти прямо на чипе?

Никак, 48 КБ SRAM у каждого ядра, итого 44 ГБ, если сложить.

Задержка eDRAM была выше, чем у SRAM-кэшей, но в несколько раз ниже, чем у обычной DDR3/DDR4, и для графических задач вроде монтажа фильмов и тяжелого рендера, где рабочий набор текстур легко превышал десятки мегабайт, выигрыш был ощутимым, порядка x2-x3 при перемонтаже фильмов, что во временном исчислении превращало обработку из 12-14 часов на 2 часовой фильм всего в несколько часов.

Но ведь этого не было.

Задержка отличалась от оперативки в полтора раза (3dnews) или ближе к двум (chipsandcheese), на бенчмарках eDRAM особо не отражалась (ускорение монтажа в 2-3 раза - citation needed) и было понятно, что она подпирает встроенную графику, которой пропускной способности не хватало, но и больше двух каналов DDR в потребительское железо ставить нехорошо (Apple не знает). В "серьёзных" процессорах eDRAM не было (Xeon E5 и HEDT, сделанные из них).

На следующем этапе производительная графика стала приобретаться у AMD, которая решала проблему ПСП через HBM2. Были такие гибриды - Kaby Lake G с тремя кристаллами (процессор от Intel, GPU от AMD и HBM2).

те же eDRAM и HBM дают в 3–5 раз меньшую задержку, чем DDR5, при разумной стоимости

130 нс у Xeon Max, то есть в два с лишним раза больше, чем у DDR5. Она про ПСП, не про задержки.

Параллельно похожий подход развивался в мире HBM (High Bandwidth Memory) ... представляет собой дополнительный кристалл SRAM

* DRAM, стопку кристаллов.

можно было бы построить цепочку «SRAM → EDRAM → HBM → L5? → DDR → NVM».

eDRAM здесь вроде ничего не даёт, её ставили до времён 3D-кэша (задержки&ПСП) и HBM (ПСП&объём), которая в общем-то тоже eDRAM (eDRAM в Haswell тоже была отдельным кристаллом на одной подложке с процессором).

Я бы такое нарисовал:
L1-L3 (SRAM, вкл. 3D V-Cache) → HBM & HBF* → DDR → CXL & SCM** → прочее

* флеш-память, которую хотят поставить в положение HBM и таким образом выжимать ПСП.

** раньше поводили рукой и говорили, что будет некий storage-class memory (то есть memory-class storage, исправлять было поздно*~), который по задержкам займёт место между DRAM и флешем. Но Optane с его 3D Xpoint умер, взлетел CXL (можно вспомнить старые RAMdisk'и на PCIe) и быстрый флеш от конкурентов живёт (Toshiba XL-FLASH) либо возрождается (Samsung Z-NAND).

*~ "I think I coined the term in a meeting in Almaden in early 2000s. But not long afterwards we were in a meeting with Stuart Parkin, and he said “we really should be calling it memory class storage!!” I think Stuart was right" - https://thememoryguy.com/what-exactly-is-storage-class-memory/

Я все ещё не понимаю почему при таком небольшом количестве памяти, 32кб, 2мб кэшей( в сравнении с объемами ддр), этих объемов хватает для ускорения. Ведь очевидно что код не стоит на месте, и у него постоянно меняются "горячие" переменные, которые нужно подтягивать из ОЗУ. А ОЗУ, какая сравнили, это чердак. Тоесть в процессе работы придется бегать до чердака. И если рассмотреть какие-то большие массивы, то врятли они влезут в кэш.

Так же усиливает это не понимание что при загрузке системы, потребляется несколько Гб ОЗУ в принципе. И на фоне этого кэш в 32кб (2мб тоже) кажется мелким.

Я могу сказать про игры, но думаю это будет справедиво для большинства софта. Свременные игры занимают 16+гб оперативки, но это это не значит, что процессор реально работает со всем этим объёмом, потому что юольшая часть памяти будет просто загруженные ресурсы (текстуры, модели, звуки, анимации и разные буферы). Из них 90% используются редко или вообще обрабатываются видяхой, а не процом.
Потом в каждый конкретный кадр процессор обычно крутится вокруг очень маленького набора данных вроде позиций объектов, состояний AI, параметров физики и тд. И такой рабочий набор занимает очень немного, по моим замерам на текущем проекте горячий рабочий сет занимает всего 5Мб на каждый гигабайт выделенных данных в общем, т.е. на 8Гб всей игры мы имеем 40Мб рабочего сета, который мы перевариваем каждый кадр.

Поэтому даже относительно маленький кеш процессора в 32кб и несколько мегабайт L2/L3 позволяет это дело прокачать. Потом весь этот горячий сет мы пытаемся положить максимально линейно, тут уже пофик на красивые абстрации и паттерны работы - поэтому у нас появляются компоненты ECS, хот секции физический тел и тп. Учитывая что проце загружает память сразу линиями, вместе с нужным элементом сразу подтягиваются его соседи. В итоге мы приходим к том, что следующие обращения уже попадают в кеш, поэтому, несмотря на гигабайты оперативки, в реальности мы почти всё время работаем с маленьким набором данных, и кеш отлично справляется с тем, чтобы держать этот коробку и мешок под рукой. А вот если этого не получается, тогда начинаются проблемы, но это уже совсем другая история.

Надеюсь я ответил на вопрос

Причин несколько, но все они сводятся к одному: "чертова физика, бессердечная ты с*ка".

Доступ к L1 кэшу должен быть мгновенный (1-5 тактов), иначе теряется смысл и можно ходить в память. Но чтобы доступ был мгновенный, нужно:

  1. Иметь быстрый lookup (при увеличении размера - увеличивается время на поиск очевидно

  2. Иметь физически короткие контакты (дорожки). Иначе на частотах 4-5 ГГц, сигнал тупо не дойдёт за 1 такт, а это увеличивает latency. Речь о расстоянии в миллиметры и меньше, но можете сами посчитать сколько сигнал успеет пройти на такой частоте.

  3. Иметь разумное энергопотребление, и что важнее, тепловыделение, т.е. нельзя располагать память слишком плотно. Косвенно опять же связано с размером самой дорожки.

Плюс всё это не должно стоить слишком дорого. Некоторое время, на заре времён, экспериментировали с размерами L1 кэша, его ассоциативностью и прочим. Выяснилось, что 16кб - слишком мало. 64кб - слишком долгий доступ и греется зараза.

32-48 кб - оптимально. Так и повелось. По крайней мере для x86_64. Впрочем, и сейчас есть чипы с бОльшим количеством L1 кэша, у тех же Apple M-серии вроде что-то порядка 192 КБ. Если честно не вникал как они этого достигли, но вон чатгпт говорит что latency там все равно большой, физически архитектура сильно сложнее получилась, а компенсируется latency большим пайплайном исполнения.

Это конечно полезная информация для понимания, но я задаюсь вопросом почему этого хватает. dalerank выше уже частично ответил, что по статистике только 5 МБ горячих данных на 1 ГБ получается.

Да не так, чтобы "хватает". Просто на текущий момент физически доступ быстрее не сделать к объёмам памяти больше, чем то, что есть.

Полно сценариев, где объем кэша недостаточен и хотелось бы побольше, просто ну вот никак. Увеличивая объем - приходится увеличивать скорость доступа и в какой-то момент достигается паритет между кэшом и RAM)

HDD - L6 кэш, DVD - L7 кэш...

Сетевые ресурсы — L8

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации