Я просто использовал ~ 1 миллиард в качестве счетчика для a z-index
в CSS, и думал о сравнениях, которые должны продолжаться. Есть ли разница в производительности на уровне ALU при сравнении очень больших чисел с очень маленькими?
Например, будет ли один из этих двух фрагментов более дорогим, чем другой?
snippet 1
for (int i = 0; i < 10000000; i++){
if (i < 10000000000000) {
//do nothing
}
}
snippet 2
for (int i = 0; i < 10000000; i++){
if (i < 1000) {
//do nothing
}
}
performance
cpu
Viziionary
источник
источник
CMP
машинная инструкция медленнее, еслиi
она больше.Ответы:
Каждый процессор, над которым я работал, сравнивает, вычитая один из операндов из другого, отбрасывая результат и оставляя только флаги процессора (ноль, отрицание и т. Д.). Поскольку вычитание выполняется как одна операция, содержимое операндов не имеет значения.
Лучший способ наверняка ответить на вопрос - это скомпилировать ваш код в сборку и ознакомиться с документацией целевого процессора для получения сгенерированных инструкций. Для текущих процессоров Intel это будет Руководство разработчика программного обеспечения для архитектуры Intel 64 и IA-32 .
Описание инструкции
CMP
(«сравнить») приведено в томе 2А на стр. 3-126 или на стр. 618 документа PDF и описывает ее работу следующим образом:Это означает, что второй операнд при необходимости расширяется до знака, вычитается из первого операнда и результат помещается во временную область в процессоре. Затем флаги состояния устанавливаются так же, как и для
SUB
инструкции («вычитать») (стр. 1492 в PDF).В документации
CMP
илиSUB
документации нет упоминания о том, что значения операндов имеют какое-либо отношение к задержке, поэтому любое значение, которое вы используете, является безопасным.источник
Это очень маловероятно, если переход от маленького числа к большому не изменит ваш числовой тип, скажем, с a
int
на along
. Даже в этом случае разница может быть незначительной. Вы, скорее всего, увидите разницу, если ваш язык программирования тихо переключается на арифметику произвольной точности под прикрытием.Тем не менее, ваш конкретный компилятор может выполнять некоторые умные оптимизации, о которых вы не знаете. То, как вы узнаете, это измерить. Запустите профилировщик своего кода; посмотрите, какие сравнения занимают больше всего времени. Или просто запустить и остановить таймер.
источник
Многие процессоры имеют «маленькие» инструкции, которые могут выполнять арифметические операции, в том числе сравнения, с некоторыми непосредственно указанными операндами. Операнды, отличные от этих специальных значений, должны либо использовать больший формат инструкции, либо, в некоторых случаях, должны использовать инструкцию «загрузить значение из памяти». Например, в наборе команд ARM Cortex-M3 есть как минимум пять способов сравнить значение с константой:
Первая форма самая маленькая; вторая и третья формы могут выполняться или не выполняться так быстро, в зависимости от скорости памяти, из которой извлекается код. Четвертая форма формы почти наверняка будет медленнее, чем первые три, а пятая форма еще медленнее, но последняя может использоваться с любым 32-разрядным значением.
На старых процессорах x86 короткие инструкции сравнения будут выполняться быстрее, чем длинные, но многие новые процессоры преобразуют длинные и короткие формы в одно и то же представление при первом извлечении и сохраняют это унифицированное представление в кеше. Таким образом, хотя встроенные контроллеры (подобные тем, что установлены на многих мобильных платформах) будут иметь разницу в скорости, многие компьютеры на базе x86 не будут.
Также обратите внимание, что во многих случаях, когда константа интенсивно используется в цикле, компилятору нужно загружать константу в регистр только один раз - до запуска цикла - рендеринг временных различий не имеет значения. С другой стороны, в некоторых ситуациях, даже в маленьких циклах, это не всегда происходит; если цикл небольшой, но интенсивно исполняемый, иногда может быть большая производительность между сравнениями, включающими короткие непосредственные значения, и сравнениями, включающими более длинные.
источник
Короткий ответ на этот вопрос: нет , нет никакой разницы во времени для сравнения двух чисел на основе величины этих чисел, если предположить, что они хранятся в одном и том же типе данных (например, оба 32-разрядных целых или оба 64-разрядных длинных).
Кроме того, до размера слова ALU невероятно маловероятно, что сравнение двух целых чисел когда-либо займет более 1 такта, поскольку это тривиальная операция, эквивалентная вычитанию. Я думаю, что каждая архитектура, с которой я когда-либо имел дело, имела целочисленное сравнение с одним циклом.
Единственные случаи, о которых я могу вспомнить, с которыми я столкнулся, когда сравнение двух чисел не было операцией с одним циклом, следующие:
источник
@ RobertHarvey ответ хороший; Считайте этот ответ дополнением к своему.
Вы должны также рассмотреть предсказание ветвления :
По сути, в вашем примере, если
if
оператор внутри цикла всегда возвращает один и тот же ответ, тогда система может оптимизировать его, правильно угадав, в какую сторону он будет переходить. В вашем примере, посколькуif
оператор в первом случае всегда возвращает один и тот же результат, он будет выполняться немного быстрее, чем во втором случае.Отличный вопрос переполнения стека
источник
Это зависит от реализации, но это будет очень, очень маловероятно .
Я признаю, что я не читал подробности реализации различных движков браузера, и CSS не определяет какой-либо конкретный тип хранения для чисел. Но я считаю, что можно с уверенностью предположить, что все основные браузеры используют 64-битные числа с плавающей запятой двойной точности («doubles», чтобы позаимствовать термин из C / C ++) для удовлетворения большинства своих числовых потребностей в CSS потому что это то, что JavaScript использует для чисел, и поэтому использование одного и того же типа облегчает интеграцию.
С точки зрения компьютера, все двойники несут одинаковое количество данных: 64 бита, независимо от того, равно ли это значение 1 или -3,14 или 1000000 или 1e100 . Время, необходимое для выполнения операции над этими числами, не зависит от фактического значения этих чисел, потому что оно всегда работает с одним и тем же объемом данных. Таким способом можно найти компромисс: двойные числа не могут точно представлять все числа (или даже все числа в пределах их диапазона), но они могут быть достаточно близки для большинства вопросов, а виды вещей, которые CSS делает не численно достаточно требовательна, чтобы нуждаться в большей точности. Объедините это с преимуществами прямой совместимости с JavaScript, и вы получите достаточно веские аргументы в пользу двойных чисел.
Не исключено, что кто-то может реализовать CSS с использованием кодирования переменной длины для чисел. Если бы кто-то использовал кодирование переменной длины, то сравнение с небольшими числами было бы дешевле, чем сравнение с большими числами, потому что большие числа имеют больше данных для обработки . Эти виды кодирования могут быть более точными, чем двоичные, но они также намного медленнее, и, в частности, для CSS, прироста точности, вероятно, недостаточно, чтобы стоить потери производительности. Я был бы очень удивлен, узнав, что любой браузер так поступает.
Теперь, теоретически, есть одно возможное исключение из всего, что я сказал выше: сравнение с нулем часто происходит быстрее, чем сравнение с другими числами . Это не потому, что ноль является коротким (если это было причиной, то 1 должен быть таким же быстрым, но это не так). Это потому, что ноль позволяет вам обманывать. Это единственное число, где все биты выключены, поэтому, если вы знаете, что одно из значений равно нулю, вам даже не нужно рассматривать другое значение как число: если какой-либо из битов включен, то он не равен ноль, и тогда вам нужно только взглянуть на один бит, чтобы увидеть, больше или меньше нуля.
источник
Если бы этот код интерпретировался каждый раз, когда он выполнялся, было бы различие, поскольку для токенизации и интерпретации требуется больше времени по
10000000000000
сравнению с1000
. Тем не менее, это очевидная первая оптимизация интерпретаторов в этом случае: токенизировать один раз и интерпретировать токены.источник