Почему в современных CPU нет инструкции `nand`?

Почему разработчики x86 (или другие архитектуры процессоров) решили не включать его? Это логические ворота, которые могут быть использованы для построения других логических ворот, таким образом, это быстро, как одна команда. Вместо того, чтобы связывать команды not и and (оба созданы из nand), почему нет инструкции nand ?.

cpu
52 голоса | спросил Amumu 17 Jpm1000000pmTue, 17 Jan 2017 19:11:17 +030017 2017, 19:11:17

9 ответов


60

http://www.ibm.com/support/knowledgecenter /ssw_aix_61/com.ibm.aix.alangref/idalangref_nand_nd_instrs.htm : POWER имеет NAND.

Но в целом современные процессоры построены таким образом, чтобы они соответствовали автоматизированной генерации кода компиляторами, и побитовое NAND очень редко требует. Побитовое И и ИЛИ используется чаще для управления битовыми полями в структурах данных. На самом деле SSE имеет AND-NOT, но не NAND.

Каждая инструкция имеет стоимость в логике декодирования и потребляет код операции, который может быть использован для чего-то другого. Особенно в кодировках переменной длины, таких как x86, вы можете использовать короткие коды операций и использовать более длинные, что потенциально замедляет весь код.

ответил pjc50 17 Jpm1000000pmTue, 17 Jan 2017 19:46:29 +030017 2017, 19:46:29
32

Стоимость таких функций ALU составляет

1) логика, выполняющая собственно функцию

2) селектор, который выбирает этот результат функции вместо остальных вне всех функций ALU

3) стоимость наличия этой опции в наборе команд (и не имеющая какой-либо другой полезной функции)

Я согласен с вами в том, что 1) стоимость очень мала. Однако стоимость 2) и 3) практически не зависит от функции. Я думаю, что в этом случае 3) стоимость (бит, занятый в инструкции) была причиной не иметь этой конкретной инструкции. Биты в инструкции - очень скудный ресурс для конструктора ЦП /архитектуры.

ответил Wouter van Ooijen 17 Jpm1000000pmTue, 17 Jan 2017 19:50:50 +030017 2017, 19:50:50
28

Поверните его - сначала посмотрите почему Нэнд был популярен в дизайне аппаратной логики - здесь есть несколько полезных свойств. Затем спросите, сохраняются ли эти свойства в инструкции CPU ...

TL /DR - они этого не делают, поэтому нет необходимости использовать And, Or or Not.

Самым большим преимуществом для логики Nand с жестким интерфейсом была скорость, достигаемая за счет уменьшения количества логических уровней (транзисторных ступеней) между входами и выходами схемы. В процессоре тактовая частота определяется скоростью гораздо более сложных операций, таких как сложение, поэтому ускорение операции И не позволит вам увеличить тактовую частоту.

И количество раз, когда вам нужно комбинировать другие команды, исчезает мало - достаточно, чтобы Nand действительно не зарабатывал свое место в наборе инструкций.

ответил Brian Drummond 17 Jpm1000000pmTue, 17 Jan 2017 21:40:25 +030017 2017, 21:40:25
11

Я хотел бы согласиться с Брайаном здесь, а Wouter и pjc50.

Я также хотел бы добавить, что в универсальных, особенно CISC процессорах, инструкции не все имеют одинаковую пропускную способность - сложная операция может потребовать больше простых циклов.

Рассмотрим X86: AND (который является «и»), вероятно, очень быстрым. То же самое касается NOT. Давайте рассмотрим немного разборки:

Код ввода:

#include <immintrin.h>
#include <stdint.h>

__m512i nand512(__m512i a, __m512i b){return ~(a&b);}
__m256i nand256(__m256i a, __m256i b){return ~(a&b);}
__m128i nand128(__m128i a, __m128i b){return ~(a&b);}
uint64_t nand64(uint64_t a, uint64_t b){return ~(a&b);}
uint32_t nand32(uint32_t a, uint32_t b){return ~(a&b);}
uint16_t nand16(uint16_t a, uint16_t b){return ~(a&b);}
uint8_t nand8(uint8_t a, uint8_t b){return ~(a&b);}

Команда для сборки:

gcc -O3 -c -S  -mavx512f test.c

Выходная сборка (укороченная):

    .file   "test.c"
nand512:
.LFB4591:
    .cfi_startproc
    vpandq  %zmm1, %zmm0, %zmm0
    vpternlogd  $0xFF, %zmm1, %zmm1, %zmm1
    vpxorq  %zmm1, %zmm0, %zmm0
    ret
    .cfi_endproc
nand256:
.LFB4592:
    .cfi_startproc
    vpand   %ymm1, %ymm0, %ymm0
    vpcmpeqd    %ymm1, %ymm1, %ymm1
    vpxor   %ymm1, %ymm0, %ymm0
    ret
    .cfi_endproc
nand128:
.LFB4593:
    .cfi_startproc
    vpand   %xmm1, %xmm0, %xmm0
    vpcmpeqd    %xmm1, %xmm1, %xmm1
    vpxor   %xmm1, %xmm0, %xmm0
    ret
    .cfi_endproc
nand64:
.LFB4594:
    .cfi_startproc
    movq    %rdi, %rax
    andq    %rsi, %rax
    notq    %rax
    ret
    .cfi_endproc
nand32:
.LFB4595:
    .cfi_startproc
    movl    %edi, %eax
    andl    %esi, %eax
    notl    %eax
    ret
    .cfi_endproc
nand16:
.LFB4596:
    .cfi_startproc
    andl    %esi, %edi
    movl    %edi, %eax
    notl    %eax
    ret
    .cfi_endproc
nand8:
.LFB4597:
    .cfi_startproc
    andl    %esi, %edi
    movl    %edi, %eax
    notl    %eax
    ret
    .cfi_endproc

Как вы можете видеть, для типов данных под 64-типа все просто обрабатывается как longs (отсюда и l , а не l ), поскольку это «родная» битовая ширина моего компилятора, как кажется.

Тот факт, что существует mov s между ними, связан только с тем, что eax является регистром, который содержит возвращаемое значение функции. Обычно вы просто рассчитываете в регистре общего назначения edi для вычисления результата с результатом.

Для 64 бит это то же самое, что и «quad» (следовательно, завершающие слова q) и rax /rsi вместо eax /edi.

Похоже, что для 128-битных операндов и больше Intel не стремилась реализовать «не» операцию; вместо этого компилятор создает регистр all- 1 (самосогласование регистра с самим собой, результат сохраняется в регистре с помощью команды vdcmpeqd) и xor s.

Короче: Внедряя сложную операцию с несколькими элементарными инструкциями, вы не обязательно замедляете работу - просто нет преимущества в том, чтобы иметь одну инструкцию, которая выполняет задание с несколькими инструкциями, если это не быстрее.

ответил Marcus Müller 17 Jpm1000000pmTue, 17 Jan 2017 22:46:31 +030017 2017, 22:46:31
10

Сначала не путайте побитовые и логические операции.

Побитовые операции обычно используются для установки /очистки /переключения /проверки бит в битовых полях. Ни одна из этих операций не требует использования nand («а не», также известного как «бит очистить»).

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

ответил Peter Green 17 Jpm1000000pmTue, 17 Jan 2017 20:44:40 +030017 2017, 20:44:40
10

NAND часто не реализуется напрямую, потому что наличие инструкции AND неявно дает вам возможность прыгать по условию NAND. Выполнение логической операции в CPU часто устанавливает биты в регистре флагов.

Большинство регистров флагов имеют флаг ZERO. Флаг нуля устанавливается, если результат логической операции равен нулю и в противном случае очищается.

Большинство современных процессоров имеют инструкцию перехода, которая перескакивает, если установлен флаг нуля. У них также есть istruction, который перескакивает, если флаг нуля не задан. AND и NAND являются дополнениями. Если результат операции И равен нулю, результат операции NAND равен 1, и наоборот.

Поэтому, если вы хотите прыгать, если NAND двух значений истинно, тогда просто выполните операцию AND и прыгайте, если установлен флаг нуля.

Так что если вы хотите прыгать, если NAND двух значений является ложным, то просто выполните операцию AND и прыгайте, если флаг нуля ясен.

ответил user4574 18 Jpm1000000pmWed, 18 Jan 2017 22:40:05 +030017 2017, 22:40:05
4

Просто потому что что-то дешево не означает, что оно экономически выгодно .

Если мы примем вашу аргументацию ad absurdum, мы пришли к выводу, что процессор должен состоять в основном из сотен вариантов инструкций NOP, потому что они являются самыми дешевыми для реализации.

Или сравните его с финансовыми инструментами: вы купили бы облигацию в размере 1 доллар с возвратом 0,01% только потому, что можете? Нет, лучше бы сохранить эти доллары, пока у вас не будет достаточно, чтобы купить облигацию на 10 долларов с лучшим возвратом. То же самое происходит с силиконовым бюджетом на процессоре: эффективно использовать много дешевых, но бесполезных операционных систем, таких как NAND, и поставить сохраненные транзисторы во что-то более дорогое, но действительно полезное.

Нет расы, чтобы иметь как можно больше операций. Поскольку RISC против CISC доказал, что Тьюринг знал с самого начала: меньше - больше. На самом деле лучше иметь как можно меньше операций.

ответил Agent_L 18 Jpm1000000pmWed, 18 Jan 2017 21:12:55 +030017 2017, 21:12:55
3

На аппаратном уровне либо nand, либо нет - это элементарная логическая операция. В зависимости от технологии (или в зависимости от того, что вы произвольно называете 1 и того, что вы называете 0), либо nand, либо не может быть реализовано простым, элементарным способом.

Если мы игнорируем случай «nor», вся другая логика строится из nand. Но не потому, что есть некоторая доказательство в компьютерной науке, что все логические операции могут быть построены из и - причина в том, что просто не какой-либо элементарный метод для построения xor, или, и т. Д., Что лучше затем построим его из nand.

Для компьютерных инструкций ситуация другая. Команда nand может быть реализована, и это будет немного дешевле, чем реализация xor, например. Но только крошечный бит, потому что логика, которая вычисляет результат, крошечная по сравнению с логикой, которая декодирует инструкцию, перемещает операнды вокруг, гарантирует, что одна операция только вычисляется, и берет результат и доставляет его в нужное место. Каждая инструкция выполняет один цикл, как дополнение, которое в десять раз сложнее с точки зрения логики. Экономия nand vs. xor была бы незначительной.

То, что подсчитывает то, сколько команд требуется для операций , которые фактически выполняются с помощью типичного кода . Nand нигде не находится в верхней части списка обычно запрашиваемых операций. Это гораздо чаще, чем и, или, не запрашивается. Разработчики процессоров и инструкторов рассмотрят множество существующих кодов и определит, как разные инструкции повлияют на этот код. Они, скорее всего, обнаружили, что добавление инструкции nand приведет к очень небольшому сокращению числа команд процессора, выполняющих запуск типичного кода, и замена некоторой существующей команды на nand увеличит количество выполненных команд.

ответил gnasher729 22 Jam1000000amSun, 22 Jan 2017 02:41:23 +030017 2017, 02:41:23
2

Просто потому, что NAND (или NOR) может реализовать все блоки в комбинационной логике, не переводит на эффективный побитовый оператор таким же образом. Чтобы реализовать AND, используя только операции NAND, где c = a AND b, вам нужно будет иметь c = NAND b, затем b = -1, затем c = c NAND b (для NOT). Основными логическими побитовыми операциями являются AND, OR, EOR, NOT, NAND и NEOR. Это не так много, чтобы покрыть, и первые четыре, как правило, построены в любом случае. В комбинационной логике основные логические схемы ограничены только количеством доступных ворот, что является совсем другой игрой в мяч. Количество возможных взаимосвязей в программируемой матрице ворот, которая звучит так, как вы на самом деле, действительно будет очень большой. Некоторые процессоры действительно имеют встроенные массивы ворот.

ответил Robin Hodson 22 Jam1000000amSun, 22 Jan 2017 11:04:20 +030017 2017, 11:04:20

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132