vottak08 написал(а):об этом подробнее пожалуйста :smile: мне самому интересно
Здесь, собственно, всё очень просто. Каким образом можно повысить производительность процессора? Можно повышать тактовую частоту (вспомним "гонку за мегагерцами" времен архитектуры Netburst). Можно добавлять новые наборы команд (MMX/SSE/SSE2/SSE3/SSSE3/SSE4.1/SSE4.2/AESNI/AVX), а можно попытаться увеличивать IPC - количество инструкций, которые процессор выполняет за цикл. С этой целью процессоры современные Intel набиты всевозможными архитектурными особенностями, такими как micro- и macrofusion, LSD (loop stream detector) и т.д.
Постоянно растет количество исполнительных блоков в процессоре. Ведь в один момент может поступить последовательность строковых команд, а следующий - SIMD-команд.
(SIMD используют для обработки строк, но термин "строковые команды" закреплен за набором команд LODS/SCAS/STOS/CMPS использующих регистры общего назначения).
Поскольку каждое исполнительное устройство в той или иной степени специализировано, эти команды будут загружать только часть их них, в то время как другие исполнительные устройства будут простаивать.
Тогда Intel сделала достаточно неоднозначный шаг и добавила в Pentium 4 поддержку "гипернитевости" (hyperthreading). В каждое физическое ядро (которое тогда было одно) были добавлены второй комплект почти всех регистров. Не только регистров общего назначения, сегментных, счетчика команд, регистров FPU/MMX (они у них общие), SSE и системных: LDT, GTD, IDT, TSS, CR0..CR4, регистров отладки DR0-DR3, DR6, DR7, но и большинства MSR регистров. А также собственный APIC для обработки прерываний.
Зачем я это перечисляю? Затем, чтобы уважаемый читатель мог себе представить, что с точки зрения пользователя у него появлялось два процессора вместо одного.
До этого момента процессоры ПК (серверные процессы мы не рассматриваем) в каждый конкретный момент могли выполнять только один поток команд.
Есть у нас две программы, готовые к выполнению - они конкурируют между собой за ресурсы процессора.
Пока одна программа выполняется, вторая стоит в очереди. Закончился квант времени, выделенный первой программе - процессор выполняет переключение контекста (сохраняет регистры первой программы и загружает регистры второй) и начинает исполнять её.
Если программа по каким-то причинам не может продолжать выполнение (к примеру, запросила данные с жесткого диска и ждет их получения), её отправляют в очередь и переключаются на другую.
Теперь рассмотрим ситуацию, когда процессор одновременно исполняет ДВА потока команд.
Если у нас есть всего две задачи, готовые к исполнению, никто не стоит в очереди. Не производятся дорогостоящие программные переключения контекстов (система команд Intel позволяет переключать контексты аппаратно, но ни одна известная мне ОС уже давно этой возможностью не пользуется).
Предполагалось, что одновременное исполнение двух потоков команд позволит добиться большей загруженности исполнительных устройств. Пока одна программа выполняет SIMD-команду, второй в это время понадобятся какие-то операции чтения/записи регистров общего назначения.
Идея может быть была и неплохой, но исполнение оказалось так себе и многие пользователи (включая меня) этот самый Hyperthreading просто отключали.
Ведь одновременной исполнение двух потоков команд на одной процессоре означает, в частности, то, что каждому процессу достается вдвое меньший объем кэш-памяти. Ну и т.д.
В результате из архитектуры Core Duo (и Quadro) этот механизм был исключен. Потом, в core i его вернули обратно, но это уже совсем другая история...
Для чего я это рассказываю?
Да по крайне простой причине - архитектура "Bulldozer" была сделана по аналогии с Intel'овским Hyperthreading.
С двумя различиями. Первое состояло в том, что у Intel любой поток мог использовать любое исполнительное устройство. AMD жестко закрепила за каждым потоком свой набор исполнительных устройств для целочисленных операций и разделяемый между двумя потоками блок операций с плавающей точкой.
Кроме того, кэш данных 1-го уровня (а кэш первого уровня, как всем хорошо известно, еще со времен самого первого Pentium выполнен по Гарвардской архитектуре - отдельное адресное пространство для команд и для данных) у AMD был раздельным. Для каждого виртуального ядра свой.
Получившуюся конструкцию маркетологи AMD немедленно обозвали "двумя ядрами", хотя очевидно, что в лучшем случае его следовало бы называть процессорным модулем.
Почему процессорный модуль оказался неудачным?
Во-первых, у каждого модуля имелось всего одно устройство дешифровки команд, которое должно было одновременно обслуживать два "недоядра". При этом производительность этого устройства была даже меньше, чем производительность дешифратора Intel, который обслуживал всего одно полноценное ядро.
Это "узкое место" архитектуры Zambezi было ликвидировано в Piledriver - каждое недоядро получило собственный дешифратор.
Каждый процессорный модуль Bulldozer имеет раздельный 16кБ-ный кэш для каждого из ядер. разработчики AMD не смогли добиться когерентности кэша и, в конце концов, чтобы не сорвать сроки выпуска были вынуждены сделать его со сквозной записью (writethrough) вместо обратной записи (writeback).
Аналогичную организацию кэш-памяти Intel последний раз применял в процессоре 80486 в 1989 году.
Вообще, необходимо отметить, что кэш-память процессоров AMD, несмотря на свои вроде бы приличные размеры, проигрывает кэш-памяти Intel. Условно можно сказать, что эффективность кэш-памяти пропорциональна величине, полученной умножением её размера на степень ассоциативности. У Intel кэш-память первого уровня (что для данных, что для инструкций) имеет размер 32к при ассоциативности равной 8.
Кэш инструкций (общих для обоих ядер) Buuldozer'а вроде бы имеет вдвое больший объем - 64к. Но он всего лишь двухканальный (ассоциативность = 2).
В результате имеем: Intel (32*8) > AMD (64*2).
Теперь сравним количество исполнительных устройств. Ядро процессора Intel имеет 6 исполнительных устройств, 3 из которых могут выполнять всевозможные арифметические, логические и прочие операции, включая операции с плавающей точкой, еще два - это load/staddr и одно для записи результатов в память (store).
То есть всего 3 ALU (арифметико-логических устройств) и 3 AGU (устройств генерации адреса) на ядро.
Модуль "Бульдозера" имеет больше исполнительных устройств. У него 4 ALU (не поддерживающих операции с плавающей точкой), 4 AGU и два 128-разрядных FMAC (fused multi-add capabilities) - устройства, выполняющих команды x87 и все SSE/AVX.
При этом, на каждое ядро (в терминологии AMD) приходится всего по 2 ALU и AGU + FMAC'и, разделяемые между двумя "ядрами".
То есть, одно ядро Intel выполняет по 2 AVX операции за такт, в то время как модуль AMD - 1 операцию. По полоперации на "ядро".
Конечно, называть половинки модуля "ядрами" столь же некорректно, как называть двухядерным Pentium 4 с поддержкой HT.
Тут уж постарались маркетологи AMD. Конечно, слова "восьмиядерный процессор" звучат лучше, чем "4-хядерный с аппаратной поддержкой выполнения двух потоков команд каждым ядром".
P.S. Чисто по-человечески я могу понять руководство AMD. В то время, как Intel давно клепает 10-тиядерные Xeon'ы, очень неудобно честно признаваться: "ребята, мы не можем разместить больше 4-х ядер на кристалле. Простите, так получилось". Ведь даже их хваленые "16-тиядерные" Opteron'ы на самом деле представляют собой всего лишь два соединенных шиной hypertransport 4-хядерных кристалла в одном корпусе.
Постоянно растет количество исполнительных блоков в процессоре. Ведь в один момент может поступить последовательность строковых команд, а следующий - SIMD-команд.
(SIMD используют для обработки строк, но термин "строковые команды" закреплен за набором команд LODS/SCAS/STOS/CMPS использующих регистры общего назначения).
Поскольку каждое исполнительное устройство в той или иной степени специализировано, эти команды будут загружать только часть их них, в то время как другие исполнительные устройства будут простаивать.
Тогда Intel сделала достаточно неоднозначный шаг и добавила в Pentium 4 поддержку "гипернитевости" (hyperthreading). В каждое физическое ядро (которое тогда было одно) были добавлены второй комплект почти всех регистров. Не только регистров общего назначения, сегментных, счетчика команд, регистров FPU/MMX (они у них общие), SSE и системных: LDT, GTD, IDT, TSS, CR0..CR4, регистров отладки DR0-DR3, DR6, DR7, но и большинства MSR регистров. А также собственный APIC для обработки прерываний.
Зачем я это перечисляю? Затем, чтобы уважаемый читатель мог себе представить, что с точки зрения пользователя у него появлялось два процессора вместо одного.
До этого момента процессоры ПК (серверные процессы мы не рассматриваем) в каждый конкретный момент могли выполнять только один поток команд.
Есть у нас две программы, готовые к выполнению - они конкурируют между собой за ресурсы процессора.
Пока одна программа выполняется, вторая стоит в очереди. Закончился квант времени, выделенный первой программе - процессор выполняет переключение контекста (сохраняет регистры первой программы и загружает регистры второй) и начинает исполнять её.
Если программа по каким-то причинам не может продолжать выполнение (к примеру, запросила данные с жесткого диска и ждет их получения), её отправляют в очередь и переключаются на другую.
Теперь рассмотрим ситуацию, когда процессор одновременно исполняет ДВА потока команд.
Если у нас есть всего две задачи, готовые к исполнению, никто не стоит в очереди. Не производятся дорогостоящие программные переключения контекстов (система команд Intel позволяет переключать контексты аппаратно, но ни одна известная мне ОС уже давно этой возможностью не пользуется).
Предполагалось, что одновременное исполнение двух потоков команд позволит добиться большей загруженности исполнительных устройств. Пока одна программа выполняет SIMD-команду, второй в это время понадобятся какие-то операции чтения/записи регистров общего назначения.
Идея может быть была и неплохой, но исполнение оказалось так себе и многие пользователи (включая меня) этот самый Hyperthreading просто отключали.
Ведь одновременной исполнение двух потоков команд на одной процессоре означает, в частности, то, что каждому процессу достается вдвое меньший объем кэш-памяти. Ну и т.д.
В результате из архитектуры Core Duo (и Quadro) этот механизм был исключен. Потом, в core i его вернули обратно, но это уже совсем другая история...
Для чего я это рассказываю?
Да по крайне простой причине - архитектура "Bulldozer" была сделана по аналогии с Intel'овским Hyperthreading.
С двумя различиями. Первое состояло в том, что у Intel любой поток мог использовать любое исполнительное устройство. AMD жестко закрепила за каждым потоком свой набор исполнительных устройств для целочисленных операций и разделяемый между двумя потоками блок операций с плавающей точкой.
Кроме того, кэш данных 1-го уровня (а кэш первого уровня, как всем хорошо известно, еще со времен самого первого Pentium выполнен по Гарвардской архитектуре - отдельное адресное пространство для команд и для данных) у AMD был раздельным. Для каждого виртуального ядра свой.
Получившуюся конструкцию маркетологи AMD немедленно обозвали "двумя ядрами", хотя очевидно, что в лучшем случае его следовало бы называть процессорным модулем.
Почему процессорный модуль оказался неудачным?
Во-первых, у каждого модуля имелось всего одно устройство дешифровки команд, которое должно было одновременно обслуживать два "недоядра". При этом производительность этого устройства была даже меньше, чем производительность дешифратора Intel, который обслуживал всего одно полноценное ядро.
Это "узкое место" архитектуры Zambezi было ликвидировано в Piledriver - каждое недоядро получило собственный дешифратор.
Каждый процессорный модуль Bulldozer имеет раздельный 16кБ-ный кэш для каждого из ядер. разработчики AMD не смогли добиться когерентности кэша и, в конце концов, чтобы не сорвать сроки выпуска были вынуждены сделать его со сквозной записью (writethrough) вместо обратной записи (writeback).
Аналогичную организацию кэш-памяти Intel последний раз применял в процессоре 80486 в 1989 году.
Вообще, необходимо отметить, что кэш-память процессоров AMD, несмотря на свои вроде бы приличные размеры, проигрывает кэш-памяти Intel. Условно можно сказать, что эффективность кэш-памяти пропорциональна величине, полученной умножением её размера на степень ассоциативности. У Intel кэш-память первого уровня (что для данных, что для инструкций) имеет размер 32к при ассоциативности равной 8.
Кэш инструкций (общих для обоих ядер) Buuldozer'а вроде бы имеет вдвое больший объем - 64к. Но он всего лишь двухканальный (ассоциативность = 2).
В результате имеем: Intel (32*8) > AMD (64*2).
Теперь сравним количество исполнительных устройств. Ядро процессора Intel имеет 6 исполнительных устройств, 3 из которых могут выполнять всевозможные арифметические, логические и прочие операции, включая операции с плавающей точкой, еще два - это load/staddr и одно для записи результатов в память (store).
То есть всего 3 ALU (арифметико-логических устройств) и 3 AGU (устройств генерации адреса) на ядро.
Модуль "Бульдозера" имеет больше исполнительных устройств. У него 4 ALU (не поддерживающих операции с плавающей точкой), 4 AGU и два 128-разрядных FMAC (fused multi-add capabilities) - устройства, выполняющих команды x87 и все SSE/AVX.
При этом, на каждое ядро (в терминологии AMD) приходится всего по 2 ALU и AGU + FMAC'и, разделяемые между двумя "ядрами".
То есть, одно ядро Intel выполняет по 2 AVX операции за такт, в то время как модуль AMD - 1 операцию. По полоперации на "ядро".
Конечно, называть половинки модуля "ядрами" столь же некорректно, как называть двухядерным Pentium 4 с поддержкой HT.
Тут уж постарались маркетологи AMD. Конечно, слова "восьмиядерный процессор" звучат лучше, чем "4-хядерный с аппаратной поддержкой выполнения двух потоков команд каждым ядром".
P.S. Чисто по-человечески я могу понять руководство AMD. В то время, как Intel давно клепает 10-тиядерные Xeon'ы, очень неудобно честно признаваться: "ребята, мы не можем разместить больше 4-х ядер на кристалле. Простите, так получилось". Ведь даже их хваленые "16-тиядерные" Opteron'ы на самом деле представляют собой всего лишь два соединенных шиной hypertransport 4-хядерных кристалла в одном корпусе.