12 ответов:
деление по степеням 2 быстрее с
unsigned int, потому что его можно оптимизировать в одиночную инструкцию переноса. Сsigned int, это обычно требует больше машинных инструкций, потому что деление раундов к нулю, но сдвиг вправо раундов вниз. Пример:int foo(int x, unsigned y) { x /= 8; y /= 8; return x + y; }здесь есть соответствующие
xчасть (подпись отдела):movl 8(%ebp), %eax leal 7(%eax), %edx testl %eax, %eax cmovs %edx, %eax sarl , %eaxа вот и соответствующие
yчасть (беззнаковое деление):movl 12(%ebp), %edx shrl , %edx
в C++ (и C) переполнение целого числа со знаком не определено, тогда как переполнение целого числа без знака определено для обертывания. Обратите внимание, что, например, в gcc вы можете использовать флаг-fwrapv для определения переполнения со знаком (для обертывания).
undefined signed integer overflow позволяет компилятору предположить, что переполнения не происходит, что может ввести возможности оптимизации. См., например,этот блог для обсуждения.
Это будет зависеть от конкретной реализации. Однако в большинстве случаев разницы не будет. Если вы действительно заботитесь, вы должны попробовать все варианты, которые вы рассматриваете и измеряете производительность.
unsignedприводит к той же или лучшей производительности, чемsigned. Некоторые примеры:
- деление на константу, которая является степенью числа 2 (см. Также ответ от FredOverflow)
- деление на постоянное число (например, мой компилятор реализует деление на 13, используя 2 инструкции asm для unsigned и 6 инструкций для signed)
- проверка четности числа (я понятия не имею, почему мой компилятор MS Visual Studio реализует его с 4 инструкции для
signednumbers; gcc делает это с 1 инструкцией, как и вunsignedcase)
shortобычно приводит к той же или худшей производительности, чемint(еслиsizeof(short) < sizeof(int)). Снижение производительности происходит, когда вы назначаете результат арифметической операции (которая обычноint, неshort) к переменной типаshort, который хранится в регистре процессора (который тоже типаint). Все преобразования отshortдоintнайдите время и раздражает.Примечание: некоторые DSPs имеют быстрые инструкции умножения для
signed shortтип, в данном конкретном случаеshortбыстрееint.что касается разницы между
intиlong, я могу только догадываться (я не знаком с 64-разрядными архитектурами). Конечно, еслиintиlongимеют одинаковый размер (на 32-битных платформах), их производительность также то же самое.
очень важное дополнение, отмеченное несколькими людьми:
что действительно важно для большинства приложений объем памяти и используемая пропускная способность. Вы должны использовать наименьшие необходимые целые числа (
short, может быть, дажеsigned/unsigned char) для больших массивов.это даст лучшую производительность, но коэффициент усиления нелинейный (т. е. не в 2 или 4 раза) и несколько непредсказуемый - это зависит от размера кэша и отношения между вычислениями и передачей памяти в вашем приложение.
Это в значительной степени зависит от конкретного процессора.
на большинстве процессоров существуют инструкции для арифметики со знаком и без знака, поэтому разница между использованием целых чисел со знаком и без знака сводится к тому, какой из них использует компилятор.
Если какой-либо из них быстрее, он полностью зависит от процессора, и, скорее всего, разница незначительна, если она вообще существует.
разница в производительности между знаковыми и беззнаковыми целыми числами на самом деле более общая, чем предполагает ответ на принятие. Деление целого числа без знака на любую константу может быть выполнено быстрее, чем деление целого числа со знаком на константу, независимо от того, является ли константа степенью двойки. См.http://ridiculousfish.com/blog/posts/labor-of-division-episode-iii.html
В конце своего поста, он включает в себя следующий раздел:
естественный вопрос заключается в том, может ли одна и та же оптимизация улучшить подписанное разделение; к сожалению, похоже, что это не так по двум причинам:
приращение дивиденда должно стать увеличением величины, т. е. приращением, если n > 0, уменьшением, если n
штраф за отказ от сотрудничества делителя составляет только около половины от подписанного деления, оставляя меньшее окно для улучшений.
таким образом, похоже, что алгоритм округления может быть выполнен для работы в подписанном подразделении, но будет недостаточно эффективен стандартный алгоритм округления.
короче говоря, не беспокойтесь перед фактом. Но потрудитесь после.
если вы хотите иметь производительность должны использовать оптимизацию производительности компилятора который может работать против здравого смысла. Следует помнить, что разные компиляторы могут компилировать код по-разному, и сами они имеют разные виды оптимизации. Если мы говорим о
g++компилятор и говорить о максимизации это уровень оптимизации с помощью-Ofast, или, по крайней мере Ан-O3флаг, по моему опыту она может составлятьlongвведите в код с еще лучшей производительностью, чем любойunsignedтип, или даже простоint.это из моего собственного опыта, и я рекомендую вам сначала написать свою полную программу и заботиться о таких вещах только после этого, когда у вас есть фактический код на ваших руках, и вы можете скомпилировать его с оптимизацией, чтобы попытаться выбрать типы, которые на самом деле работают лучше всего. Это также хорошее очень общее предложение о коде оптимизация для повышения производительности, писать быстро во-первых, попробуйте компиляцию с оптимизацией, настроить вещи, чтобы увидеть, что работает лучше всего. И вы также должны попробовать использовать различные компиляторы для компиляции вашей программы и выбрать тот, который выводит наиболее производительный машинный код.
оптимизированная многопоточная Программа расчета линейной алгебры может легко иметь > 10x разница в производительности точно оптимизированный против неоптимизированного. Так что это имеет значение.
выход оптимизатора противоречит логике во многих случаях. Например, у меня был случай, когда разница между
a[x]+=bиa[x]=bизменено время выполнения программы почти в 2 раза. И нет,a[x]=bне был более быстрым.вот например NVIDIA с указанием что за Программирование их графических процессоров:
Примечание: как уже было рекомендовано лучшей практикой, подписанная арифметика должно быть предпочтительнее беззнаковой арифметики, где это возможно для лучшая пропускная способность на SMM. с языковой стандарт размещает больше ограничения на поведение переполнения для неподписанной математики, ограничение компилятора возможности оптимизации.
не только деление на степени 2 быстрее с беззнаковым типом, деление на любые другие значения также быстрее с беззнаковым типом. Если вы посмотрите на таблицы инструкций Agner Fog вы увидите, что неподписанные подразделений имеют аналогичную или лучшую производительность, чем подписанные версии
например, с AMD K7
╔═════════════╤══════════╤═════╤═════════╤═══════════════════════╗ ║ Instruction │ Operands │ Ops │ Latency │ Reciprocal throughput ║ ╠═════════════╪══════════╪═════╪═════════╪═══════════════════════╣ ║ DIV │ r8/m8 │ 32 │ 24 │ 23 ║ ║ DIV │ r16/m16 │ 47 │ 24 │ 23 ║ ║ DIV │ r32/m32 │ 79 │ 40 │ 40 ║ ║ IDIV │ r8 │ 41 │ 17 │ 17 ║ ║ IDIV │ r16 │ 56 │ 25 │ 25 ║ ║ IDIV │ r32 │ 88 │ 41 │ 41 ║ ║ IDIV │ m8 │ 42 │ 17 │ 17 ║ ║ IDIV │ m16 │ 57 │ 25 │ 25 ║ ║ IDIV │ m32 │ 89 │ 41 │ 41 ║ ╚═════════════╧══════════╧═════╧═════════╧═══════════════════════╝то же самое относится и к Intel Pentium
╔═════════════╤══════════╤══════════════╗ ║ Instruction │ Operands │ Clock cycles ║ ╠═════════════╪══════════╪══════════════╣ ║ DIV │ r8/m8 │ 17 ║ ║ DIV │ r16/m16 │ 25 ║ ║ DIV │ r32/m32 │ 41 ║ ║ IDIV │ r8/m8 │ 22 ║ ║ IDIV │ r16/m16 │ 30 ║ ║ IDIV │ r32/m32 │ 46 ║ ╚═════════════╧══════════╧══════════════╝конечно, они довольно древние. Новые архитектуры с большим количеством транзисторы могут закрыть зазор, но применяются основные вещи: как правило, вам нужно больше макро-операций, больше логики, больше латентности для выполнения подписанного деления
традиционно
int- Это собственный целочисленный формат целевой аппаратной платформы. Любой другой целочисленный тип может привести к снижению производительности.EDIT:
В современных системах все немного по-другому:
intможет на самом деле быть 32-разрядной на 64-разрядных системах по причинам совместимости. Я считаю, что это происходит в системах Windows.современные компиляторы могут неявно использовать
intпри выполнении вычисления для более коротких типов в некоторых случаях.
IIRC, на x86 signed / unsigned не должно иметь никакого значения. С другой стороны, Short/long-это другая история, поскольку объем данных, который должен быть перемещен в/из ОЗУ, больше для longs (другие причины могут включать операции приведения, такие как расширение короткого до длинного).
беззнаковое целое число выгодно тем, что вы храните и обрабатываете оба как битовый поток, я имею в виду просто данные, без знака, поэтому умножение, деление становится проще (быстрее) с операциями сдвига битов
подписанные и беззнаковые целые числа всегда будут работать как одиночные инструкции часов и иметь одинаковую производительность чтения-записи, но в соответствии с Доктор Андрей Александреску unsigned предпочтительнее, чем signed. Причина этого заключается в том, что вы можете поместить в два раза больше чисел в одном и том же количестве битов, потому что вы не тратите бит знака, и вы будете использовать меньше инструкций, проверяющих отрицательные числа, что приводит к увеличению производительности от уменьшенного ПЗУ. По моему опыту с элемент Кабуки VM, который отличает ультра-высокой производительностью скрипт реализация, это редко, что вы на самом деле требуется подписанный номер при работе с памятью. Я провел майские годы, делая арифметику указателя со знаковыми и беззнаковыми числами, и я не нашел никакой пользы для подписанного, когда не нужен знаковый бит.
где знак может быть предпочтительным при использовании сдвига битов для выполнения умножения и деления степеней 2, потому что вы можете выполнить отрицательный полномочия 2-го деления со знаком 2-х дополняют целые числа. Пожалуйста, смотрите некоторые больше видео на YouTube от Андрей для получения дополнительных методов оптимизации. Вы также можете найти хорошую информацию в моей статье о самый быстрый в мире алгоритм преобразования целого числа в строку.
Comments