Содержание
Лекция 1 (2012-10-15)
О чём этот курс, его содержание
Спецкурс кафедры АСВК, семестровый, в конце экзамен, форма экзамена скорее всего письменно-устная, но точно пока неизвестно.
В курсе предполагается рассказать то, что не затрагивается в других курсах, читаемых на факультете. Базируется на знаниях, полученных в процессе занятий реальными вещами после окончания университета.
Будут затронуты такие темы как физические основы построения ЭВМ с точки зрения того, что удалось достигнуть сейчас, флоу построения процессора и чипа, как вообще организован чип, x86, arm, power, mips — текущее состояние. Как организованы современные платформы и как происходит взаимодействие внутри них. Особое внимание периферии, так как интерфейсы требуют всё больших вычислительных ресурсов. Интеграция интерф общения с периферийными устройствами (сетевые адаптеры, видеокарты, и т.п.) на спарках, и не только, например, уже интегрированы в сам процессор. Вопросы подключения ускорителей. Мобильные платформы и вопросы энергосбережения.
Сегодняшняя лекция про то, как эти самые ЭВМ устроены, как напаяны эти самые страшные провода и чипы. Рассказ будет несколько фрагментарен, но лектор надеется, что этого будет достаточно для понимания, как оно вообще работает.
Голодный минимум
Не будем начинать с пафосных речей о том, что такое информация. Начнём с того, что у нас есть биты — два различимых состояния, которые надо хранить, передавать и обрабатывать.
Всё это можно делать различными способами. Механический — счёты, машина Бэббиджа, калькулятор Паскаля. Состояния дискретны. Сложны в реализации. Бэббидж, например, так и не смог добиться нужного качества шестерёнок. Механика и в современных системах зачастую лимитрует производительность. Например, скорость произвольного доступа к жесткому диску упирается в механику. Хотя, вся механика заключается только в движении головки. Более механическая core memory, где магнитные сердечники нанизываются на пересечения проводов, запоминая бешеные килобиты-мегабиты информации, при том, что современные им жёсткие диски были ёмкостью десятки мегабайт. Чем меньше механики, тем лучше, используем электромагнитизм во благо человечества.
Схема зажигания лампочки магнитной катушкой — пускаем ток, катушка намагничивается, притягивает металический язычок, который замыкает контур и даёт ток лампочке.
Если два таких реле соединить последовательно, то лампочка загорится, только если оба ключа замкнуты. Таким образом, мы изобрели логический элемент «И», и можем себя с этим поздравить. Аналогично, можем включить реле параллельно и получить элемент «ИЛИ». Реле — это один из способов организации схем, которые использовались в конце 40-х годов, потом перешли на лампы, потом на транзисторы. На реле зато очень удобно все показывать — ток пустили, лампочка загорелась, всё понятно.
Далее будут использоваться следующие обозначения логических вентилей:
И
ИЛИ
По аналогии можно сконструировать другие логические примитивы — буфер, отрицание, исключающее или, или-не, и-не:
БУФЕР
НЕ
НЕ-И
НЕ-ИЛИ
ИСКЛ_ИЛИ
НЕ-ИСКЛ_ИЛИ
Описание логических вентилей в википедии
У подобных схем есть некоторое время срабатывания. Оно, вообще говоря, зависит от массо-габаритных характеристик реле. Поэтому вводится элемент буфер (простейшая конструкция — два последовательно соединенных отрицания). В основном он нужен для выравнивания потоков, когда один идёт по сложной схеме, а второй по простой, и надо их синхронизировать.
Так же вводятся сумматор и полусумматор ( как на курсе основы кибернетики).
Полусумматор (A, B — входы, S — выход, C (carry-bit) — бит переноса):
И сумматор:
Если сделаем извращение и зациклим NOT, то это будет очень странная схема, но она будет иметь право на существование. Получим генератор автоколебаний (тактовой частоты) . PLL(phase locked loop) и DLL (delay locked loop). Имея такой генератор, можно им тактировать разные схемы.
Из двух модулей или-не можем собрать штуку, работающую довольно интересным способом:
Два ключа разомкнуты — лампочка не горит. Замыкаем вход один вход один раз, потом размыкаем, а лампочка продолжает гореть (за счет того, что или на входе достаточно всего одной 1). Схема запомнила свое состояние. Если замкнем один раз другой вход, лампочка погаснет. Такая несложная схема называется latch, или защелка. Это базовый элемент различных схем. Все подобные схемы называются flip-flop (тригеры). Из википедии — простые элементы, запоминающие состояния, обычно называют защелками. Элементы, запоминающие состояния и включающие в себя генератор тактовой частоты (clocked devices) называют триггерами (flip-flops).
Чтобы из этого сделать что-то интересное, добавим защёлку по уровню(Gated D latch):
У простой защёлки два входа, но ток мы подавали либо на один, либо на второй. Логично попробовать сделать нечто, где это "либо-либо" определяется одним входным битом. Защёлка по уровню получается из простой защёлки тем, что
к схеме добавляется разветвитель, у которого один вход (D) и два выхода: D и отрицание D.
так же добавляется вход E (write-enable, clock, control). Если E=1, то защелка передает D на свой выход Q, и, соответственно, отрицание D на свой второй выход. Если E=0, то защелка остается в неизменном запомненном состоянии, чтобы не происходило с D.
Обозначение защелки по уровню:
Таблица истинности для защелки по уровню:
E |
D |
Q |
!Q |
0 |
любое |
предыдущее Q |
предыдущее !Q |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
Защёлки по уровню необходимы, в частности, при сопряжении наборов логики, тактирующихся различными генераторами тактовой частоты.
Следующий необходимый нам элемент — защёлка с срабатыванием по фронту (positive-edge triggered master–slave D flip-flop):
Защёлка со срабатывание по фронту получается, фактически, соединением двух защелок с срабатыванием по уровню и добавления в правильные места инвертеров.
Обозначение на схемах:
Таблица истинности:
Clock |
D |
Q_next |
Превращается из 0 в 1 |
0 |
0 |
Превращается из 0 в 1 |
1 |
1 |
Не превращается из 0 в 1 |
X |
Q |
В момент переключения сигнала C из 0 в 1 мы запомнили вход D. Будем использовать, когда будем рассматривать всякие периферийные шины. Когда клок начинает подниматься из 0 в 1, берётся состояние со всех входов, а в остальное время там ещё идут всякие переходные процессы. Например, шина PCI на этом играет.
У защёлки по уровню переименуем входы в write-enable и data-input, а выход оставим один, назвав data-output. Вот у нас ячейка памяти в один бит.
Итак, у нас есть память. Чтобы иметь доступ, надо к ней адресоваться. Чтобы адресоваться сделаем ещё одну простенькую схему. Возьмем таких ячеек много, например, 4. Допустим, мы хотим их читать последовательно. У нас два бита на адрес. На входе адрес надо дешифровывать, чтобы понять, из какой именно ячейки брать окончательный DataOutput.
Есть две волшебных коробочки — дешифратор и селектор.
Пример дешифратора для 2 битов адреса и 4 выходов (позволяет по адресу подать напряжение на нужный выход):
Пример селектора для 2 битов адреса и 4 информационных входов (позволяет оттранслировать на выход вход с номером, соответствующим адресу):
Из селектора, дешифратора и ячеек памяти собирается блок памяти.
Из D-type latch с переключением по фронту можно собрать уменьшитель тактовой частоты в два раза.
Если собрать их несколько, то можно получить счётчик тактов. Полезная штука.
Это голодный минимум, который нам потребуется дальше при рассмотрении архитектуры процессоров.
Ещё немножко поговорим про воркфлоу разработки чипов и, наверное, на этом и закончим.
Воркфлоу разработки чипа
В Sandy Bridge’e порядка 2-x миллиардов транзисторов. Из них 30 процентов только память. И вы видели, как это всё соединено — даже селектор 4 на 1 уже было не очень понятно, а в более сложной логике все ещё страшнее. Логика в десятки, сотни, тысячи элементов ещё обозрима умом (так делалось в 50-е годы), то сейчас умом это уже не обозримо, и есть воркфлоу разработки, начиная от относительно высокоуровнего system-c и вплоть до топологии. Когда у вас уже нарисованы все дорожки, просчитаны все задержки, и на всех уровнях у вас происходит верификация, что вы укладываетесь в необходимое время.
Сначала появляется некая идея про то, что должен делать чип. Разрабатывается спецификация, разрабатывается архитектура.
Архитектура. На этом уровне определеяется функциональность создаваемого чипа, создается спецификация. Осуществляются начальные этапы формальной верификации.
Модель. Задается высокоуровневое описание того, как будет реализовываться указанная в спецификации функциональность. Чаще всего используется язык проектирования и верификации моделей системного уровняSystemC
'''Netlist''' (описание графовой структуры) + '''SDF''' (привязка к временным ограничениям, time constraints)
Place&Routing. Есть чудесный граф без привязки к реальной жизни, что создать соответствующую ему интегральную схему, его надо разложить на несколько плоскостей, чтобы ничего не пересекалось и лежало красиво, и соблюдались time-constraints. Сказали гигагерц — должна вся логика за наносекунду переключаться. В связи с этим, кэш 2-3 уровня обычно работает на какой-то части от основной частоты (потому что дешифраторы/селекторы там большие слишком).
Floor Planning — примерный дизайн расположения основных блоков, чтобы раскладывать не два миллиарда транзисторов за раз, а отдельно каждый блок, каждый из блоков по 100-10 миллионов транзисторов.
DFT. После того, как вы полили несчастную кремниевую пластину кучей химикатов, у вас есть некий процент негодных чипов. Эти негодные чипы хочется выявлять как можно раньше. Пластину режут, потом клеят на подложку. Изготовление подложек процесс нетривиальный, и тратить их на негодные чипы не хочется. Актуален вопрос отсеивания бракованных чипов сразу после разрезания. DFT (Design for testability) — базовые проверки на то, что логика переключается, итп. Это тест именно работоспособности чипа, а не его функциональности.
PLOC (pin location) package от того куда вы какие дорожки выведете будет зависеть то, как удобно у вас будет дизайнится печатная плата (PCB). Pentium 4 требовал 10 слоёв подложки, например. Тогда же выравниваются дорожки. Разбегание дорожек skew, его нужно компенсировать на PCB.
Power. Оценка power consumption, TDP.
В следующий раз про архитектуры различных платформ и немножко про процессор изнутри.
Дополнительная часть
На самом деле никаких нулей и единиц не существует. Сушествуют high и low, которые условно считаются 1 и 0. Пусть номинальное напряжение у нас 5 вольт. 0—0.8 считаем 0, 2.2—5 — единицей, а что между ними? Между ними x. На некоторых этапах симуляции мы допускаем на входе что-то неизвестное.
PCIe 3.0 8 GT/s 125 ps^(-1)
Дергать напряжение с такой скоростью — задача затруднительная. В реальной жизни идут всякие переходные процессы. Сейчас рассказывается обзорная штука, ничего строго.
TTT74xx — библиотека логических элементов.
Хотим подавать какой-то сигнал, например 0111010. Реальный график напряжения будет весьма гладкий, поэтому надо предвосхищать смену значений — pre-emphasis — преусиление (преискажение) и post-emphasis. Тогда мы сможем начать передавать что-то похожее на тот сигнал, который мы хотим передавать.
Реально увидеть этот график сложно, поэтому смотрят на eye-diadram — гонят по проводу большое количество данных и смотрят, какая картина происходит статистически, определяя, как часто мы попадаем в значимые значения, а как часто в молоко.
Differential pair.
Машинерией считывания сигнала занимается serdes — serialiser deserialiser.
Это все был трансмиттер.
На приеме приезжает страшный, измученный искажениями сигнал, к которому обычно применяется следующее:
- отсеять гармоники. Самый простой способ — использовать комбинацию активного сопротивления и индуктивнусть и ёмкостное сопротивление такие, что они будут минимальны именно на частоте приемника. Другой способ — использовать decision feedback eq. Используем автоподстройку усиления.
Ссылки (by Allena)
Лекция 2 (2012-10-22)
Сегодня попытаемся продолжить дискурс, начатый в прошлый раз, а именно рисование различных вентилей под соусом архитектуры современных платформ.
Схема простейшего процессора
В прошлый раз мы остановились на том, что нарисовали сумматор, который умел складывать целый один бит. Довольно очевидно, что сцепив несколько таких устройств мы можем построить сумматор на несколько бит.
Соединим сумматоры посредством нескольких шин A[n:0], B[n:0], CarryOut, CarryIn, Result[n:0].
С этим чудесным функциональным устройством что-нибудь делать. Можно брать память и сумматор.
Из нескольких триггеров по фронту можно собрать аккумулятор (поставить их рядом и сказать «запоминайте значения»).
Тригер со сбросом — это обыкновенный триггер с срабатыванием по фронту, перед которым стоит ещё один триггер со срабатыванием по уровню с инвертированным клоком. Сохранили в момент перехода с нуля в единицу значение передаваемое на вход DI. Добавили Rst symbol. Когда ресет единица, или когда отрицание данных единица — мы сбрасываем. Сделали это через конъюнкцию с клоком.
v
Таким образом в счётчик, собранный из нескольких делителей частоты, можно добавить сигнал ресета.
Каким образом этим чудесным устройством можно пользоваться? Мы можем задать начальное значение в памяти. Делается различным образом. Так или иначе добавить какой-нибудь селектор и входы Write и DataInput. На каждом клоке получаем в аккумуляторе сумму аккумулятора и очередной ячейки памяти.
Очень круто, мы научились складывать ячейки памяти. Как остановиться? Останавливаем клок.
Не густо.
Можно заметить, что счётчиком на самом деле можно управлять, потому что это точно такой же набор триггеров. Можно добавить запись в память. Добавим память с перенумерованными командами. Мы приблизимся к гарвардской архитектуре, в которой команды и данные хранятся отдельно.
Из блоков counter data_memory Cmd_memory Sum Dec Accum Mux_n_to_2n можно собрать чудесный компьютер, который умеет суммировать и сохранять.
[схема]
Историческая справка
Есть процессор (CPU).
Есть чипсет, который на самом деле занимается вводом-выводом.
Есть контроллер памяти (MC — memory controller) и собственно память. Контроллер памяти может присутствовать как часть чипсета, может входить в него — это не принципиально, главное что они все друг с другом связаны.
Чипсет имеет некоторые интерфейсы ввода-вывода. На данный момент это PCI Express и всякое legacy. Начиная с Sandy Bridge PCI Express переехал в процессор. Туда же, начиная с Nehalem, переехал контроллер памяти, и в некоторых вариантах процессоров стало появляться встроенное видео.
В процессоре расположены функциональные устройства, выполняющие непосредственно некие операции и фронтенд. Фронтенд занимается, в частности, предсказанием и всяким таким. Результат работы функциональных устройств может попадать на архитектурные регистры, может сохраняться в памяти. В CISC архитектурах, в частности в х86, внутри процессора команда, которая ему попадает, обычно довольно сложная. То есть, например, «сложить ячейку по косвенной адресации с промежуточным числом или с регистром и потом куда нибудь сохранить».
Внутри процессора эта команда разбивается на несколько операций. У Intel они называются μ-оп. Такая организация появилась с Pentium Pro (P6).
А вот Pentium MMX базировался на предыдущей архитектуре P5. Это вариант развития архитектуры Pentium, там было два конвейера: u и v. Один из них мог почти всё (u), а в v конвейер был вспомогательный, и были сложные правила, какие операции на каком можно выполнять, какие можно выполнять одновременно. В Pentium MMX добавились регистры mm0..mm7. Кто не знает, регистры MMX замещают регистры FPU. В FPU имелось 8 регистров fp0..7 и набор команд, который позволяет с ними работать. Всё бы хорошо, но доступ к ним в виде стека и ширина у них 80 бит. MMX-регистры использовали младшие 64 бита fp регистров.
Pentium Pro была новая архитектура, в которой добавили много плюшек. В частности, разбитие на μ-опы и несколько декодеров. В Pentium II было 3 декодера, один из них кажется мог выполнять 3 μ-оп за такт, другие по 1. В Pentium III вроде было 4-1-1, в Core 4-2-2, в Nehalem вроде стало больше декодеров и вообще он претерпел большие изменения.
Вариант архитектуры P6:
Вариант архитектуры Nehalem:
NetBurst (Pentium 4) сейчас не затрагивали, потому что он имеет достаточно сильно отличающуюся архитектуру от ранее упомянутых, и , как показала практика, архитектура была не очень удачная, хотя были бешеные гигагерцы — быстро появились 2, 3 ГГц, но гнать дальше было невозможно из-за слишком длинных конвейеров, слишком большой ошибки предсказания, и так далее.
Тогда же AMD выпустило версию в K10 с интеграцией контроллера памяти в процессор, а не в чипсет, тогда же они сменили впервые за долгое время сокет.
Функциональные устройства на самом деле называются бэкенд. Это все обмазано некоторым количеством кэшей. На фронтенде имеется кэш команд. L1 появился в x86, L2 в Pentium II—Pentium Pro. У AMD начиная с P6.
У x86 есть проблемы с декодингом (разбором) команд, поэтому достаточно существенную часть по площади от логики фронтенда занимает разбор команд.
Volatile memory (энергозависимая память) из той, что обычно используется, есть примерно 3 типа:
- память на тригерах, для хранения данных внутри чипа
- static random access memory (SRAM)
- dynamic random access memory (DRAM)
Общая идея заключается в том, что если двигаться от триггеров к DRAM, то тратится меньше логики для хранения одного бита, меньше энергопотребление, но менее удобно. Например, DRAM надо обновлять(«рефрешить»), доступ к ней медленный — сотни тактов, и вытаскивать оттуда надо сразу по 32-64-128 битов. В DRAM выходит около 1 транзистора на 1 бит.
IO
Ввод-вывод, на самом деле, практически повсеместно представлен шиной PCI/PCI Express. Практически все интерфейсы, которые интересны обычному пользователю, обычно вставляются как PCI устройства. USB hub, USB контроллер, SATA Host Bus адаптер. Но, помимо этого, есть ещё некоторые другие интерфейсы.
Как мы видели, процессор — это не магия. Это тот же самый чип, и, если мы рассматриваем какой-нибудь embedded, то там встречается такая штука как local bus, который позволяет нам писать в память, и как-то иначе работать с ней. Есть ещё такая штука как JTAG — консьюмерская штука, протокол стандартизирован в IEEE249. Предназначение — всякие отладочные вещи, в основном, чтение и запись триггеров внутри чипа. Если в случае десктопной платформы с JTAG общаться не придётся, потому что все его пины выжраны, то в случае ARM часто встречается ситуация, что интроспекция производится с помощью JTAG, потому что он, среди прочих, интегрирован в datasheet.
Ещё про выводы — VGA с соответствующим рандапом, либо DVI, HDMI. Thunderbolt точно идет как PCI Express.
Это то, что касается примерной архитектуры. Контроллер памяти чаще всего часть либо чипсета, либо CPU. Между CPU и чипсетом у Intel’а использовались, по хронологии: FSB, DMI, QPI. В случае AMD, начиная с K10, для связи чипсета с процессором начали использовать гипертранспорт (HyperTransport). Одно время гипертранспорт достаточно активно продвигался в качестве ассиметричного ответа Intel’у, потому что как PCI, так и PCI Express это детища Intel’а, как и большинство современных периферийных шин. А гипертранспорт какое-то время был противовесом, казалось что отвоюет какую-то долю рынка, но так уже перестает казаться. Даже AMD уже планирует отказаться от его использования. Для связи с южным и северным мостом уже используется, де-факто, по другому названная PCIe x4 (alink), но с модифицированной электромеханикой — заранее известно, что ожидать с той стороны, и инициализация попроще. Для связи процессора и северного моста также может тоже уже не будет использоваться гипертранспорт.
Последнее K10 что помнит лектор MagnyCours (???) потом они сказали, что делают новую архитектуру, но как-то совсем всё грустно.
Архитектура Bulldozer — они решили сделать гипертрединг (hyper-threading) наоборот. Гипертрединг (гиперпоточность) — это попытка использовать избыток функциональных устройств. Здесь наоборот — взяли два ядра и объединили их по части FPU и по фронтенду. За счёт этого они решили выиграть по упрощению. Идея взялась из того, что фронтенд штука сложная, и хотелось их объединить. Но вот не срослось, по тестам штука грустная. Дальше были Piledriver и Streamveller. Они умудрились сохранить сокет. Все помнят, как Intel меняет сокеты. Почему в Sandy Bridge поменялся — потому что PCI Express переехал с чипсета на процессор, и вся схемотехника платы поменялась. В серверном варианте Sandy Bridge E у вас 40 линий gen3. AMD сокет довольно редко меняет, с K10 оно вроде все одинаковое.
Обзор платформ
Интересен IBM Power A2 18-ядерный, и с интерконнектом в чипе, и все это на 45 нм техпроцессе. Есть желание иметь большое количество вычислительных ядер и низкую latency. Шины типа QPI позволяют связывать не только процессор и чипсет, но и процессоры между собой, в случае последних архитектур от Intel’а. У AMD всё грустнее, они делают через гипертранспорт. У процессора до 4 гипертранспорт ендпойнтов из которых 3 кэш-когерентны, то есть можно собирать 3-4 процессорные конфигурации.
У Intel’а с Westmere Intel Xeon e8xxx, Xeon e7-8xxx там довольно большое количество QPI ендпойнтов. На вестмерах у супермикры есть варианты 8 процессорной платформы, они правда собраны не вполносвязный граф, а вдовольно интересную архитектуру.
У каждого ядра по станд набору регистров?
У х86 все очень развесисто. Есть рег общего назначения, которые на самом деле нифига не общего, общего начинаются только с x86-64, есть ещё куча всяких регистров.
add ax, bx mul ax, cx mov [dx], ax xor ax, ax mov ax, [cx]
Эти вещи можно выполнять параллельно. (Почему?!)
Чтобы более-менее утрясти и закончить с историей, расскажем в общих чертах что происходило с х86 и пауэрами. х86 реально можно рассматривать только Intel и AMD. в какой-то момент (386-486) было достаточно много других вариантов но как-то они все выглядели совершенно несерьезно разве что у глиа было преимущество по энергопотреблением, но оно все завончилось из-за довольно низкой производительности.
386 FPU
486 кэш L1
В P5 появились у-в конвейеры и ммх.
В P6 появились мопы, PAE (поддержка 64-битной адресации), L2 кэш. где-то здесь появился ещё SSE.
NetBurst и параллельно с ним Pentium M
У AMD K6 зднау, K7 Athlon,
В K8 MC → CPU, хотя и пришлось менять сокет, но зато наличие контроллера памяти в ЦПУ реально увеличивает производительность. У Intel’а при аналогичной штуке в Nehalem’е очень сильно старадала производительность PCI Express, изза того что PCIe оказался на чипсете, а контроллер памяти в процессоре, оказало очень плохое влияние на DMA — возможность пси-устройств напрямую работать с памятью хоста. Там стало всё очень плохо, это заметили те, кто занимался видеокарточками, сетевыми адаптерами, но это исправили только в Sandy Bridge.
Хотели достигнуть 3 ГГц, но теплопакет стал вываливать за 160 ватт и не достигли.
Сore SSE3
Сore 2 SSSE3
Nehalem AES-NI, MC → CPU
Sandy Bridge avx, PCIe → CPU
у AMD был K10.5
64 бита впервые появилось после K8 в AMD, у Intel’а 64 появилось в Pentium D.
По поводу IBM’а.
В следующий раз подробнее про то, как работает процессор.
Ссылки
Лекция 3 (2012-10-29)
Организация процессора
Сегодня про организацию процессора.
Схема.
Ряд качеств:
- Конвейерный принцип.
- Суперскалярность -- несколько операций за такт (благодаря нескольким FU).
Сравнение и условный переход могут объединятся в одну операцию, итп. Про преобразование инструкций в операции фу ещё поговорим. Так или иначе есть операции, которые надо выполнять ( не совсем те, что инструкции). Эти операции могут выполняться в какой-то степени одновременно.
- Ещё одинм важным аспектом является то, что порядок операций не жесткий. Происходит вычисление зависимостей, в некоторых реализациях осуществляется спекулятивное выполнение.
Раньше инструкции и операции были одинаковы, теперь сложная инструкция на входе разбивается на простые опы внутри, что позволяет упрощать архитектуру и повышать тактовую частоту.
Все это обмазано каким-то количеством кэщей. Здесь нарисован л1 л2, вообще их больше, дальше попробуем рассказать.
Как происходит выполнение команд?
- Чтение в кэш. Чтоб можно было их сколь либо быстро разбирать.
- Разбираются они в кэш инструкции. В х86 они разбираются в л1 инстракшн кэш. Сейчас будем рассматривать х86, но для повер писи, спарков до ниагары, мипсы всё похоже, с точностью до размеров. Перед попаданием в инстракшн кэш в некоторых реализациях может выполняться полное или частичное декодирование. Полное делается в нетберст, частичное в к7(Атлон), к8(Атлон64) и интел кор 2 и старще -- там частичное декодирование.
- Из инстракшн кэша происходит забор инструкций. После обработки в блоке декодирования появляется поток мопов. У повер писи они называются опы, у интел микрооперации, у амд мопы.
- Аллокация регистров. В процессоре есть архитектурные регистры (операнды инструкций) и внутри бэкенда используются физические регистры, которых существенно больше, потому что мы пытаемся делать скалярное, спекулятивное, внеочередное выполнение, и без доп. регистров это трудно.
- В процессе аллокации после этого операция попадает в буфера планировщика и блок переупорядочивания. В нём и происходит уже непосредственно ожидание на выполнение команд. В РОБ хранятся все операции, которые ещё не завершили выполнение и одновременно с этим эти операции находятся в ожидании на выполнение внутри блока планировшика,обычно они там уже привязаны к определенным фу.
- Когда устройство освобождается и планировшик решает, что оп может быть выполнена( все данные готовы, регистр под результат есть), то она запускается на выполнение.
- Операция может возыметь эффект на бранч предикшн, регистры, кэши.
Попытаемся подробно рассмотреть каждый из данных блоков.
Инстракшн кэш. Обычно представляет собой некую память, обычно срам (довольно быстрая память, работающая на частоте не сильно меньше процессора и имеет объем 8 кб для пентиум 4, нехалем сандибридж 22 кб, в хасвелл есть желание радикально увеличить размер л1 кэша, правда непонятно, за счет чего. Сейчас это порядка 32 кб.
Как вообще она реализуется? Как следует из названия кэш предназначен для хранения данных, которые присутствуютт в памяти, но к ним хочется быстрый доступ. Выборка из него должна быть быстрая ( 1 такт), а складывать мы туда хотим из разных участков памяти. Если мы таскаем по 1 байту их разных мест, то выбирать быстро можно было бы только для маленьких объемов. Поскольку что данные, что инструкции, нам требуются кусками, хранить их принято последовательно.
Первый термин -- строка кэша, кэш лайн. Чаще всего от 32 до 128. В х86 обычно 64 байта. Младшие 6 бит адресуют байт внутри строки. Остается 26 бит, кэш в 512 строк. Поиск за один такт малоосуществим. Скажем, что 9 бит адреса нам скажет, какая строка используется, а старшие биты это просто некий тег, и если он совпал, то это та строка, которую мы искали. Если нет, то у нас произошел хэш-мисс и строку надо грузить из памяти. Это называется дайрект адрессинг. Такой способ не является эффективным. Если не влезает все в кэш, у нас сразу возникают проблемы, потому что мы начинаем выбивать строчки рандомно и никак не учитываем историю её использования, что сильно ухудщает производительность кэша. Поэтому везде пытаются сделать некую ассоциативность. Асс -- сгруппируем строки по 4/8/16. У интела по 8. Тег становится на 3 бита больше (с 6 по 11). Теперь уже не 9 бит а меньше, если асс уровня 8, то ... Таким образом мы выбираем набор, а это уже используется как тег, но мы его ищем среди набора из 8 строк. И думаем про то, какую из 8 строк выкидываем, если не нашли и все заняты. Обычно используется лист рисентли юзд. Строка, которая использовалась позднее всего выкидывается. Для этого требуется дополнительные три бита.
В итоге, кэш имеет примерно следующую структуру
Схема
Кэш первого уровня для ассемблера прозрачен. Кэш 2-3 уровня обычно можно потюнить. Хотя в реальности все можно потюнить, везде поставить счетчики, и все не так чудесно.
Чем больше строк, тем больше алиасинг. Тем меньше строк, тем меньше флексибилити.
Есть ряд схем, где реализуется полная ассоциативность.
Пусть тег имеет 20 бит, и нам надо сравнить его сразу с 8 значениями. Схема, на вход 8*20-20=140 сигналов. Это занимает много места и очень грустно. Если не 32-разрядная, а 64 разрядная адресация, то под адресацию может уходить до 48 бит. Сейчас планомерно патчиками увеличивают количество битов доступных для адреса (про ядро линукса). Там сначала мапинг физ устройств, потом...
Все сразу поняли, почему мы берем старшие биты адреса а не младшие, потому что это способствует лучшему поведению кэшмисса -- строчки будут выбиваться с разных страниц -- при последовательном подсчете последовательные строки попадают в разные блоки кэша.
Следующий важный блок -- предсказание переходов и направлений условных переходов. В некоторых арх отсутствует, иногда можно пытться заменить спекулятивным выполнением, можно ничем не заменять, но это плохо.
БПП помогает пытаться угадать, куда может быть сделан переход и заранее начать декодировать и аллоцировать операции. Если базируемся целиком на спекулятивным выполнении (Intel Itanium, Cell) -- гибрид ежа с ужом, с одной стороны влив, с другой стороны много всяких вкусностей. Там фактически выкинули бпп и вместо этого опирались на спекулятивное выполнение. 128 слово состоит из 3 комманд и некоторых битов маркеров, в которых говорилось, что команда должна выполняться спекулятивно. Спекулятивные команды в итоге либо давали эффект либо нет.Счастья не случилось, потому что чтобы генерировать код, для которого это было бы хорошо, оказалось сложно, компиляторов под это так никто и не сделал. То, что касается целлов -- они имеют частично схожую архитектуру.
В х86 используется бренч таргет буффер в котором сохраняется адреса команд, на которые производились переходы. Он имеет размер типа 512 записей. И когда появляется эффект команды, туда помещается адрес инструкции если на нее был переход. Используется во всяких циклах, безусловных переходах и так далее.
Если, например, мы видим что на данную инструкции может быть осуществлен переход, то мы можем получить её из кэша уже декодированной.
Второй частью бранч предикшн явл. бранч хистори тейбл -- куда осуществлялись исходные переходы, плюс эвристики куда могут осуществляться переходы дальше. Если угадываем правильно, то на удачное срабатывание уходит 1-2 такта. Эвристики являются коммерческой тайной, но можно наблюдать, что предсказываются интерливд, длинные, с задааным количеством итераци циклы, колл ретурн предсказывается, иногда одноразовые переходы. Понятно, что если мы с переходом не угадали и она идет не туда, куда мы подумали, то мы заранее декодировали не те инструкции не по тому адресу и приходится сбрасывать почти весь конвейер и честно идти получать инструкцию по нужному адресу и так далее.
У поверов бранч предикшн попроще, поскольку они от этого не так сильно страдают. Блок нужен, когда очень большой конвейер и большие потери, если его сбрасывать. В этом блоке за счет разнообразных эвристик.. Бранч предикщн и сам занимает довольно много логики, если смотреть на чип.
Далее ещё один сложный в плане реализации блок -- декодирование. Сложный в х86, потому что инструкции имеют разную длину - до 16 байт + префиксы, минимальный 1 байт (подряд много нопов можно сделать очень маленькими). Борятся с проблемой сложности амд и интел по разному. Амд делает предварительную разметку. В л1и у амд с к8 инструкции уже размечены. У интела предекодирование начиная с кор2. Схема след -- берутся куски выдранные по 16 байт и скармливаются 16 PLA (Programmable Logic Array) -- скармливаются с разным смещением. И каждый пытается понять, является ли 4 байта началом команды, 1 байт префиксом. Делается за 1 такт. Потом информация собирается начиная с первой. Таким образом можно понять, где начинается команда, итд.
Сама команда. Префиксы задают режим команды. За одним из префиксов куча команд -- всё ссе, итд. Сама команда - операция и аргументы, а в конце интермидиат аргумент и, например, смещение, если того требует формат команды.
Интел долго не мог отказаться от специальных регистров, accumulator, counter, base, data -- они все имели специальный смысл. Например, цикл был только по cx, или команда сильно усложнялась и начинались всякие упражнения.
На вход декодеру поступают размеченные команды, а на выходе у него мопы -- то есть операции, выполняемые фу.
Из важного есть (типы):
- Op просто операция, использует физ регистры
- Load для загрузки данных в физ регистры
- Store данные с физ регистра поместить туда-то
На операции такого вида у вас происходит разбивка команд.
mul %ebx, %edx[2]
Будет разбита на
load %edx, 2 op mul store (...)
Обычно есть более главный декодер, генерирующий 4 мопа за такт, и менее главные, которые генерируют 1-2 мопа за такт. В кор 2 схема стала типа 4-2-2. У к8 схема 2-2-2. У нехалема и сандибриджа ещё больше. Реально кор2 мог читать 4 инструкции и выдавать до 6 мопов за такт.
Можно реализовывать и более сложные операции. Амд поддерживал не совсем простые мопы, а например оп-стор, лоад-оп. Усложняло фу, упрощало декодер. Поэтому то, что у амд по чиселкам декодер был меньше, не совсем корректно сравнивать. Начиная с пентиум м интел тоже научился мерджить мопы. Начиная с кор 2 появился мерджинг теста и условного перехода.
Далее мопы попадают в реордер буффер и ставятся в очередь на выполнение.
Про аллокацию. В х86 физ регистры имеют размер 80 бит. Если опер ссе, то аллоцируются 2 физ регистра. Начиная с нехалема размер внутр. регистров кажется был увеличен. Этих регистров толи 32, то ли 64. Их гораздо больше, чем архитектурных.
Это чистилище ещё называется reservation station -- где опер ожидают свое выполнение. В пентиум м и корах это было один блок сложения, один умножения, один лоад, один стор. В кор2 кол-во фу увеличилось, в нехалеме ещё увеличилось, но в нехалеме появился гипертрединг и жестко делил ресурсы декодера и буферов, а тут все было довольно гибко, но чтобы его компенсировать он стал достаточно широким. В первых корах 40 мопов, кор 2 64, нехалем 128. Проиграть по сравнению с кор2 было нельзя с включенным гипертредингом. Ну и декодер стал более мощным в нехалеме.
Если непредсказаннный переход, то так и будете здесь висеть и ничего загрузить не сможем, пока все операции перед переходом не выполняться и все становиться очень грустно, поэтому непредсказанные переход убивает производительность напрочь. Есть кол. оценки отношения кол инструкций к мопам. до кор 1.4-1.5, начиная с кор засчет фьюжн почти 1-1 если компилятор хороший. У амд отношение изначально было не сильно больше 1 за счет более сложных мопов. ы
Можно заметить что здесь везде фу выполняют и ссе и обычные. В амд бульдозер это безобразие было решено прекратить, потому что операции ссе выполнялись медленно. Было решено разнести целочисленные и блоки с плав точки, но в пересчете на одно ядро они очень сильно тормозились фронтендом, и сильно тормозились операциями с плавающей точкой, хоть их блок и выполнял по 4 операции за такт.
То ли в нехалеме, то ли в сандибридже был сделан рывок и они стали выполнть до 8 операций за такт, что сейчас убивает амд.
В случае с повер пс декодер значительно проще, и довольно много фу, за счет чего в пересчете на такт он производителен, но у него хуже с бранч предикщн, за счет чего он в принципе страдает.
Что ж делается с результатами операций -- либо висят пока их не обработает завязанная на них операция стор. Буфера чистилища не очень большие, по 6-8 операций, и чуть ли не польностью ассоциативны, плюс для принтия решений планировщик может посмотерть на такт вперед.
В след раз сказ про память. 3 ноября, суббота, 12.30, сбор около 73.
Translation Lookahead Buffer
Встретим, когда будем говорить про страничную организацию памяти и этом всем. Операнды, которые в инструкциях, получили адреса натуальные, а выборку из памяти делаем по адресам физическим. В х86 механизм реализован аппаратно. Это ещё один кэш, обычно двух уровневый, в котором хранится соответствие старших битов натуральных адресов физическим. Важно, что бы те биты, адреса, что мы ищем в кэше, они укладывались в страницу, то есть в 12 бит. Нужно это для того, что вот этот тег преобразуется в тлб и сразу идет на поиск в кэш. То есть на самом деле есть ещё это преобразование из натурального в физический.
Nehalem и SandyBridge
Сначала хотел бы рассказать про две интел архитектуры. После того как интел выкинул нетберст, в предыдущей лекции отличия почти не упоминались, но они есть. нб оперирует трассами. Декодирование выполняет полностью, трассы как элемент переходов и так далее. Набор решений в сумме получился не очень удачный. Интел её тянула 5 лет, но в конце таки выбросила.
Эволюционно было PIII, P-M(стал получше декодер, появился моп-фьюжн), Core (PM-2), Core 2, Nehalem и SandyBridge. Изначально казалось, что нехалем позиционируется как попытка перейти к контроллерам памяти внутри процессора. В кор2 впервые появились 4 ядерные чипы, которые в принципе делались за счет 2 чипов на одной подложке. Два чипа, один субстрейт, по ногам тоже самое, увеличенное количество конденсаторов.
Схема
l2 кэш в корах был эксклюзивным.
Если вы делаете эксклюзивный кэш, то когда вы его себе забираете, у других он пропадает.
Одно из главных нововведений нехалем -- л3 кэш, причем он был инклюзив. Это позволило ещё немножко увеличить количество ядер. При этом л1-л2 синхронизировались.
Миграция процессов между ядрами в нехалеме стала менее болезненным мероприятием.
Контроллер памяти таки переехал на чип, в процессор. Задержки по досутпу в память сильно уменьшились. Эту архитектуру удалось раскочегарить до 10 ядер. Вестмеры по технологии 6+4, плюс гипертрединг, получалось 20 тредов с одного чипа.
Помимо этого в нехалеме было произведено довольно много микроархитектурных изменений. Для хоть сколько нибудь нормальной работы гипертрединга понадобилось увеличить количество всех ресурсов внутри ядра -- буфферов бранч предикшн, бранч хистори предикщн, добавилось эвристик. Увеличились размеры ROB, увеличилось количество операций в резервации, увеличился буффер на операции лоад и стор, что позволило минимизировать негативные эффекты, связанные с гипертредингом, и им стало реально пользоваться -- по сравнению с кор 2 не происходит деградации производительности. Была заменена шина, она стало более униформенной. Начиная с нехалемов появилась qpi (quick Path Interconnect). Она реально стала изображать из себя интерконнект -- роутинг, это всё. Супермикра на базе 4 сокетных вестмеров реализовали 80 ядерную конфигурацию. Это вызов в сторону паверовских смп машин, которые издревле этим славились.
Там была проприетарная мать, процессы ставились в датаборд, достаточно смешная конструкция (картриджи в пентиум 2, только гипертрофированные).
Санди бридж
Довольно много принципиальных изменений. Полностью перерисовали блок предсказаний переходов. Поменялись эвристики, теги большего размера. В чем-то хуже, в чем-то лучше.
Перенесли пси экспресс на чип, что решило проблему нехалемов с дма.
На многосокетных конфигурациях идет заметная деградация производительности, особенно на дешевых чипах.
Надо брать хеон е7_ 8 серии, по 4 тыщи долларов за штуку, тогда у вас все будет хорошо.
В санди бридж было сделано дальнейшее продвижение на пути поддержки большого количества ядер.
AVX увеличилась ширина регистра.
Лекция 4 (2012-11-03)
Устройство памяти
Сегодняшняя лекция будет про устройство памяти и взаимодействие процессора с ней. Начиная с видов яччеек памяти, какая бывает память.
Под памятью в первую очередь имеется в виду нечто с произвольным доступ и относительно невысокой задержкой, этим она отличается от систем хранения данных -- жестких дисков,м агнитных лент.
Память можно классифицировать следующим образом:
- volatile. Энергозависимая. Требует постоянного питания чтобы хранить данные.
- Non-volatile. Не энергозависимая. Но звезды сложились так, что у нее есть некоторые недостатки -- либо длительные задержки, либо ридонли, либо еще что-нибудь не очень хорошее. Одна из самых больших проблем -- сложность в производтсве по сравнению с volatile. Энергозависимая же память строится просто и быстро.
В дальнейшем будем преимущественно рассматривать энергозависимую память, а именно два вида -- SRAM и DRAM. Static random Access Memory, Dynamic Random access memory.
Начнем с SRAM, потому что она нам по большому счету знакома. Если намдать триггер с некоторыми ограничениями.
Так получилось, что сейчас все устроено на транзисторах. npn, pnp.
Принцип тот же самый.Управляя наличием дырок в перемычке вы управляете прохождением тока. Полевой транзистор. Полевые транзисторы компактные, поэтому они вытеснили все остальные. В отличие от биполярных транзисторов управляются напряжением, а биполярный транзистор прибор очень хитрый и нестабильный.
Вход и выход объединены. чтобы записать сначала поднимаем и опускаем отрицание BL, а потом поднимаем write enable. Практически как в защёлке по фронту, но объединили вход и выход.
В чем плюшки статической памяти
- она быстрая, насколько это возможно.
- интерфейс простой
- состояние дифференциально -- можно удвоить напряжение и использовать более мелкие транзисторы.
SRAM просто кусок логики, точно так же как и триггер. Хотя это довольно удобный и быстрый способ хранения данных, он имеет недостатки. Долго рисовали, но и в чипе это не так просто -- шесть транзисторов сделать, да еще и их соединить. статическая память считается дорогой, размещать её сложнее, она занимает больше места поэтому её нельзя делать много. Есть варианты статической памяти с 1-3-4-8-10 транзисторами различными. Увелечиние количества транзисторов для стабилизации питания, потому что когда вы открываете гейты происходит достаточно сильный скачок питания. Уменьшение тоже имеет ряд недостатков -- вы начинаете терять преимущества, которые предоставляет статическая память.
Есть более экономичные способы хранения данных. Например, динамическая память.
Динамическая память это конденсатор, который гейтится с транзистором.
Штамповать такие ячейки память значительно проще. Динамическая память всем хороша, но жутко неудобна, потому что для хранения использует просто разность потенциалов на конденсаторе. Если открываете гейт и течет ток -- есть что-то, не течёт -- нет. Если конденсатор слишком маленький, то ток он отдает недолго, небыстро, и вообще отдает его очень мало. В связи с этим для использования DRAM надо использовать усилители, после многократного чтения нужно обновлять ее состояние, кроме того конденсаторы маленькой емкости имеют свойство разряжать со временем и к ячейкам DRAM надо применять такую операцию как рефреш -- обновление. Чтение DRAM также получается небыстрой операцией.
В битве статической и динамической памяти побеждают обе. DRAM там где объем нужен больше чем скорость, SRAM там где скорость нужна больше чем объем. SRAM используется на чипе, DRAM -- как основная память, в которой хранятся данные, к оторым не нужен достаточно горячий доступ -- каждый так, десять, сто.
Динамическая память организуется довольно определенным образом. вы наверно слышали про DDR SDRAM с какой нибудь циферкой -- 1,2,3,4. S - synchronous, double data rate.
Как устроена SDRAM? Фактически оно организовано примерно так, как рассматривалось ранее -- мультиплексор и демультиплексор, только чуть сложнее. Современные чипы это уже несколько гигабит, поэтому организована она в виде набора двумерных массивов. В Row подается адрес. Массив обычно примерно квадратный. На пересечении стеик изображены ячейки памяти DRAM.
Идея в следующем. В виду того, что городить селектор и мультиплексор из 30 бит адреса в миллиард ячеек это плохая затея, используют такую конструкцию, снижающую разрядность адреса в два раза, и выбор строки и столбца происходит раздельно. Мы экономим на интерфейсе чипа и всего модуля памяти, мы экономим на размере мультиплексоров и демультиплексоров. Работает она следующим образом. Делается Row Adress Select.
Есть Addr, RAS (Raw Adress Strobe)и CAS(Column Adress Strobe). На спадающем фронте RAS считываем CAS и защелкивается как адрес, потом мы мигаем CAS и выбираем столбец, а дальше мы используем ещё один строб, из которого уже получаем данные свои.
Дальше для них последовал ряд оптимизаций, в частности Past Page Switch. Если мы читаем несколько столбцов, мы можем не делать заново выбор строки -- Fast Page Mode (FPM) DRAM. EDO DRAM умела подавать следующую команду пока ещё идут данные. Схема.
Ras 2 CAS latency, CAS latency, precharge, command rate, actively precharge-- характеристики чипа.
Следующим важным этапом было Burst EDO RAM. Позволяла получать данные бёрстами -- происходил автоинкремент адреса и получали до 4 блоков данных. Почему блоков? Ширина этого набор сигналов она в принципе 4-8-16 бит, чаще всего 4 или 8. Таких матриц не одна, а несколько и читаете вы с них фактически параллельно.
Дальше появилась SDRAM, которая начала нормально тактироваться. Асинхронный DRAM в чем проблема была -- рефреш был асинхронный. А у синхронной DRAM команды рефреша шли общим потоком.
СDRAM. Частота от 100 до 200 мегагерц, то есть можно было 8-1600 мегабайт, хотя реально на 200 мегагерц не раскачивали, обычно 100-133.
Дальше появилось то самое DDR. Идея в том, что у нас появляется некий буфер. А дальше вы отдаете данные по двум фронтам.
В DDR2 удвоили количество бит которые в буффере и удвоили частоту. В DDR3 ещё тоже самое -- буффер на 8 бит и отдают на увеличенной частоте по двум фронтам.
Частота работы конструкции за 10-15 лет не сильно поменялась -- там все равно конденсаторы и вместо того, чтобы его разогнать его просто уменьшают -- мы сохраняем частотоу но запихиваем большее количество ячеек, а с больше ячеек мы можем отдавать их больше за раз за счет параллелизма.
Проблема в том, что шина тактируется по прежнему. И, чем выше частота, тем выше задержки в такт, что не лучшим образом влияет на производительность DRAM. Поэтому сейчас активно начинают использовать многоканальную память.
Precharge чтобы вам сменить строку тоже нужно проделать некую операцию -- рас пречардж, фактически сообщить новое сотояние чобы ячейка выбралась. Это занимает неокторое время и его можно сгладить за счет посыла пречердж пока ещё идет берст данных, который к слову сейчас уже не 4, а больше, зачастую.
Так устроен интерфейс самого чипа DRAM. В модуле DRAM этих чипов находитс несколько. Ширина интерфейса 64 бита или 72. На модуле может быть несколько так называемых ранков, которые могут выбираться сигналом чипселект. Может быть один ранк, может больше. n ranks, m chips, each of them w bits wide. Magic formula w*m = n*64. идея в том, что у вас есть н ранков, каждый из которых может отдавать 64 бита, таким образом они собраны в м чипов, каждый из которых отдает по в битов. Сермяжная суть этой формулы в том, что она позволяет понять насколько вы можете вообще ра??шивать доступ памяти применительно к конкретным модулям. w = 4/8/16. 4 for ECC (9 чипов, 8 данные, в 9 error correction code).
По поводу контроллера. Контроллер можно делать многоканальным что позволяет увеличить количество считываемых ранков. Первые реализации многоканальных контроллеров делали такую штуку как ganging. Делали всегда выборку по строке и столбцу. Позволяло делать проще логику контроллера, использовать меньшее колиичество дорожек, но впоследствии от этого отказались и каналы теперь работают независимо.
По поводу DDR3. Начиная с него сняли ограничения на сброс. Тяжесть DDR2 была в том,что изначально синхроноус DRAM предполагает что все сигналы призжають более менее одновременно. На 100 мгц разбегание дорожек ещё можно выдержать, оно окло милимметра. На DDR2 стало понятно, что количество доржек растет, а требования к разводке все также усугубляются. Разбегание доржки становится дефакто в 2 раза меньше. В DDR3 сняли ограничение и сихронизация ушла частично на следующий уровень поэтому в том числе там были более высокие задержки, но разводить стало челоевечней.
JEDEC
На сегодня уже сотни гигабайт в секунду.
Далее, про кэширование. В принципе, кэширование было в каокй-то мере рассмотрено на предыдущей лекции. Кэширование инструкций и кэширование данных идеологически ничем не отличаются.
Кэширование L1, L2, L3.
L1 идет на ядро, имеет размер сейчас порядка 32 килобайт, 4-8 ассоциативны. Все ли помнят что такое ассоциативность? Кэшировать отдельный байты очень плохо, поэтому в кэше хранятся обычно строки по 32/64 байта. За счет того, что они выровнены -- младшие 6 бит адреса вам говорят где брать ячейку в строке. Но надо ещё найти строку. Можно было бы искать по всем оставшимся битам адреса (назвав их тег) и за одно сравнение быстренько находить нужную линейку кэша. Но возникает загвоздка -- параллельное сравнение требует количество транзисторов и проводов очень большое при росте уровня кэша. Развести 20 000 дорожек и разместить 20000 транзисторов это логически не очень простая задача, которая очень плохо ршается. Это будет полная ассоциативность.
Есть подход с точностью до противоположного. Проверяем совпали биты или нет, если не совпали загружаем из памяти. Эффективность такого решения не очень высокая, потому что вы начинаете выкидывать строки,которые отстоят на 2^(s+6) байт, что может быть плохо с точки зренияя кэшмиссов если атомы наших данных толще. Поэтому строки объединяются в блоки по 4-8. Таким образом будут сначала индексироваться блок, а потом в нем полноассоциативно искать нужный адрес, но делать это уже среди 4-8 строк.
4-ассоциативного кэша достаточно, чтобы сгладить негативные эффекты алиасинга и уменшить кэш миссы в 2.5-3 раза. В L1 виртуальная адресация. L2 кэш 1-4 мегабайта, ассоциативность 4-16, физическая адресация. с виртуальной адресацией при смене контекста кэш теряется. В L2 может влезать несколько конетксов, к тому же он медленный -- 10-20 тактов и это вполне сглаживает преобразование виртуального адреса в физический. L2 кэш шарится между небольшим количеством ядер, например двумя. L2 это просто большой кэш, но все так же у ядра.
L3 сейчас уже у всех. В x86 появился первым у амд, до этого был у поверов и спарков. У итаниумов он был одним из способв компенсации недостатков архитектуры -- ядер было всего ничего, но зато они толстые. L3 per chip.
Инфраструктура кэшей позволяет сглаживать доступ в память.
Переходим к адресации.
В подавляющем большинстве современных архитектру используется странично-сегоментная адресация памяти.
Есть виртуал адрес и физикал адрес. Отображение между ними для организации всех этих современных плюшек -- многопроцессорность, защищенный режим, должен выполняться, и он выполняется но снекотрой гранулярностью. Размер гранулы -- страница. Кроме того, это отображение выполняется аппаратно. Занимается этим блок memory management unit. Ему задется некоторая информация о том, что у нас есть неокторое отображение и дальше он может по этой информации выполнять преобразование. Как оно происходит.
Есть виртуальный адрес, он разбиивается на две части -- адрес внутри страницы и индекс. И есть некая таблица в памяти,на которую указывает некоторый внутренний регистр. Смотрим в ней по индексу, получили указатель на физический адрес. Размер этой таблицы будет экспонентой от количества бит. Такая простая схема используется только для очень больших страниц -- 4 мегабайта, например, тогда для 32-бит адресов там будет 10 бит.Но далеко не всегда удобно оперировать такими страницами. Обычно используются таблицы 4 килобайта. Тогда для 32 разрядной архитектуры на индекс остается 20 бит. Тогда вы разбиваете адрес на несколько частей и делаете косвенную адресацию. Работает так -- вы берете старшие несколько бит адреса, индесируете таблицу первымнабором битов, там адрес следующей таблицы, которая индексируется следующим набором битов и так далее, и на 4ой итерации вы находите префикс который так долго ждали. Все хорошо, но получаются 4 последовательных операций.
Сейчас используется 4 уровня, ищется по 34 битам. размеры наборов битов по 9 бит. Каждая таблица 512 записей, общей мощностью 4 килобайта.
4 последовательных поиска -- штука не очень хорошая. Чтобы её сгладить есть такая штука как тлб, которая кэширует результаты этих преобразований. Она тоже многоуровневая, как кэши. по крайней мере у интела она полносвязная. Там 128 или 256 записей, и разводится она очень тяжко, потому что там реально нужна полная ассоциативность. Есть тлб 2 уровня, у которой уже есть какая-то ассоцитивность 4 или 8. Длина строки 32 бита, там напиханы индексы и флаги.
Пае увеличло размер записи в 32 бит до 64. когда это появилось это был 96, когда появился пентиум про. Казалось, выгоды никаккой нету. 20 бит чудесно укладывались в три уровня. Пае добавил 4 уровень и сделал размеры записей в два раза больше. Тогда 8-64 гб памяти на серверах было не очень распространено на x86.
Вообще говоря, различные регионы памяти могут использоваться различными способами. Иногда они отображаются на чипы DRAM как есть, а иногда нет, а отображаться на памятьвидео устройства, или PCI експресс устройства, или просто как то мапится могут. Все эти особенности конфигурируются через memory type range reisters, там же конфигурируется способ использования данного региона. Например, можно сккзать, что операции записи можно кэшировать и послыать более оптимальным способом (выровненными лингецками по 64 байта). В основном нужен для PCI експресс устройств чтобы указать особенности семантики -- можно ли кэшировать чтение, выполнять чтение без побочных эффектов, или противоположную штуку, что кэшировать операции с этой памятью вообще нельзя, например если туда выведены какие-то условные ио порты(хотя они вообще отдельно) ну или какому-то устройству надо сразу и точно получать те операции.
Кэши бывают двух типов write-through и write-back. Это режи мработы кэша. Сквозная запись -- у вас есть линейка в кэше, вы ее обновляете -- в память сразу идет запись. райт бэк просто помечает линейку, что он грязная, и при выбрасывании из кэша она записывается. Райт бэк лучше с точки зрения производительности но порождает доп проблемы с когерентностью. Чтобы их решать есть механизм MESI Modified Exclusive Shares Invariant -- стейт машина которая определяет как происходит переход между этими 4 состояниями кэша -- модифайд, эксклюзив, шаред, инвэлид. И действия -- лоад, стор и ещё два. Если разрисовывать там грустная таблица переходов. Идея в том, что это прописывается и жизнь сразу становится проще и понятней. Начиная с нехалемов используется MESIF, когда необходима полная свзяность между кэшами -- если модифицируете шаред ячейку, то ее надо сразу писать, а Forward говорит что она уже модифицирована и не вызывает дополнительных пересылок. Request for ownership надо делать если для шаред вы хотите модифицировать. Рфо станет инвэлид посл еэтого вы ее делаете модифайд.
DMA --direct memory access, когда устройства могут работать с памятью напрямую, как ядра. Будем говорить дальше, когда говорить про переферию.
IOMMU. как можно было заметить мму -- чатсь процессора. А переферийные устройства ею нея влются и ничего не знают про отображение виртуальных адресов в физические. Поэтому для устройств не работают все механизмы защиты памяти. Берете файрвайр и пишете/читаете в любое место памяти. И ничего с этим не сделаешь. помимо файрвайр такими особенностями обладает PCI Express. Хотя сейчас наконец-то в x86 появился иомму, когда у вас есть дополнительный чип перед мемори контроллером который занимается отображением тех адресов, которые использует железка в адреса физической памяти. У интела это называется очень красиво VTd, но в реальности это все попытка реализовать IOMMU. Реалищуется как и мму,только конфигурировать его сложнее потому тчо находится он дальше от процессора.
e820 эт оназвание такой микросхемы, было. Сейчас это просто некий интерфейс который позволяет конфигурировать те регионы которые доступны/или недоступны.
Full buffer. Это способ переложить часть работы мемори контроллера на модуль памяти. он фактически сам выдает команды чтения записи и выдает уже просто данные. таким образом вы забарываете проблему что вы не можете повесить много модулей памяти на одну шину. DDR2 240 дорожек. 480 ног это дофига.
У современных x86 их всего чуть больше 2000.
У IBM z10 было 8765 ног, они собиралось в MCM по 5 + 2 storage контроллера, и ящики чипов памяти. стоило это 10 миллионов долларов, было совместимо с систем 360 и было майнфреймом. Вот это реальная архитектура не то что инетл, который уже дропнул реальный режим, который всего-то 30 лет назад появился.
Поскольку часть мозга на чипе работает быстрее, все становится лучше, но чипы становятся дороже и сложнее в производстве и поэтому отстают от тупых чипов.
COntent Addressable Memory. cam и tcam часто используются в чипах роутеров, когда у вас стоит задача по IP адресу установить кому посылать пакет. Т она вообще от троичности. -- расширение когда у вас надо длеать поиск по маске -- помимо ключа ещё указывается маска по которой надо сравнивать. dest ip, prefix+mask. То есть не столько для поиска сколько уже для применеия правил. Соответственно отличается оно тем что сверяютс ятольк те Destination IP биты, у которых маска единица. У маршрутизаторов приор иттет имеют те префиксы, которые длиннее. В случае с памятью приоритет имеют те записи,к оторые лежат раньше в памяти соответственно роутеры просто упорядочивают эти префиксы по длине.
Лекция 5 (2012-11-12)
Взаимодействие с периферией. PCIe.
Небольшая перестановка в плане курса.
Сегодняшняя тема -- периферия.
На предыдущей лекции был рассказ про память. Перескажем ее минут за 5.
Различают
- энергозависимую память
- SRAM ячейки на транзисторах
- DRAM отвратительный по интерфейсу способ, но хорош тем, что там только один конденсатор и один транзистор. Конденсатор может накапливать заряд, его там можно удреживать, а при появлении напряжения его разрядить. Отсюда недостатки - медленное, надо периодически перезаряжать. Был расмотрен интерфейс взаимодействия с драм памятью, в котором адресация выполняется по строкам и столбцам. Память драм представлена набором двумерных массивов (4-8-16), что позволяет считывать несколько бит параллельно. Были рассмотрены
- FPM DRAM
- (B)EDO DRAM
- DDRx SDRAM - отдает биты на удвоенной (х2, х4, х8) эффективной частоте. Связано с тем, что этот массив ячеек выгодно не разгонять, а увеличивать объемы, а скорость увеличивать за счет буферизации. Поэтому с каждым поколением DDR растет лэтенси в тактах и способствует работе с более крупными блоками.
- энергонезависимую память
Было рассмотрено взаимодействие процессора и памяти. Кэши инструкций. Блок MMU -- аппаратная поддержка виртуальной адресации (преобразование виртуальных адресов в физические). Чтобы это преобразование работало сколь либо эффективно, т.к. это страничная организация памяти, при адресации нескольких гигабайт страниц миллионы, хранение в виде линейной структуры не способствует эффективности поиска, поэтому используется иерархическая структура. Чтобы это работало эффективно используется TLB -- это тот же кэш, но обычно с полной ассоциативностью, его так же может быть несколько уровней.
Перифeрия
Нам бы хорошо бы взаимодействовать с внешним миром.
Есть периферийный устройства. Взаимодействие происходит различными способами
- memory mapped io чтение и запись в некие проассоциированные виртуальные порты
- PIO/ DMA -- некий способ отображать память устройств в адресное пространство процессора, а для устройств механизм изменения памяти хоста. Хост это связка процессор-память, устройство -- некое периферийное устройство.
Все упирается в физический уровень
- последовательные протоколы. Малое количество управляющих сигнальных линий для передачи данных, передача каким-либо образом сериализуется и реализуется какой-либо высокоуровневый протокол.
- Пример -- интерфейс JTAG, IEEE1149, служит преимущественно для чтения и записи внутренних регистров некоего устройства, в основном в отладочных целях.
В нем есть несколько линий. Тригеры соединяются в цепочку, и есть комбинаторная обвязка, включающая его в определенном режиме. Связываете такие ячейки набором триггеров, Все регистры объединяете вместе, три цепочки по несколько сотен тысяч бит, дальше путем тактирования можете продвигать значения этих бит. Чудесный интерфейс, в принципе один провод, на самом деле нет. Позволяет не только считывать, но и записывать значения в регистры. Позволяет остановить устройство, считать значения, понять что происходит (попытаться) потом записать и дальше. Хотя не все современные устройства позволяет так просто остановить клок. Например, PCI Express (??). Схема.- I^2C. Inter Integrated circuit. Интерфейс взаимодействия между интегральными схемами. Всего два сигнала SCL(clock) и SDA(data).
Устройства разделяются на мастер и слейв. Кодирвание за счет взаимного положения поднимаюшихся и опускающихся фронтов. Схема. Идея в том, что за счет взаимного расположения фронтов клока и данных, например если клок хай, то это старт условие с которого начинается передача данных. Довольно простая кодировка для передачи битов. Формат простой -- есть старт условие, адрес, бит чтения/записи, бит A, Data, A, P. Идея в том, что управляя этими сигналами, то мастер, то слейв померенно, мастер говорит что передает некий адрес, чтение запись и ждет подтверждения. Подтверждение делается так -- поднять Data флаг. Если у нас например запись, то потом у нас идут данные, 8 бит, после каждого байта ожидается подтверждение. Чтение аналогично. Всего две линии, но за счет кодировки можем передавать со скоростью больше 100 КГц. Прост в разводке. - параллельные протоколы. Обычно ориентированы на большое количество линий, доп. информация о разборе сообщений может идти доп. сигнальными линиями. Интерфейс с памятью -- один из видов параллельного протокола. DRAM параллельный, доп. линии говорят читаем мы или записываем, и вообще всякое.
- В противоположность I^2C в PowerPC используется протокол DCR. Там сигналов -- read, write, privilege, data [0..31], addr[0..31], master[0..31]. Этот интерфейс используется, смешно сказать, для чтения регистров. Но в нем можно видеть, что там сотни линий. Но в принципе все просто, принимаешь соответствуюшие битики и куда надо посылаешь. Нет никакой комбинаторной сложности в передаче, потом ожиданий, итд.
Параллельные интерфейсы были популярны по двум причинам
- проще логика разводки
- повышение скорости с повышением количества линий
Но возникала проблема -- выравнивание дорожек. 8 выровнять ещё можно, то 100 уже печально, особенно если разные устройства висят на одной шине. Пример перехода от грустно к чуть менее грустно это эволюция от ISA до PCI Express. В х86 это основной интерфейс, подключенный непосредственно к процессору. Их может быть несколько, последовательный порт, параллельный порт, но все остальные интерфейсы глобально и надежно периферия кард интерконнект. PCI (Perepherical Card Interconnect). До этого были (E) ISA. Первоначально ISA Это Industrial Standart ARchitecture. Была 8-битная шина, устройства подключались последовательно, позволяли передавать данные. В основном управлялось портами ввода-вывода. Потом появилось возможность управления, потом стала 16-битной, но это все совсем страшное легаси, хотя и до сих пор встречается. А потом появилась 32-разрядная PCI. Схема. В стандарте можно было иметь до 8 шин на каждой по 10 устройств. Много устройств на одной шине -- проводов меньше, но работает со скоростью самого медленного устройства. Выход несколько шин, но это требует пропорционального количества проводов.
Оснавная идея шины PCI достаточно простая. Хотим преимущественно читать или писать. Есть мастер, есть таргет, мастер может читать или передавать данные бёрстами. Шина 32-разрядная. Есть 32 бита данных, есть 32 бита на адрес и есть пачка служебных сигналов. Схема. Сигналы addr [0..31], data[0..31], clk, trdy, irdy, select, frame, devsel, jtag [0..4], etc. Шина PCI жила несколько дольше чем хотелось бы. Есть некий арбитр, который говорит, ты можешь что-то поделать (выставляется сигнал REQ) Пары req gnt заводились на каждый арбитр (каждое устройство) независимо. Когда устройство хотело что-то передать оно посылало REQ, потом поднимало бит адреса, получало сигнал, каждый знал свой диапазон адресов и соответственно отвечал, после чего начиналась собственно передача. Тактировалось по внешнему клоку. Клок мог иметь довольно произвольную частоту. Тот кто им управлял мог его полностью остановить. Изначально диапазон был 16-33Мгц до полной остановки, потом ограничение снизу сняли. Это частота и ширина 32 бита давали не очень большую скорость. Это повлекло расширение PCI -- до 64 бит, потом ещё было расширение до 66 мегагерц, в PCIx ещё в 2 раза частоту разогнали, что давало аж до Гб/сек, но это все было дорого. Поэтому произошел переход на шину PCI Express, тогда же примерно произошел переход от параллельного ата к последовательному.
PCIe
Достаточно интересный стандарт -- PCI Express. 3-я версия около 800 страниц. У стандарта PCI все было скромнее -- 200-300 страниц. PCI во многом определяет электромеханические особенности работы, это довольно значительная часть протокола. В противоположность этому в стандарте PCI экспресс гораздо больше уходит на логику.
В PCIe несколько лэйеров
- TLP транзакций
- DLLP -- как работает точка-точка.
- link layer инициализация линка, логика среды передачи данных. Два подуровня -- логический и физический.
У PCIe 3 версии
- PCIe gen1 - 2,5GT/s -- гигатрансферы в секунду. В реале 2 гигабита на линию(??). Стандарт поддерживает передачу по нескольким лэйнам.
- PCIe gen2 5 GT/s
- PCIe gen3 8 GT/s -- улучшили схему кодирования, вместо 8/10 стали использовать основанную на стейт машине схему 128/130. 125 пикосекунд.
Это очень красивые чиселки. Если у вас 16 лэйнов, то 16*8 это 16 гигабайт в секунду в одну сторону, очень много. Скоро ещё удвоят.
Если говорить более предметно, то PCIe определяет некоторую топологию устройств PCIe root complex -- некое устройство, с одной стороны корень иерархии, с другой стороны взаимодействует с хостом, преимущественно с его памятью. Далее топология имеет древовидную структуру, есть энд-пойнт девайсы, есть свитчи, есть всякие бриджи на PCI, которые могут подключать PCI устройства и обеспечивать интероперабельность между PCIe и PCI устройствами.
Есть некие сообщения которыми устройства обмениваются между собой. Чаще всего ендпойнт обмениваетс с хостом, или еп с еп. Есть ещё отдельно флоуконтрол.
Продолжение идеи PCI что отдельно выполняются запись и чтение. Посылается сообщение что происходит операция с такой то памятью. Сообщения имеют размер кратный DWORD (32 Бита). Есть префикс для служебной информации. Основная идея что у нас есть хедер, который имеет размер 2 дворда, определяет тип и разлиные характеристики, например таргет. В зависимости от типа определяется формат и размер заголовка.
Бывают операции, операций довольно много. Можно выделить 4 блока
- Memory. Операции с памятью. Чтение, запись, атомарные операции (какие) (начиная с стандарта 2.1). В принципе рут комплекс должен уметь говорить, что он умеет.
- IO. Это такое легаси. PCIe это такой инновационный протокол, но вот есть PCI железка, хочется к ней прикрутить PCIe, но не перекореживать всю логику, потому что ее может быть много разной. Есть два способа возбуждения сигнальных интерраптов -- вне сигнальной шины, использует выделенные сигналы, отдельные 4 дорожки, которые можно поднять, у неё возбуждалось желание, процессор поднимал, что поднялось, а потом устройство могло опустить. Это механизм при масщтабируемости стал печальным, поэтому перешли на другой -- специального вида сообщения, запись в определенный участок памяти, который специальным образом отмаплен и обрабатывается хостом. Легаси устройства могут многое, до сих пор присутствуют уже в третьей версии стандарта и не собираются уходить. При разработке новых устройств использовать эти механизмы не рекомендуется.
- Message. Используется для всяких сообщений -- прерывания, о питании, вендор-специфик месседж.
- Config. Работа с конфигурационным пространстов. Появилось ещё в PCI. У каждого устройства подразумевается некое адресное пространство, в котором это устройство всяко разно описано -- вендор ид, девайс ид, класс, фанкшн. Схема. Может поддерживать разные фичи, например ссылка на следующий экстеншн. Таким образом устройство может декларировать что поддерживает M?SI. Ещё устройство может декларироать, что у него есть некоторые участки памяти, отражающиеся в его. Базовые адресные регистры -- 4 младщих бит говорят тип, потом несколько бит захардварены в ноль, остальные просто захардварены. Чтобы понять его размер туда писали единички и их считали (?). Туда писался ио регион, ???. Далее всякие настройки питания, дальше шли всякие фичи. Всякие капабилити, например, максимальный размер пейлоада и запроса на чтение. Это характеристика ограничивающая как рут комплекс так и девайсы. У девайсов есть размер буффера, у подсистемы тоже есть ограничение.
В PCIe появилось более продвинутое Message Signal Interupr -- MSIx, проверяет до 4 тысяч. Немножко разный формат сообщений.
На уровне Transation Layer Protocol определены правила формирования транзакций, возможности по реордерингу, что делать если вы не умеет обрабатывать такой тип. Не одна сотня страниц посвящена тому, как рут комплекс должен обрабатывать разные типы сообщений.
На Datlink Layer Protocol добавляется чексумма транзакции (32 бита в концу) и 16 бит в начале -- номер транзакции для флоп контролл(?). Ожидается, что на этом уровне сообщения идут последовательно, если после н приходит н+2 вы по обратному каналу это сообщаете. Идея в том, что определяется закон обратной доставки и определяются кредиты для флопп контролл. В конце сообщается сколько места в буфере осталось под головы и вообще. Обеспечиваете, то не произойдет денайал оф сервис, а другая сторона будет ждать пока не придет достаточно кредитов чтобы продолжит передачу.
TLP добавляет маркеры конца и начала транзакций. Определяет, что должно происходить когда ничего не предается, что-то передается. В этом начинаются отличия ген3, изза другого кодирования на малых транзакциях может быть чуть похоже.
На верхнем уровне линк лэйера у вас есть несколько лэйнов и вам надо передать, например байт. Вы его раскладываете по лэйнам, забиваете лишнии, итд.
На этом же уровне вводится стейт машина. Есть начальное состояние, если появляется вольтаж, начинаете посылать синхропакеты, потом 2 конфиг пакета, потом линк поднялся. ???.
Это был сумбурный рассказ про PCIe. Что можно подчеркнуть. На данный момент это один из наиболее развитых способов передачи данных в малых и средних эвм, особенно в х86, а так же немного в паверах и спарках, хотя там и очень много интел специфичного, особенно в порядке байт. Основным конкурентом является гипертранспорт, который немножко умер, хотя по характеристикам и плюс-минус сопоставим.
В следующий раз про периферийные интерфейсы -- usb, firewire, sata.
Лекция 6 (2012-11-19)
PCIe, USB, FireWire
Сегодня про один из насущных примеров периферии -- USB. Universal Serial Bus. Пример того, как интерфейсы делать не надо. Но, несмотря на сложность, низкую производительность и прочие негативные факторы, заложенные by design, он был достаточно популярен, потому что был прост в использовании и накладывал мало ограничений на устройства -- как на периферийные, так и на хост-контроллеры. Вторая версия вышла в 2000 году, она декларировала пропускную способность до 480 мегабит в секунду, реально тогда достигать такой производительности было дорого. В связи с этим в специфик был сделан ряд допущений, которые позволяли реализовать compliant hardware, которое не удовлетворяло скоростным характеристикам и требования там были попроще.
Начну с того, что напомню про то, как устроен PCIe -- пример того, как периферийные интерфейсы делать возможно надо. В нем достаточно большое количество legacy, но если рассматривать только ту часть, которая касается совместимых устройств, а не legacy -- то там достаточно все аккуратненько.
PCIe
Рут комплекс. У каждого устройства в дереве есть даунстримные порты и один апстримный порт (если это свитч). Из этой древовидной топологии следует адресация и всё такое. Каждому устройству сопоставляются свои диапазоны адресного пространства. Если приходит транзакция сверху и видишь, что она твоя -- направляешь вниз, иначе выбрасываешь.
Адресные пространства указываются в адресных регистрах (BAR).
Транзакции устройствами могут посылаться в любой момент. Остановить устройства в этом начинании может исключительно flow control, который считается по нескольким аспектам. Идея в том, что есть несколько лимитов(буферов для временного хранения транзакций). Устройство складирует доступные лимиты -- отдельно на количество транзакций, отдельно на общий объем. Эти размеры вычисляются независимо по каждому линку. Информация о том, что появилось место, передается либо как часть пакетов, либо отдельным пакетом, если нет встречного трафика. Endpoints могут посылать транзакции сами, даже друг другу, но чаще всего общаются с хостом. Два ендпойнта при общении друг с другом должны оба знать об общении.
GPUDirect от NVIDIA -- либо GPU могут обмениваться друг с другом по PCIe (не через отдельный мост, как в случае с SLI), так могут обмениваться по PCIe с сетевым интерфейсом. Чаще всего рассматривается в связке с Infiniband. Но это должна поддерживать и видеокарточка, и сетевой интерфейс.
Тот факт, что оно так устроено позволяет достигать на любом линке максимальной пропускной способности, немого снижающейся за счет кодирования и выравнивания лейнов. Если не рассматривать 32 лейна, то на оверхеды уходит 3-4%.
Universal Serial Bus
PCIe тоже в некотором смысле последовательный -- в том, что передача битов по каждому лейну идет последовательно. Но в отличие от PCIe, где на один лейн отводятся честные 2 дифпары, чтобы был у нас дуплекс, в USB дифпара одна. Там 4 сигнала -- напряжение, дифпара, земля.
USB хост, к которому подключаются хабы, к которому подключаются function. Одно устройство может предоставлять несколько функций, и чтобы не городить виртуальный свитч было придумано такое устройство. Свитч -- недешёвая штука с точки зрения реализациии. PCIe контроллер это несколько сотен тысяч транзисторов. PCIe свитч на 3-4 линка это миллион транзисторов, и свитчу нужны ещё буфера и так далее. Наличие функций позволяет всего этого безобразия избежать. В случае USB, если у вас compound device, который может иметь несколько функций -- например, клавиатура с трекпойнтом, то вы должны будете реализовать таки да хаб, который есть unremovable функцией и оно реализуется именно так и никак иначе. Это USB 2.0. В USB 3.0 был сделан ряд довольно значимых изменений, но на общую схему он не повлиял.
В USB 3.0 стало только хуже. В теории можно добиться того, что вам USB устройство отдает что-нибудь похожее на 60 мегабайт в секунду. В USB 3.0, при заявленной скорости 5 гигатранзакций в секунду, максимальная теоретически достижимая пропускная способность 400 мегабайт в секунду.
Это строго дерево, дерево можно выстроить по уровням, уровней не больше 7. Всегда есть первый уровень -- хост контроллер и скорее всего у вас будут хабы. Дальше у вас первые два уровня есть, в ограничение уровнями упереться сложно, но то, что два уровня съеты почти всегда, несколько печально.
Самое страшное в USB это то, что это polled шина. То есть, все операции изначально issued by HC. Функция не может что-то послать без запроса хост контроллера. Казалось бы есть устройства, который могут захотеть что-то посылать, как им работать? Про это дальше.
Основных версий стандарта 4:
- 1.0 lowspeed 1996 1.5 Mb
- 1.1 fullspeed 1998 12
- 2.0 highspeed 200? 480
- 3.0 superspeed 201? 5000.
Есть возможность доставать то ли до 10 ампер, то ли 100 Ватт. Везде идет питание 5 вольт. По стандарту первых трех версий там может быть не больше полуампера. Но, поскольку USB 3.0 появлялся примерно одновременно с Thunderbolt, и у него та же заявленная пропускная способность. Потому что Thunderbolt расширение PCIe для внешней периферии.
Содержательно в стандарте USB определяется три уровня.
- client software - function
- driver - endpoint
- hc - bus
Есть прикладное ПО, которое общается с функциями посредством доставляемого неопределенного в стандарте программного интерфейса. Есть некая абстракция, которая определяется на уровне client software. Библиотека которая реализует этот интерфейс взаимодействует с USB драйвером. Client software генерирует IRP. Эти IRP передаются драйверу,а драйвер на основании них генерирует трансфер. Трансфер на физическом уровне.
Определяется несколько видов. Соответственно устройство общается с хостом посредством пайпов. То есть, все взаимодействия которые происходят, они на самом деле происходят посредством пайпов. Это такая вот FIFO абстракция реализованная в железе. В USB 2.0 пайпов 4 вида:
- configuratuinal. У девайса всегда есть хотя бы один конфигурейшн пайп, который считается сконфигурированным изначально -- как с ним работать.
- interrupt
- isochronous
- bulk
При подключении устройства хаб вообще сообщает, что у него какие-то порты и их соcтояние. Когда подключаем устройство, он поднимает соответствующий бит в конфигурационном пространстве данного порта, хост контроллер это замечает и конфигурирует это новое устройство. Если подключили хаб, то все происходит рекурсивно. Обратно ситуация при отключении -- если что-то отключается, то хаб это замечает сам, выставляет нолик соответствующему порту, после чего хост контроллер это замечает и делает необходимое для удаления устройства. В связи с этим важный аспект, то что вообще одной из задачей драйвера хост контроллера является постоянное что-то всех устройств находящихся на шине. Хост контроллер занимается тем, что периодически опрашивает, предоставляет возможность дать всем интерфейсам. Всем ендпойнтам, или наоборот читает, что с них, в случае необходимости энумерации он читает с них, делает запросы всем хабам.
Сама последовательность состоит из нескольких сообщений. Сначала HC посылает запрос по некоему адресу. Устройство видит запрос, смотрит, что совпадает адрес, и если готов принимать данные, то там есть два направления in и out, чудесное свойство и по завершению транзакции посылается acknowledgement. Это вариант взаимодействия в 3 сообщения, бывает ещё в 4. Если у нас что-то, то говорит ура и получает acknowledgement, что все принято, или что все поломалось по дороге, либо если это транзакция что-то, то о ней говорят, что устройство утверждает, что может ее принять, транзакция уходит, устройство ее принимает.
Как я уже сказал при конфигурации появляется набор пайпов. Как эти пайпы работают -- собственно позволяют как-то перекачивать данные, а именно.
Пайп вида configuration и соответствующие транзакции доставляются как только, так сразу. У них есть гарантированная полоса опускания в 10 процентов от фрейма. Все время передачи разделяется на фреймы, в случае 1.0 это 1 миллисекнуда, в случае 2.0 это 125 микросекунд -- так называемые микрофреймы. В рамках этого фрейма происходит локация времени для различных видов транзакций.
Транзакции вида interrupt устроены следующим образом. У них есть некие ограничения на пропускную способность, то есть они "вот опрашивай меня с такой то частотой, я буду тебе посылать сообщения такого то размера". Частота может варьироваться от раза в микрофрейм до 255 милисекунд или до 4 секунд. И тогда хост контроллер с такой периодичностью будет посылать запросы к данной функции на предмет "а есть чего?". Такой вид пайпа обычно используется для устройств ввода -- мыши ли клавиатуры. Обычно, они могут запросить больше пропускной способности, но в обмен на это им не будет предоставлена возможность retransfer если случилась ошибка передачи сообщения. Механизм достаточно высокоскоростной шины, но нифига не отказоустойчивой. Регулируется точно также -- размер транзакции в микрофрейм и частота опроса. Обычно используется во всяком аудио-видео (asynchronous?).
Bulk транзакции -- передачи, которые могут ходить в свободное время. У них низший приоритет. Устройство, если хочет что-нибудь послать, будет когда-нибудь опрошено, но никаких гарантий когда -- нет.
Когда эти пайпы конфигурируются устройство запрашивает пайп определенного размера -- "8 пайпов, каждый из которых пусть меня опрашивает каждую милисекунду а я ему буду давать 512 байт". HC считает, что он может устройству дать, и, если пайпов не хватает, то конфигурация может пройти не очень успешно.
Есть ещё аспект размера буферов. У вас должно хватать буферов на то, что эти транзакции могли идти нужным потоком. Задержки и физические ограничения должны учитываться HC.
Тактировнаие. В USB есть несколько клоков. Одни из них больше пользовательские -- больше для software, тактируется interrupt, лейну когда посылать очередные IRP. Третий клок, которым тактируется сама шина USB на 1.8 килогерца. Этот клок встроен в способ передачи данных, там использует NRZI. Есть два состояния и между ними происходит переключение. За счет переключения на каждом такте добиваетесь того, что этот клок всегда есть.
Можно заметить здесь в отличие от PCIe или firewire нет никакого DMA. Устройства обмениваются транзакциями. Это хорошо с точки зрения безопасности, с другой стороны не очень быстро может оказаться, потому что весь трафик надо обрабатывать ПО, и вы имеет чудесную нагрузку на процессор. В свое время это было еще одним ограничением на 480 мегабит. Это сейчас USB ест 10-15 процентов, а тогда это могло быть гораздо больше.
В USB 3.0 кажется появился DMA, но от этого сильно легче не стало.
Еще расскажу про firewire.
Firewire
Примерно тогда же, в конце 90 - начале 2000 появилась шина firewire IEEE1394. Всего было несколько редакций, прежде чем оно почило в бозе. Довольно интересно -- там были варианты с 6 и 9 контактными разъемами, да, 6 контактов соответственно без питания, 9 с питанием. Скорости были что-то типа 400/800/1600/3200, но в реальности даже 800 вы наверно не видели, если только у вас нет какого-нибудь макбука. Отличие от USB HC .. Сам стандарт в отличие USB стандарт firewire это стандарт IEEE и чтобы заменить его копию надо вступить в консорциум и платить деньги -- небольшие, около 200 баксов в год, но тем не менее. Есть там стандарт firewire, есть OHCI, которая соответствующей рабочей группой утверждено и распространяется и при реализации ориентируются на него. С SATA та же история -- сам стандарт закрыт, а стандарт advanced host controller interface -- имплементация Intel HC SATA, которая в виду открытости победила проприетарные реализации контроллеров. С FW все грустнее, хоть и есть OHCI, но из-за закрытости стандарта ендпойнты к нему не реализуешь и большого распространения он не получил.
Тем не менее он довольно интересный, там все довольно просто.
Есть несколько видов запросов
- async dma recv
- async dma transmit
- isochr dma rv
- isochr dma tr
На шине может быть от 0 до 15 устройств и этих портов опять же может быть много. Топология -- скорее сего можно построить то же дерево но в реальности так никто не делает, все просто их стекают в цепочку. Там нетривиальная схема взаимодействия хоста и pending transactions. Если у вас реализован out of order buffer, вы можете комплитнуть транзакцию сразу -- сказать ок. Она получена и на хост она уйдет потом. Если лень реализовывать буфер можете не комплитить, пока не уйдет на хост.
Записи в рамках эти запросов определено 48-битное адресное пространство которое делится следующим образом.
Старшие 20 бит единицы, остальные -- пространство адресов, за исключением 256 мегабайт эти 4 гигабайт это software control memory, называется она high. High и middle отличаются тем что в middle обработка различных ошибок, они посвящены тому что ошибки уходят в программное обеспечение. В high ошибки обрабатываются стандартно, то в случае middle никаких действий по ошибке не происходит считается что по об этом заботится само. Например, по этим адресам реализуется ip over 1394. Смешно тем, что там реализуется сразу ip, а не Ethernet и ping там не работает.
Если сравнивать с PATA, то при подключении двух устройств деградация будет намного более сильная чем в случае с FW.
Лекция 7 (2012-11-26)
Устройства хранения данных
Жесткие диски и вариации на тему, устройства хранения применимые к малым и средним ЭВМ.
Сначала про историю того, как эволюционировали способы подключения и сами устройства.
Исторически конторы которые занимались жесткими дисками -- основными устройствами хранения средних и малых ЭВМ -- Seagate и Western Digital. Seagate когда-то имел другое название, но будем называть его Seagate.
Изначально Seagate разработал ST-506. Пример но в те же годы WD разрабатывала интерфейс IDE. Посредством эволюции этих двух для компьютера IBM PC/AT появился ATA, который использовался на протяжение лет 20 -- началось в 1983, задепрекейчен был интерфейсом SATA, который разрабатывался с небольшим участием Intel 2003 году. SATA заменил Parallel ATA, так получилось, что последовательный интерфейс был проще.
Опять же Seagate разрабатывал собственный чудесный интерфейс SASI, который опять же в начале 70-ых эволюционировал в Small Computer System Interface -- SCSI, помимо протокола много чего определял относительно среды передачи данных, был параллельным. У ATA было 40 пинов (9+16+??), у SCSI 50-60 пинов. Со временем так получилось, что с приходом к пониманию, что дальше тянуть среду передачи данных с параллельной шиной нельзя, появилось SCSI для различных интерфейсов -- iSCSI(over IP), SCSI over FiberChannel. Сам по себе SCSI определял не только протокол для устройства хранения (как АТА), SCSI устройства весьма разнообразны в своих возможностях -- допустимы, например, removable media. Важным медиа для SCSI стал ATAPI -- способ передавать команды SCSI по ATA. Таким образом подключались cd-rom, ZIP, супердрайвы. Где-то здесь появился EIDE. SAS. ATA over Ethernet. Как симметричный ответ iSCSI ATA тоже можно передавать по сети, но не поверх IP, а поверх Ethernet, что имеет некоторые следствия.
Актуальными на данный момент являются SATA, SAS и SCSI(больше софтовая штука). Остальное почило в бозе или осталось как легаси.
Сегодня будет про
- ATA
- SATA
- SCSI
- ATAPI
- SAS
- (iSCSI)
- (PC)
- (IB)
Вообще говоря сам по себе протокол ATA ничего интересного не представляет, хотя в нем есть много особенностей, с которыми вы можете столкнуться если будете обширно взаимодействовать со стораджем. До сих пор есть понятие device 0, device 1, до сих пор CHS нумерация.
ATA
Интерфейс подключения устройств хранения данных. Достаточно простой.
40 пинов. 16 бит данных, device addr, cs, slave, DMACK/DMARQ, INTRQ, IORD/IOWR/IORDY(для PIO и в режиме DMA для подтверждения DMA -- DMA ready на data in, DMA ready on data out), Reset.
Ещё есть такие понятия как pin 20, pin 28, pin 34.
Основная идея -- обновление блока регистров (в SATA -- shadow register block). У устройства поддерживается некое состояние и не его базе оно понимает, чего ему делать. Команда подается следующим образом -- специальным образом конфигурируется блок регистров и потом начинают передаваться данные. Практически все выписанные пины -- легаси. В связи с чем? DMA появилось в ит атачмент чуть ли не в первом, в связи с тем, что альтернативой было только PIO, а он работал отвратительно медленно. PIO это Programmed IO. DMA появилось в первой версии протокола, до этого использовался упомянутый IDE с PIO.
Начнем выписывать версии, их было много.
- ATA 1. 1994 год. Появилось DMA. Так же как и с памятью не сразу появилась возможность писать понесколько слов подряд в одну строку. Так и здесь -- запись была по одному слову 16 бит.
- ATA 2. Много улучшений. MW DMA, 28-bit addr. Изначально регистра адреса был 22 бита, что ограничивает емкость в 2 терабайта, но это исправили и позволили адресовать 128 гигабайт. В DMA использовалась CHS, как в IDE. Во времена PC AT то какую геометрию у диска знал биос сам и в нем информация либо была зашита железно, либо конфигурировалась. Потом стало понятно что так жить нельзя и надо делать со стороны устройства. Но с конца 90 начали использовать зональную запись и оно потеряло смысл. цхс перестало отражать реальную геометрию диска. В разное время упирались в различные ограничения, но это исправлялось либо в биосе, либо руками в нулевом секторе можно было поправить геометрию.
- ATA-3 sw dma deprecated, smart. DMA 2
- ATA-4. впервые появилось atapi UDMA 33
- В районе ATA 5. Появилась поддержка цф. Появилось 80 пин, ультра-DMA-2, скорость типа 33 мегагерца, 32 бита, позволяет передавать 16 гигабайт в секунду. Там они сломали механическую совместимость по коннекторам но добавили землю между проводами -- меньше кросстолки и уменьшается сопротивление. UDMA 66
- ATA 6. 48-битная адресация путем накидывания ещё слов в реджистер блок (сейчас он около 512 слов). Позволяет адресовать дикие петабайты.
- ATA 7. Появилась очередная скорость UDMA/133 это условно говоря предел.
В протокол вкорячили работу с 2 дисками. Пин 20 просто ключик. В современных разъёмах там заглушка. Пин 28 -- cable select. Идея в том, что жесткие диски могут сами понять мастер он или слейв. До этого такая фича была, но в проводах. Если у вас 28 пин заземлен, то можете считать себя мастером. А если висит -- слейвом. Это все условность,конфигурация может быть переписана на устройстве и вообще не связана с тем, что ходит когда девай селект. До тех пор как появились 80 пиновые кабеля он был прописан как фича но не был стандартизован и народ кустарно выбивал/перебивал дорожку. Это было плохо тем, что возникало отражение. ATA он не терминируется в отличие от SCSI и при увеличении скорости отражение начинает играть все большую роль. При разработке ATA 5 было принято волевое решение о физическом расположение мастера.
В режиме DMA если 2 девайса подключены работало то что медленнее. Если было ATA4 и ATA5, то ATA5 или ATA6 не могли отдельно тактироваться.
SATA
Существует 3 итерации стандарта, готовится 4-ая, возможно выйдет в следующем году. По скоростям 1.5 GT ~ 150 MB/s, 3 и 6. Кодирование везде 8/10. Питание у ATA 4-пиновое -- 12в, земля, земля, 5 в.
Сигнальный кабель -- 7 пинов. Причем довольно смешно -- то что торчит, это земля -- она есть общая, для трансивера, для ресиваер, ещё есть пины Tx Rx.
Питание -- 15 пинов. Причем там выставляется 3 разных вольтажа -- 3.3, 5, 12. Это все хорошо размешано землей. На каждый из этих вольтажов по 3 пина, причем один торчит -- чтобы земля поднималась первой. И три пина только земли. Чтобы можно было в сумме нагрузку распределять. Один пин зарезервирован, сейчас граундится.
Ещё есть такая тенденция -- не все вольтажи везде разводятся. Если реализуется мобильное устройство, можно забить на разводку 5 и 12 вольт.
Это оказывает негативное влияние на минимизацию устройств -- разъемы большие. Можете использовать нестандартный разъем, но вы будете не совсем SATA устройство и это может негативно сказаться на вашей карме.
Маленькие ссдшки 5х5 см, которые вешаются на одну линию пси ген 3.
На линклеере все кучеряво. Используется кодирование 8/10.
По поводу физики ещё стоит рассказать -- как вообще поднимается линк. Стейт машина в стандарте для описания различных аспектов взаимодействия девайса и хоста в том что касается поднятияя линка. В PCIe она весьма развесистая и много внимания уделено параллелстейтам. PCIe, как и в пси, который за счет отраженного сигнала позволял делать устройства зеленее, нонандерстендабл. У вас есть некая логика транзишнов между ними поскольку надо делать синхронизацию заголовки кул старт в течение того что. Отличие кулстарат -- л1 состояние в котором фактически все отключено но трансмитер работает и когда приходит синхропоследовательность он синхронизируется и заодно поднимает всю железку обратно и соответственно л0с тоже какой то войд стейт.
С устройствами есть только типы и отдельное состояние и диаграмма попроще.
Первым поднимается хост -- начинает транслировать первую синхропоследовательность (то что в PCIe было бикон). Это символ. Кодирование 8/10. 8 бит называются символами. Обозначаются ABCDEFGH. ABCDE FGH берёте как десятично число k 28.3. 5 бит транслируются в 6, 3 в 4 и следят чтобы было уравновешено по единичкам, что бы вольтаж не задирался. То, чего было в последнее время больше определяет какой вариант преобразования взять для этих половинок. По два варианта для каждого,меняющего диспарити на плюс и на минус. 8 бит это символ -- как данные 8 бит, в канале 10 бит. Почему к? Для данных стандартная таблица, но у нас остается много избыточности, которой можно пользоваться чтобы передвать командные биты. В SATA таких символов 2 -- k28.3 k28.5 -- отдельный битик говорит данные или команда. Но реально командных символов 2. В PCIe их побольше. 28.5 только для лайна. 28.3 для команд.
Host tx: wake -- caminit -- ?? -- comwave Посылается не один символ, а сто шесть десятых, расстояние 66 милисекунд и 100 милисекунд. DevTX: -- --
Схема.
У PCIe семь состояний, каждый определяется своей стейт машиной, некоторые довольно развесистые.
SDF
FIS
CRC
EOF
Так выглядит одна SATA- транзакция. Start of Frame, Enf of Frame -- стандартныесимволы. FIS -- заголовок и команды, стандартная структура. Команды могут быть либо легаси, либо более модные. Когда принимающая сторона видит EOF он знает, что предыдущее было црц. Здесь выравниваюшие символы можно вставлять просто посередине транзакции. Если вы вставили холд, в ответ может придти холдда, это означает что все плохо. Это позволяет делать флоу контрол -- если все буфера забились и все закончилось, но вы начинаете слать флоу. А вот в PCIe для несколько типов операций определены кредиты и считаются отдельно по головам и катушкам.
Подробнее по состояниям. Начинаете слать холд резет, делаете это заданное в стандарте время. Посылаете 28. что-то -- определенный символ, который говорит о том, что резет. Как только вы перестаете это делать, девайс в определенные рамки должен прислать ответ (минимальный и макс границы, миним дли эвитации отражений при кросстолках). Дальше происходит калибровка линий связи на основании комм инита. Начинаете посылать вейк, устройство калибруетсЯ, выравнивается, начинаете посылать данные.
Для поддержки обратной совместимости SATA может выглядеть как легаси ATA хост и рассказывать, что у него есть много девайсов. В режиме эмуляции должен предоставлять реджистер блок и поддерживать его сотояние чтобы выглядеть достаточно ATA устройством.
SCSI
Определили не просто физический протокол, а как и ATA, PCI, ISA -- определили довольно большое количество команд, определили некий формат,этим занимался Seagate, некий формат сообщений -- довольно прикольный. Первые 4 бита номера команды указывали на то, какой у неё будет размер. Команда 0xh или 1xh, то дальше 6 байт заголов Схема.
С физической точки зрения это шина. В первых версиях скорости типа 5 мб на 16 бит -- 10 мб/сек. В какой-то момент перешли на LDS, сохранив механически разъем, но поменяв эдектрически. LDS был в ультра SCSI 2 начиная с 40 мгц.
К ней может подключаться 16 устройств, сейчас это называется таки parallel scsi коннектор. Шина должна явно терминироваться -- в отличие от ATA. Терминирование означает, что там сильный большой и страшный резистор. Если у вас Open Ended кабель, то изменение вольтажа начинает отражаться, усиливаясь. Есть кабель. Начинаете внезапно увеличивать ему вольтаж. Если у вас кабель висит. Пока оно статическое все нормально, а при изменении сигнала.. на такой частоте задается индуктивность и чтобы сменить вектор надо повесить резистор. Быстрая смена напряжения в высокочастотном линке -- индуктивность кабеля сильно влияет и если его терминировать, то наводки от самого же кабеля.. там не наводки. Отражения -- эффект в том, что вольтаж усиливается идя обратно от конца кабеля, если кабель нетерминирован. За счет регулярности передаваемых данных наложение отраженного сигнала закрывает глазок.
Поскольку передача по 2 фронатм + 16 битов у вас получается 140 мб, что быстрее чем SAS 2.0
Командный уровень SCSI довольно универсальный язык для управления устройствами оказался пригодным много где и используется поверх различных сред передачи данных.
LUN -- сначала 16, потом до 256 плюс в теории может быть некоторая иерархия. Logical Unit(??) Number.
ATAPI
Advanced Technology Atached Program Interface. Тянется с PC AT.
Про него можно сказать только то, что тот же самый ATA, но введена команда пэкет и стандартный набор команд ATA, которые устройство может не поддерживать, так как они заменяются командами SCSI. Нужно было потому что как среда передачи данных интерфейс ATA получил широкое распространение, но был предназначен только для жестких дисков. Возникала проблема со всяким ремувабл медиа, а хотелось подключать cd rom, ZIP, супердрайвы по интерфейсу ATA. До этого они подключались кто во что горазд, была куча расширений IDE, которые долго тянулись. Как правило cd rom подключались на звуковые карты, которые таскали на себе по 4 варианта разъема, которые почти ничем не отличались. ZIP и супердрайвы иногда подключались как честный SCSI. Потом некотрое время просто добавляли преобразователь в SATA. Radeon два поколения тянул добавление к интерфейсу AGP оборачиватель и разворачиватель в PCIe.И был смешно наблюдать как некоторые вещи упирались в скорость работы этого переходника.
SAS
Обратно совместим с SATA, но туда насыпали ещё пинов. Скорость у него 600 гб в секунду, при том, что он использует ??2.
iSCSI
SCSI over IP, протокол 3 уровня, может раздавать SCSI устройства всему миру и позволяет с них грузится, хотя это кроме спец железок почти никто не умеет.
Как вообще работает PXE? Есть сервер, который раздает по tftp загрузчик, ?? скачивает образ, а образ умеет работать со SCSI.
AoE
Ata over ethernet, правда лектор его никогда не видел. Оно не маршрутизируется.
FC & IB
FiberChannel исторически для того чтобы сторадж ходил, потом добавили подержку SCSI. 1-2-8-16 гигабит, разрабатывалось для мейнфреймов, основная медиа -- оптика. Хотя сейчас умирает, убиваемый иб, кое где остается, большое легаси. IB умеет инкапсулировать ethernet, поверх ethernet есть IP, поверх IP можно гонять SCSI и некоторые люди так делают.
В плане физики, как это на самом деле реализуется. Все довольно банально. Стоит ведерко с IB, подключено к свитчу, в нем торчит устройство. Схема. Ведерко может не иметь когнитивных свойств и просто быть большим диском, либо какие-то когнитивные свойства иметь. Если не имеет, то ведерок можно напихать сколько угодно, свитч -- кроссбар, он не тормозит. Эта штука пафосно называется SAN, на них навешивается gpfs, lustre.
Лекция 8 (2012-12-03)
Начальная загрузка
Есть некая платформа -- system on chip, или процессор+чипсет+память+северный мост+южный мост, есть power source, есть периферия. Устройства подключены кто-то через южный мост, кто-то через северный. Включаем питание: в памяти полная каша, процессор ничего не помнит. Есть некоторое количество энергонезависимой памяти. Было бы недурно правильно все это безобразие инициализировать и заставить работать. Не все можно закодировать в железе. В встраиваемых системах ещё лет 20 назад вся конфигурация выполнялась замыканием проводов. Вся логика реализовывалась в железе. Конфигурация логической схемы хранилась в энергонезависимой памяти. Вся конфигурация занимала 10-100 пинов. Таким образом можно управлять микроволновками, стиральными машинами. Все это чудесно, но для чипа[сложнее мозга микроволновки] эта штука затратная. Логично вынести инициализацию во вне. Поэтому обычно есть отдельный чип, где хранится инициализационная программа.
В x86 процессор включается и начинает что-то выполнять. Инициализировался и сообразно настройке пинов что-то выполняет. У ARM и system-on-chip довольно долго был разброс и шатание -- как проводить инициализацию. Были системы типа SPARC, POWER PC, у которых все было хорошо, но однообразно. В x86 все довольно кучеряво, поэтому про него и рассказ. Это вообще обычная ситуация для x86, во всех других системах все скучно и работает, а в x86 все кучеряво.
Обычно у процессора и чипа есть некоторое множество конфигурационных чипов. Мануалы про это дело занимают не одну сотню страниц. Помимо пинов есть ещё внутреннее состояние. Тем не менее, есть возможность так или иначе (в зависимости от конкретного чипсета) завести некий диапазон адресов на энергонезависимую флешку.
Но как решается проблема инициализации? Волевым решением. Говорим, что есть адрес reset vector (который регулируем пинами), с которого начинаем выполнение. x86, даже 64-битные, начинает работать в реальном режиме. Есть адрес CS F000h IP FFF0h это получается адрес FFFF0h. В реальном режиме осталось всего 16 бит и этот адрес содержит указатель на код BIOS.
В реальности помимо BIOS сейчас есть ещё UEFI. С точки зрения инициализации они не очень отличаются, UEFI структурно более лучше, но реально нужен чтобы дропнуть большое количество легаси. Реально для южного моста, северного моста, процессора все мануалы считают, что UEFI это тот же BIOS, ибо неважно.
Можно сделать x86 вообще без BIOS, но она будет печально работать, потому что хорошо бы предоставлять хотя бы int 13h. Если его и других полезных вещей не предоставить, то придется патчить систему и большое количество драйверов.
Изначально название BIOS взялось с машин работавших с pcm(??). В конце 70х, когда появились восьмибитные 8080, никакого BIOS не было, все было в hardware. BIOS реализовал базовую работу со всем -- с видеоадаптерами, с вводом-выводом. PC XT. IBM PC/AT среди прочего появился AT_attachement и привычный BIOS -- отдельная микросхема, просто ROM, и она содержала тот самый вынесенный код для инициализации системы. Там была такая штука как POST, зачатки энумерации устройств. Интерфейс ATA конфигурировался железно, [как и?] ISA шина. Все работало довольно грустно.
Потом появилось и было стандартизовано много чего. В начале-середине 2000х появился новый стандат ACPI, APM, DMI/SMBIOS, ESCD.
С ходом времени выделилось несколько устройств с которых можно грузиться:
- ATA
- PCI
- что ещё BIOS знает.
Все это знание приобретенное. Есть ATA устройства, с ними общение происходит посредством чтения-записи регистрового файла, который находится известно где и северный мост позволяет им управять. BIOS видит посредством интерфейса ATA, что есть несколько дисков, с одного из них можно положить 512 байт в память и на них джампнуться. Конфигурация хранилась на отдельном устройстве с батареечками, сейчас кладут на флеш или капаситор -- конденсатор большой емкости для подпитки памяти.
Помимо ATA устройств внятно сконфигурировать можно ещё PCI устройства. Там есть, условно говоря, северный или южный мост, скорее всего северный, там либо PCI арбитр, либо ещё что-то. Так или иначе, к этим PCI устройствам можно получать доступ по магическим адресам. Можно замапить на них определенный регион памяти.
В конфигурационном пространстве устойства написано, что у него есть PCI device ROM. Этот девайс ROM куда-то отмапится путем записи смещения в конфигурационное пространство, и вы чудесным образом этот ROM сможете либо считать, либо сджампиться. У него есть 2 варианта -- x86 код или байт код на форте. BIOS для второго варианта должен поддерживать open firmware. Все это грузится после POST, потому что POST включает тактирование процессора, проверку памяти, проверку периферийных устройств - жестких дисков, некоторые BIOS умеют PCI устройства.
BIOS обладает настолько когнитивными свойствами, что может понять, что некое PCI устройство на самом деле -- контроллер USB и поднять USB.
Есть ещё вариант, когда это делает сам северный мост. Лектор не помнит в каком случае что копируется, это сильно зависит от пары мостов, они могут кэщировать BIOS.
Мануалы для BIOS программера для sp5100 -- 150 страниц. Описание всех фич. Там можно настраивать то, как раскидываются PCIe лейны, как конфигурировать 6 линий ATA, которые у него есть, и много чего ещё . Куча таблиц связанных с конфигурацией встроенной поддержки звука, и т.д.
BIOS занимается чем -- поднимается. Есть ещё некая логика, которая управляет сигналами питания -- включили железку в блок питания, это тоже есть некое взаимодействие. Помимо вольтажа питания стандарт ATX предусматривает наличие сигналов типа PowerGood, после которого сигналы питания могут роутиться дальше. Питание стабилизировалось -- можно отдавать дальше. Оно идет на периферию, платформу... По поводу того, как питается это хозяйство -- там довольно много преобразователей прямого тока, потому что напряжение платформы может составлять сотни ватт.
ACPI
В начале исторически был APN. Этот стандарт был разработан совместно Intel и Microsoft по поводу advanced power management. Доступ был к зашедоуленному диапазону адресов. Нажали кнопку питания, садится батарейка с одной стороны, с другой стороны перевод со стороны софта происходят переходы в разное состояние. С другой стороны стандарт дропнут через 10 лет окончательно, что часто случается со стандартами Microsoft.
С одной стороны ACPI энумерирует устройства, с другой стороны позволяет управлять питанием.
Есть несколько наборов стейтов:
- global G state
- power C state
- Perf P state
Различные устройства -- процессор, северный и южный мост поддерживают переходы в различное состояние. Если переходим в C2 clock off, процессор софту доступен, но типа спит. Этому соответствует погашивание клока и остаются интерфейсные схемы, чтобы перевести обратно в C0. Самое рабочее состояние 0, остальные -- всякое энергосбережение.
С стейты специфичны для процессоров. В K8 K10 есть C1S который типа лучше чем C1 в плане энергосбережения. Но зато они пожертвовали C2.
ASPM
Power management. В PCI появились стейты, и между ними можно было как-то переходить, но никто этим никогда не пользовался. Все отдавалось на усмотрение производителя железки. В PCIe это все было стандартизовано, и этим могло управлять программное обеспечение. В стандарте все было прописано. Дефакто все на это забивают и до сих пор если какое-то железо начинает пропадать или очень странно определяться, один из первых вариантов -- выключить ASPM.
DMI/SMBIOS
Ещё один способ энумерации железа.
SMBIOS стандартизирует способ доступа к таблицам и формат таблиц с информацией о платформе. dmadecode - утилита рассказывает много интересного о системе.
Ручек к BIOS из ос немного -- 13 прерывание, а сам BIOS вы с ним особенно ничего не поделаете, а SMBIOS дает возможность на что-то из железа повлиять.
ESCD
Пример, касающийся маппинга ресурсов -- IRQ, DMA-каналы, регионы. Если BIOS при загрузке видит, что конфигурация совпала, он берет предыдущий маппинг, а если не совпала, то по некоему алгоритму.
MMIO
в x86, и не только, он введен через диапазон адресов, при чтении и записи в которые работает некий мозг записи на определенные пины. У вас есть последовательный порт, сейчас он ногами н торчит, северный мост знает, что его надо отдать, и он у него в печенке сидит.
Последовательный порт это 003f8. Если вы будете писать в этот порт байтики.
Схема.
Может быть включится лампочка.
Все это было нагромождением тайного знания. Если вы пишите собственный BIOS, это тайное знание все равно надо поддерживать.
UEFI имеет некоторую модульную структуру. У UEFI базовый стандарт открыт, закрыты некоторые расширения. Для понимания базового стандарта достаточно.
Есть некий кернел, который представляет собой все тот же самый чуть ли не BIOS, поверх которого вешаются сервисы, которых может быть довольно много, с которыми взаимодейстует ОС. Теперь, вместо того, чтобы писать байтики напрямую, вы будете использовать красивый интерфейс для делания того же самого. Он подмял под себя все, что раньше регулировалось пачкой стандартов.
Как вы могли заметить, загрузка устройства -- штука простая, магии никакой нет. Подают питание, а дальше флешка с произвольным кодом, который должен либо загрузить ОС, либо восстановить.
ОС реализуют ту же функциональность -- энумерируют шины, вот это все. Почему бы на не выкинуть BIOS и не воткнуть туда ОС? Идея закономерная и реализуемая. Есть такая штука как speedboot. LinuxBIOS, coreboot, которая собственно и занимается тем, что инициализирует железо.
Один из вариантов реализации BIOSа, который интересен тем, что он познаваем. Амишный BIOS, felix можно уже посмотреть. С этой точки зрения представляет интерес.
Зачастую BIOS не копируется. BIOS разделен на 3-4 части и эти разные части имеют разное назначение. Есть часть которая не перепрошивается, там может не быть энумерации но систему оно поднимет, чексумму остальных частей проверит.
Лекция 9 (2012-12-10)
Имеет смысл зайти на uneex.ru и подписаться на рассылку, что-нибудь в духе lists.cs.msu.su/mailman/listinfo/uneex. В рассылке трафика немного, так что не будет ничего страшного если вы туда подпишитесь.
Примерно числа 17 будет готов список вопросов. В принципе там ничего сверхъестественного по сравнения с тем что говорил лектор не будет, достаточно просто ориентироваться в теме.
Тема сегодняшней лекции коммуникационные сети.
На следующей лекции можно либо ничего не рассказывать, либо устроить консультацию, либо какую-либо тему по заявкам. Можно поведать лектору пожелания по почте, или в рассылку, или иными средствами (контактные данные есть на uneex.org/eSyr).
Межпроцессорное, межузловое взаимодействие
Так сложилось, что тема взаимодействия различных вычислительных систем требовалась по двум основным причинам
- взаимодействие для обмена данных с целью решения общей задачи -- сети в суперкомпьютерах чаще с ними ассоциируются
- взаимодействия с целью обмена информацией чтобы кто-то мог эту информацию получить.
Так сложилось, что как следствие этих двух задач -- коммуникация ради решения общей задачи и коммуникация ради коммуникации предъявили разный набор требований к построению сетей и было порождено две категории различных сетей которые решают примерно одну и ту же задачу, но делают это сильно по разному вследствие разных требований, и городятся велосипеды для решения задач, которые естественны в другом типе сети. В последнее время тенденция сходит на нет, но тем не менее.
Соответственно, когда рассматриваются сети для решения задач, даже не сети, а коммуникации, там в жертву обычно приносится универсальность, а целью ставится производительность. Исторически наверное суперкомпьютинг существует лет 40, если считать от Cray 1. В начале это были просто большие машины, потом объединения больших машин. Объединениями они стали лет 35 назад.
С другой стороны проекты связанные с DARPA, куча других проектов целью которых было построение способов передачи информации от одной системы к другой, целью была не производительность, а обеспечение факта возможности передачи.
Межпроцессорное взаимодействие
В плане межпроцессорного обмена обычно используются всякий специализированный интерконнект, потому что там все довольно локально. Ставится два процессора и между ними проприетарная шина. У Intel это QPI, второе или третье поколение. Шина не очень открытая, лектору известно про неё мало. До последнего момента вместо QPI был FrontSide Bus, до этого ещё и ещё. Служат они для поддержания когерентности кэшей и запросов в память.
Хотя на самом деле топологии они разные бывают.
Сама идея заключается в том , что надо обеспечивать максимальную производительность с минимальными задержками. Сейчас система выродилась вот в такую
и оптимизировать особо некуда, только два чипа сливать в один. Внизу северный мост NB.
До этого схема была более разнообразна.
Круто, мы соединили два процессора и чего-то этим добились. Так было во времена Pentium 3, ставился особо головастый мост который обслуживал два CPU. Штука не скейлится вообще, больше 4 CPU не воткнете, для этого нужен очень крутой северный мост. Чтобы это сделать нормально нужно туда добавлять дополнительные мемори контроллеры, и схема перестает скейлится вообще. Добавили два процессора, парочку контроллеров и сложность возросла на порядок, потому что нужно обеспечивать соединение все со всеми, то есть сложность увеличили в 8 раз.
Помимо того, что это сейчас Intel SB+, это ещё AMD K8. Фирма AMD довольно быстро (в 2003 что ли) перешла на подобную схему, когда у вас вместо симметричной схемы AMD перешла к NonUniform. Для взаимодействия между процессорами и между процессором и северным мостом используется HyperTransport. Это такой вариант внутрихостового интерконнекта в какой-то момент казалось что он может составить конкуренцию PCIe, но не случилось. Но идея в том, что вместо сильно специального интерконнекта, как FrontSide BUS параллельная шина на 64 бита, протокол не скейлится и предназаначен только для общения между процессором и северным мостом, то HyperTransport как и PCIe несмотря на то, что есть некая специфика особого ограничения на топологию не накладывает. Да, она должна быть древовидной, но не более того. Между процессорами и периферией честный HyperTransport, а между процессорами свой вариант для поддержания кешкогерентности но работает точно так же. Можно видеть как у этого интерконнекта появилась некая свобода и этой свободой пытались воспользоваться, вынося HyperTransport на уровень межузловой коммуникации -- объединять вычислительные системы, узлы по протоколу HyperTransport.
Процессоры с 1-2-4 линка с HyperTransport (кстати поэтому отличались сокеты ц32 и ц34??). то же самое у Intel там есть варианты которые касаются разное количество каналов в память northwood westmere с разным количеством ног xeon 1767 ног с дополнительными линками QPI.
Есть два узла давайте возьмем и объединим каким-то линком процессоры на этих двух узлах. В массы это не пошло. Была такая идея с PCIe, но это опять же исследовательские проекты, нельзя сказать, что это широко распространенный подход.
Есть ряд ограничений связанный именно с топологией, схема сильно скейлиться не будет, но это стало значительно лучше чем кастомная шина только для чего-то одного.
С другой стороны тем временем тут вступаем в область того, что вы скорее всего и так знаете, развивались сети на базе Ethernet.
Ethernet
Причем Ethernet это такая чисто сеть созданная ради обмена данными, во имя факта передачи информации из одного места в другое, причем эти места могут быть как угодно далеко друг от друга, стек протоколов, TCP/IP, ISO, но это штука программная, а внизу все равно среда передачи данных, одной из которых является Ethernet. Он определен набором стандартов 802.3 и 802.1 .1 определяет общие положения, а .3 дает именно стандарты на среду передачи данных, которая либо медь, либо оптика.
Идея в следующем -- у вас есть сетевой адаптер, есть хост система и есть эфир. Чаще всего средой передачи данных является медь или оптика, раньше ещё был коаксиал но вы его скорее своего не застали. Акадо использует? Акадо использует не Ethernet, хоть и на коаксиале, там TokenRing.
Вы слушаете среду передачи данных, и из неё вылавливаете данные. Как именно вы это делаете не очень специфицировано, но сам факт такого общения породил некоторые особенности.
Обмен происходит фреймами. Фреймы эти имеют структуру которую вы сами знаете, там есть адреса по 6 октетов, далее EtherType или Size, дальше payload (минимальная длина из того 64 байт минимальный размер пакета), в начале ещё есть преамбула, потом CRC и IFGAP, итого 1500. Вы знаете почему EtherType или size -- если у вас чиселка меньше 1500 с копейками, то чиселка будет считать payload. Если же она больше 0x0800 то считается что там указан специальный тип, ка кон парсится зависит от него самого (карточка должна про него чего-то знать) и таким образом вкручиваются разные чудесные стандарты, позволяющие например жумба фреймы (иметь payload больше) VLAN и всякие радости недоступные на уровне линка. Если вы делаете какое-нибудь QNQ, то тайп будет 0x9100, первый номер VLAN, потом согласно стандарту 802.1 ac или ad, дальше 0x8AA, но про все это карточка должна быть в курсе, иначе она может их дропать.
Почему начали про формат пакета, потому что архитектура аппаратного обеспечения которое позволяло использовать данные протоколы она дизайнилась во вторую очередь после самих протоколов. Сначала придумали решение в принципе,а потом у же пытались смотреть как оно вообще реализуется. Это первый аспект. Это довольно спорное. но близкое к истине утверждение.
Уже здесь начинается много всего веселого, потому что как это разбирать вариантов много. Уже на линк левел у вас большая вариативность куда смотреть за размером пейлоада, уже на линклеере вам нужно уметь вланы с достаточно сложной логикой, причем что бы она работала быстро ее придетcя реализовывать в железе.
Карточка может быть совсем тупая- -- ловить трафик и отправлять хосту, у которого есть процессор и мифический софт с драйвером который может сказать софту -- там пришли данные, забери их с сетевого адаптера. Есть два способа взаимодействия интерапты и поллинг, либо пассивно либо активно. Интеррапт возбуждается и его обработчик проверяет есть ли чего в буфере, в случае поллинга проверяем периодически есть ли что в буфере, хотя буфера в реальности может и не быть. В страшном сне 3 мегабитного Ethernetа вы просто читали из порта в наджеде что вам начнут приходить данные, так никто не делал, потому что так нельзя и сразу же появилась буферизация того что приходит. Кольцевой буфер с утерей невлезающих пакетов, потому что у нас протокол ненадежной доставки. Схема.
DMA, про него мы уже говорили -- кольцевой буфер на хосте. Вам должны дать диапазон адресов на хосте, сообщить его девайсу и девайс будет туда складывать в каком то виде отфильтрованные и сортированные пакеты. Ну и чтобы девай сам мог периодически сообщать что-то появилось или что-то поллить. В разные времена эффективен был то один то другой метод. В 100 мб Ethernetе были интеррапты и отсутствие DMA. Когда появился гигабит стало выжираться слишком много процессорного времени, потому что выкидывается контекст, включается драгоценный код обработки интеррапта.. в районе гигабит перешли на DMA и решили что поллинг хорошо. Это неплохо и он снижает латенси, потом посмотрели посмотрели решили что интеррапты тоже неплохо, их тоже оставили, просто сейчас используются для того, чтобы сказать в буфере есть данные посмотри, а не в буфере есть данные забирай.
Понятно что два двухпортовых адаптера больше 2 систем не соединим. Ставить везде многопортовые адаптеры штука нетривиальная и хотелось бы избежать. Потому что как только появляется больше 2 вариантов достижения пути, у вас появляются проблемы.
Spanning tree, про него видимо все знают, поэтому просто упомянем. Если будем бродкастить все пакеты начнется бродкаст шторм и все умрут, поэтому стали придумывать кривульки, которая кажется называется 802.1p, которая позволяет устраивать определенные правила поп поводу того куда слать какие то пакеты и находить поддерево графа чему очень радоваться и его использовать. Проблему можно решать на всех уровнях куча протоколов внешней и внутренней маршрутизации для решения той же проблемы на другом уровне. Штука дурацкая в том смысле что опять же его надо поддерживать.
Сейчас есть вариант стандарта 802.1ad который обеспечивает тот же сервис -- позволяет избежать бродкаст шторма, но делает это по другому.
Почему это вообще проблема, потому что изначально архитектурой сети не было предусмотрено что может быть больше одной связи и когда вы начинаете объединять несколько свитчей это начинает бродкастится на все порты и все ломается. Так в Ethernet решается много чего, написано чуть ли не три десятка стандартов современные свитчи должны их поддерживать.
Когда вы выполняете фильтрации но вам нужно использовать несколько маков. Есть опять же мультикастинг на уровне L2, есть куча разных расширений, которые хорошо бы все поддерживать в железе. когда у вас речь заходить про свитч все становится печально, потому что есть вланы, вы хотите на них политику, разные пакеты маркировать по разному, появляется много логик которые вы хотите иметь на втором уровне и от этого вам нужно городить что-то с железом. Если подниматься на уровень IP, начинается ад и израиль. Потому что с заголовками такая же фингня, у IPv6 он вообще переменного размера. У IPv4 он тоже переменного, но есть поле в котором говорится, какого он размера, а в случае v6 эти опции просто зачейнены. Это не способствует скорости работы L3 коммутаторов. Все это железо в результате имеет довольно увлекательную архитектуру.
Уже на L3 стоит задача обслуживания таблиц маршрутизации. Если IP попадает на такой-то префикс, то посылать на тот порт, а иначе на другой. Такая таблица может быть достаточно большой, десятки сотни тысяч записей. Обычно, правда, вы наверное все это знаете, обычно есть сабнеты и префиксы. схема. Чтобы эту структуру обрабатывать нелинейно, основной способ организации таблицы маршрутов -- строится дерево схема. В узлах биты префикса. Дерево с роутами глубиной примерно 25 получилось у нас. Оно хорошо разреженное. Поэтому оно в прямом виде не применяется, хоть по нему довольно очевидно показывается как происходит поиск.
Существуют разные способы компрессии, упоминавшаяся в лекции по память trie tcam и всё это просто потому что протокол такой, не способствует он тому чтобы поиск был быстрым.
Поэтому с одной стороны есть попытки сделать что-то человеческое из Ethernet. Последние предложенные дополнения к стандарту включают наконец-то flow control на уровне линка и поскольку Ethernet он везде пытаются из него что сделать, но он этому всячески сопротивляется введением всяких IPv6. Основная проблема со 100 гиабитами не в том что бы сделать содесы которые могут передавать столько, а в том чтобы поддерживать пактрейт соответствующий, с этим гораздо сложнее. С IPv6 в дереве будет 128 бит. По сути Ethernet может 100 гигабит когда не нужна маршрутизация.
Есть идея которая исходит и с точки зрения интерконнекта и комм сетей сделать что-то достаточно производительно и достаточно универсальное.
Infiniband
На данный момент одним из ярких представителей является Infiniband. можно было бы упомянуть про специализированные комм сети, которые используются в суперкомпьютерах.
В принципе топология Infiniband сетей это тоже множество свитчей которые как-то подключены схема. Это одна сабнет. У такой подсети должен быть сабнет менеджер, который производит инспекцию сети и занимается управлением -- назначает адреса ( у каждого адаптера есть LID, GID, GUID. Идея в чем -- в рамках стандартаInfiniBandопределен протокол по которому см может опрашивать устройства и управлять левел частью их линков в частности назначать адреса. см после того как очнулся может энумерировать всю сеть и рассказать всем как все посылать. он же может определенным образом настроить таблицы маршрутизации.
По поводу формата пакета -- он более приземленный.
local routing, global routing, tlh payloadm in crc v crc
Почему глобал роутинг необязателен? В случае Ethernetа для надежного конекшена используем TCP -- протокол 4 уровня. Вы должны иметь заголовки Ethernetа, IP, TCP и вся это радость занимает больше 54 байт, всем хватает, хороший такой оверхед. Если вы собираетесь пересылать пакеты по 4-8 байт, то всем становится грустно, потому что у вас 90-95 процентов коммуникаций это оверхеды.InfiniBand предоставляет возможность поддерживать надежное соединение уже на уровне банального линк леера. В рамках сабнета можете организовать надежное соединение между двумя узлами. Для этого на этом уровне вводится понятие Queue Path, Send Queue, Recieve Queue, Complition Queue соответственно для обмена вы помимо адреса указываете еще очередь в которую вы посылаете данное сообщение и можете иметь некий ????. Это поддерживаете на уровне самих адаптеров за счет буферизации сообщения для которых комплишн не пришел.
Как устроены все нормальные интерконнекты.
NIC Router (адаптер на несколько портов), кроссбар, приезжают данные, сидят в буфере. Если реализован трафик контрол и виртуальные каналы (вInfiniBandкак минимум два, хотя там до 16 виртуальных каналов, 15-ый считается системным и идет без буферизации) ... Так устроено почти все коммуникационное оборудование, меняется только количество размазанной в разных местах логики. В случае больших роутеров этом может быть лайнкардом, их может быть напихано много много и вместе будет называться циска нексус или куэр опт, в случае Infiniband это будет Infiniband свитч. Решение вы можете принимать в разных местах в принципе.
Сердес, потом буфер для классификации трафика, потом зачастую QoS (в InfiniBand раскидывается по виртуальным каналам, виртуальные каналы это буфер и идея о том, ка кони должны обслуживаться), например может быть что одни пакеты более разные чем другие, то есть системный трафик идет по каналу ноль, он должен быть приоритетен. Но вы можете и сами выделить у себя классы трафика. Когда у вас будет осуществляться арбитраж приоритет будет у того, кто лезет из соответствующего приоритетного виртуального канала. Можно делать несколько виртуальных каналов для разных вещей, например для IO и для обмена данными. Иногда из-за различных приоритетов трафика могут возникать проблемы типа дедлоков и голодания. В комм сетях это разруливается конфигурацией, в InfiniBand настройкой, в Ethernetе плохо.
Принятие каких-то решений о маршрутизации можно задизайнить сеть так, что той информации которая храниться в пакете достаточно для принятия решения о маршрутизации, возможно требуется доп. информации типа таблицы маршрутов. Чем сложнее принятие этого решения, тем сложнее логика на каждый виртуальный канал и это плохо масштабируется.
Ib хорош тем, что решения на уровне L2 принимаются достаточно просто. Mellanox долго страдал что у них не было адаптивного роутинга, теперь они его сделали.
Дошло до того, что Ethernet заворачивают Ethernet в Infiniband.
Голодание может привести к дедлоку. Если есть два завязанных друг на друга потока и они идут навстречу друг другу, то они друг друга забивают. Для этого можно их положить в разные вирт каналы, которые будут арбитрироваться справедливо.
Бисекционная пропускная способность . Берете половину узлов и смотрите сколько можно предать другой половине узлов в худшем случае (количество линков).