Если бы мне пришлось писать ассемблерный код для больших целочисленных вычислений (например, простой факторинг, вычисления по модулю и т. д.) с упором на скорость, какая архитектура лучше всего подходит для этого: x86 (-64), ARM, PowerPC, MIPS или другие. ?
Какая архитектура процессора лучше всего подходит для арифметики с большими целыми числами?
Ответы (2)
Если вы работаете с небольшим количеством чисел переменного размера, я думаю, что POWER 6 лучше всего подойдет для ваших нужд (хотя я не работал с этой архитектурой), поскольку он обеспечивает высокий IPC и очень высокую частоту (до 5 ГГц).
Если вы работаете с большим количеством чисел фиксированного размера, x86-64 будет лучшим выбором, так как он имеет SIMD-операции, которые работают с 64-битными числами, и вы можете использовать эти операции для ускорения длинных арифметических операций с несколькими числами. Скорее всего, вам понадобится ЦП с поддержкой SSE 4.2 (Intel Nehalem/Westmere/Sandy Bridge или грядущий AMD Bulldozer), поскольку 64-битная инструкция сравнения PCMPGTQ была добавлена только в SSE 4.2.
Кроме того, вам могут быть интересны эти результаты сравнительного анализа GMP.
IMO ничто не сравнится с x86-64, потому что никто не заботится о высокоточной арифметике
Многие архитектуры RISC, такие как MIPS, DEC Alpha или RISC-V, не имеют регистра флагов, поэтому для получения переноса вам потребуется отдельная инструкция. Поэтому они являются плохим выбором и устраняются сразу. Например, чтобы сделать a += b
в MIPS, вам нужно
addu aLow, aLow, bLow # aLow += bLow
sltu tmp, aLow, bLow # carry: tmp = (aLow < bLow)
addu aHigh, aHigh, bHigh # aHigh += bHigh
addu aHigh, aHigh, tmp # aHigh += carry
С флагом переноса вам нужно всего 2 инструкции: add aLow, bLow; adc aHigh, bHigh
Разработчики MIPS могли бы сделать это лучше, но не
Более высокие часы помогают, как сказал Марко ван де Воорт, но эти архитектуры не имеют на 50%-100% более быстрых часов, чем эквивалент x86. Остальные вещи, которые он сказал, довольно неверны. Важно отметить, что математика произвольной точности не может быть тривиально распараллелена, поэтому
- Суперскаляр (больше ALU) не очень помогает из-за цепочки зависимостей, которая не позволяет выполнять инструкции параллельно.
- Несколько ядер и/или несколько сокетов также относительно бесполезны по той же причине.
- SIMD also won't generally help‡, because it's meant for processing multiple separate pieces of data and not a single big large integer. You don't have any way to propagate the carry from the lower limb to the next one. See
Вкратце: Вы действительно хотите вычислить переносы параллельно, что очень сложно.
В мире x86 у вас уже есть флаг переноса с самого начала. Но позже Intel представила набор инструкций ADX с новыми инструкциями ADOX, ADCX и MULX для еще большего ускорения арифметики больших целых чисел. Как они помогают, объясняется в документе Intel Новые инструкции, поддерживающие арифметику больших целых чисел на процессорах с архитектурой Intel
Но не только ADX делает x86 быстрым. Как я упоминал ранее (‡), SIMD на самом деле не помогает, но в настоящее время на x86 все может быть по-другому. У нас есть очень длинные векторы в x86 (256 бит с AVX2, 512 бит с AVX512 и, возможно, больше в будущем), поэтому, если вы используете различные приемы, такие как использование арифметики неполных слов для задержки распространения переноса, или расположите слова странным образом (например, llhhllhhllhhllhh
) вместо линейного, как в обычной арифметике больших целых чисел (llllllllhhhhhhhh
), тогда SIMD может быть быстрее, чем скалярные операции. Для получения дополнительной информации вы должны прочитать
- Могут ли преимущества SSE для подпрограмм с длинными целыми числами?
- возможно использование BigNum AVX/SSE?
- Добавление вектора Когге-Стоуна
Конечно, AVX512 поможет, только если у вас очень большие числа. В противном случае для 512-битного числа у вас могут быть лучшие результаты со скалярным кодом.
Никакие другие архитектуры в настоящее время не имеют регистров SIMD длиннее 128 бит, поэтому, даже если вы можете использовать SIMD на них, стоимость вычисления переноса намного перевешивает стоимость параллельного сложения. Опять же, это причина, по которой x86 побеждает их всех.
__int128 * __int128
меньше инструкций, чем на x86-64: godbolt.org/z/K1M_ZA
- person Peter Cordes; 01.05.2019
mulx r64
(2 мкп) не значительно дешевле, чем POWER64 mulld
(64x64=>64) + mulhdu
(64x64=> высокая 64).
- person Peter Cordes; 01.05.2019
pmull - Polynomial Multiply Long instructions (PMULL/PMULL2)
от ARM звучит интригующе en.wikichip.org/wiki/arm/armv8. Сегодня я получил сервер ARM Cavium ThunderX2 с pmull, поэтому я начинаю изучать технологии ARM.
- person Z boson; 02.05.2019