Есть ли аппаратная поддержка 128-битных целых чисел в современных процессорах?
нам все еще нужно эмулировать 128bit целые числа в программном обеспечении, или есть аппаратная поддержка для них в вашем среднем настольном процессоре в эти дни?
3 ответов
набор инструкций x86-64 может выполнять 64-разрядные*64-разрядные до 128-разрядных с помощью одной инструкции (mul
для неподписанных imul
для подписанного каждого с одним операндом), поэтому я бы сказал, что в некоторой степени набор инструкций x86 включает некоторую поддержку 128-битных целых чисел.
если ваш набор инструкций не имеет инструкции, чтобы сделать 64-бит*64-бит до 128-бит, то вам нужно несколько инструкций, чтобы подражать этой.
вот почему 128-бит * 128-бит для снижения 128-битные операции можно выполнить с помощью нескольких инструкций с x86-64. Например, с GCC
__int128 mul(__int128 a, __int128 b) {
return a*b;
}
производит эту сборку
imulq %rdx, %rsi
movq %rdi, %rax
imulq %rdi, %rcx
mulq %rdx
addq %rsi, %rcx
addq %rcx, %rdx
который использует одну 64-битную * 64-битную до 128-битных инструкций, две 64-битные * 64-битные до более низких 64-битных инструкций и два 64-битных дополнения.
короткий ответ: нет!
чтобы уточнить больше, регистры SSE имеют 128-битную ширину, но нет инструкций, чтобы рассматривать их как 128-битные целые числа. В лучшем случае эти регистры рассматриваются как два 64-разрядных (un)целых числа со знаком. Операции, такие как сложение/... может быть построен путем параллельного добавления этих двух 64-разрядных значений и ручной обработки переполнения, но не с помощью одной инструкции. Реализация этого может стать довольно сложной и "уродливой", посмотрите здесь:
как я могу сложите два регистра SSE
Это должно быть сделано для каждой базовой операции с, вероятно, сомнительными преимуществами по сравнению с использованием 64-битных регистров общего назначения ("эмуляция" в программном обеспечении). С другой стороны, преимущество этого SSE-подхода будет заключаться в том, что после его реализации он также будет работать для 256-битных целых чисел(AVX2) и 512-битных целых чисел(AVX-512) с незначительными изменениями.
Я собираюсь объяснить это, сравнивая настольные процессоры с простыми микроконтроллерами из-за аналогичной работы арифметических логических блоков (ALU), которые являются калькуляторами в CPU, и соглашение о вызовах Microsoft x64 против Соглашение О Вызове System-V. Для короткого ответа прокрутите до конца, но длинный ответ заключается в том, что проще всего увидеть разницу, сравнивая x86/x64 с ARM и AVR:
долго Ответ
Родное Двойное Слово Целочисленная Математическая Архитектура Поддержка Сравнение
| CPU | word x word => dword | dword x dword => dword |
|:-----------------:|:--------------------:|:----------------------:|
| M0 | No | No |
| AVR | No | No |
| M3/M4/A | Yes | No |
| x86/x64 | Yes | No |
| SSE/SSE2/AVX/AVX2 | Yes | Yes |
если вы понимаете эту диаграмму, перейдите к короткому ответу
процессоры в смартфонах, ПК и серверах имеют несколько ALUs, которые выполняют вычисления на регистрах различной ширины. Микроконтроллеры, с другой стороны, обычно имеют только один ALU. Размер слова процессора не совпадает с размером слова ALU, хотя они могут быть одинаковыми, Cortex-M0 быть ярким примером.
архитектура ARM
кора-М0-это большой палец-2 а Фон Нейман Архитектура Процессор, что означает, что это в основном 16-битный процессор Thumb16, но он имеет 32-битный ALU. В сборке у вас будут в основном 16-битные инструкции, а когда у вас есть 32-битная инструкция, вы загружаете слово в 32-битный регистр и используете две 16-битные инструкции. Это резко контрастирует с Cortex-M3 / M4, как полнофункциональный 32-бит Гарвард Архитектура процессоры. Несмотря на эти различия, все процессоры ARM имеют один и тот же набор или архитектурные регистры, которые легко модернизировать с M0 до M3/M4 и быстрее процессоров Cortex-A серии смартфонов с расширения NEON SIMD.
ARM архитектурные регистры
при выполнении двоичной операции обычно значение переполняет регистр (т. е. становится слишком большим, чтобы поместиться в регистре). Алу имейте N-битный вход и N-битный выход с флагом переноса (т. е. переполнения).
добавление не может быть выполнено в одной инструкции, но требует относительно мало инструкций. Однако,для умножения вам нужно будет удвоить размер слова, чтобы соответствовать результату и ALU имеет только N входов и N выходов, когда вам нужно 2n выходов, так что это не сработает. Например, при умножении двух 32-разрядных целых чисел требуется 64-разрядный результат и два 64-битных целых числа требуют до 128-битного результата с 4 регистрами размером со Слово; 2 неплохо, но 4 усложняется, и у вас заканчиваются регистры. То, как CPU обрабатывает это, будет отличаться. Для Cortex-M0 нет инструкций для этого, потому что это Thumb-2, но с Cortex-M3/M4 есть инструкция для 32x32=>64-битного регистра, который принимает 3 такта.
архитектура AVR
микроконтроллер AVR имеет 131 инструкцию, которая работает на 32 8-разрядных регистрах и классифицируется как 8-разрядный процессор по количеству команд, но имеет как 8-разрядный, так и 16-разрядный ALU. процессор AVR не может выполнить 16x16=>32-разрядные вычисления С двумя 16-битными парами регистров или 64-битной целочисленной математикой без программного взлома. Это противоположность конструкции x86 / x64 в обеих организациях регистров и операции переполнения ALU. Вот почему AVR классифицируется как 8/16-битный процессор. Почему тебя это волнует? Это влияет на производительность и прерывание поведение.
архитектурные регистры AVR
архитектура x86
на x86 умножение двух 32-разрядных целых чисел для создания 64-разрядного целого может быть сделано с помощью инструкции MUL, в результате чего 64-разрядный без знака в EDX:EAX или 128-разрядный результат в паре RDX:RAX. Однако умножение двух 64-разрядных целых чисел на x86 или двух 128-разрядных целых чисел на x64-это не та же история. Добавление 64-разрядных целых чисел на x86 требует нескольких инструкций поскольку флаг переноса из регистра в регистр касается только LSB или MSB, но 64-разрядное умножение требует БОЛЬШОЕ инструкций. вот пример 32x64=>64-разрядная x86 подписанная сборка multiply для x86:
movl 16(%ebp), %esi ; get y_l
movl 12(%ebp), %eax ; get x_l
movl %eax, %edx
sarl , %edx ; get x_h, (x >>a 31), higher 32 bits of sign-extension of x
movl 20(%ebp), %ecx ; get y_h
imull %eax, %ecx ; compute s: x_l*y_h
movl %edx, %ebx
imull %esi, %ebx ; compute t: x_h*y_l
addl %ebx, %ecx ; compute s + t
mull %esi ; compute u: x_l*y_l
leal (%ecx,%edx), %edx ; u_h += (s + t), result is u
movl 8(%ebp), %ecx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
x86 поддерживает сопряжение двух регистров для хранения полного результата умножения (включая высокую половину), но вы не можете использовать два регистра для выполнения задачи 64-разрядного ALU. Это основная причина, почему программное обеспечение x64 работает быстрее, чем программное обеспечение x86: вы можете сделать работу в одной инструкции! Вы можете себе представить, что 128-битное умножение в режиме x86 было бы очень вычислительно дорого,это. x64 очень похож на x86, за исключением того, что в два раза больше бит.
архитектурные регистры x86
64-разрядной архитектуры регистров
когда пары процессоров 2 регистры размера слова чтобы создать одно значение размера двойного слова, в стеке результирующее значение двойного слова будет выровнено по границе слова в ОЗУ. Помимо двух регистровых пар, четырехсловная математика-это программный Хак. Это означает, что для x64 два 64-разрядных регистра могут быть объединены для создания 128-разрядного переполнения пары регистров, которое выравнивается по 64-разрядной границе слова в ОЗУ, но 128x128=>128-разрядная математика-это программный Хак.
x86 / x64, однако, является суперскалярный процессор, и регистры вы знаете лишь архитектурные регистры. За кулисами есть намного больше регистров, которые помогают оптимизировать конвейер ЦП для выполнения инструкций по порядку с использованием нескольких ALUs. Хотя x64 не может быть 128-битным процессором, SSE / SSE2 ввел собственную 128-битную математику, AVX ввел 256-битную собственную целочисленную математику, а AVX2 ввел 512-битную целочисленную математику. При возврате из функций вы вернете значение в 128-битный регистр XMM0 SSE/SSE2, 256-битный AVX приводит к YMM0, а 512-битный AVX2 приводит к ZMM0; однако это дополнения к x86 / x64, а не основная архитектура и поддержка полностью зависит от компилятора и платформы выпуска (например, Python).
Короткий Ответ:
способ, которым приложения C++ будут обрабатывать 128-битные целые числа, будет отличаться в зависимости от операционной системы или голого металла, вызывающего соглашение. У Microsoft есть свое собственное соглашение, которое, к моему собственному разочарованию, приводит к 128-битному возвращению значение НЕ МОГУ возвращается из функции как одно значение. The соглашение о вызовах Microsoft x64 диктует, что при возврате значения вы можете вернуть одно 64-разрядное целое число или два 32-разрядных целых числа. Например, вы можете сделать word * word = dword
, но в Visual-C++ вы должны использовать _umul128 чтобы вернуть HighProduct, независимо от того, что это пара int he RDX:RAX. Я плакала, мне было грустно. :- (The System-V вызов конвенции, позволяет возврат 128-битных типов возврата в RAX: RDX. Однако архитектурные регистры CPU НЕ полностью поддерживает 128-битную целочисленную математику, это SIMD расширения векторной обработки, которые начались с SSE/SSE2.
Что касается того, следует ли рассчитывать на 128-битную целочисленную поддержку, крайне редко можно встретить пользователя, использующего 32-битный процессор x86, потому что они слишком медленные, поэтому не рекомендуется разрабатывать программное обеспечение для работы на 32-битных процессорах x86, потому что это увеличивает затраты на разработку и могут привести к ухудшению пользовательского опыта; ожидайте Athlon 64 или Core 2 Duo до минимальной спецификации. Вы можете ожидать, что код не будет работать так же хорошо в Microsoft, как в ОС Unix.
регистры архитектуры Intel установлены в камне, но Intel и AMD постоянно развертывают новые расширения архитектуры, но компиляторы и приложения занимают много времени, чтобы обновить вы не можете рассчитывать на него для кросс-платформенной. Вы захотите прочитать архитектура Intel 64 и IA-32 Руководство разработчика программного обеспечения и руководство программистов AMD64.