Современные компиляторы оптимизируют x * 2 операции к x <<1?

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

32
задан Jean-François Corbett 12 September 2018 в 08:02
поделиться

12 ответов

На самом деле VS2008 оптимизирует это к x+x:

01391000  push        ecx  
    int x = 0;

    scanf("%d", &x);
01391001  lea         eax,[esp] 
01391004  push        eax  
01391005  push        offset string "%d" (13920F4h) 
0139100A  mov         dword ptr [esp+8],0 
01391012  call        dword ptr [__imp__scanf (13920A4h)] 

    int y = x * 2;
01391018  mov         ecx,dword ptr [esp+8] 
0139101C  lea         edx,[ecx+ecx] 

В сборке x64 это еще более явно и использование:

    int y = x * 2;
000000013FB9101E  mov         edx,dword ptr [x] 

    printf("%d", y);
000000013FB91022  lea         rcx,[string "%d" (13FB921B0h)] 
000000013FB91029  add         edx,edx 

Это - желание, настройки оптимизации на 'Максимизируют скорость' (/O2)

31
ответ дан Rob Walker 27 November 2019 в 20:10
поделиться

Эта статья от Raymond Chen могла быть интересной:

, Когда x/2 отличающийся от x>> 1? : http://blogs.msdn.com/oldnewthing/archive/2005/05/27/422551.aspx

Заключение в кавычки Raymond:

, Конечно, компилятор является бесплатным распознать это и переписать Ваше умножение или операцию сдвига. На самом деле это, очень вероятно, сделает это, потому что x+x более легко pairable, чем умножение или сдвиг. Ваш сдвиг или multiply-two, вероятно, будут переписанными как что-то ближе к добавлению eax, eax инструкция.

[...]

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

(-1) / 2 в‰Ў 0
(-1)>> 1 в‰Ў-1

[...]

мораль истории должна записать то, что Вы имеете в виду. Если Вы хотите разделиться на два, то запишите "/2", не">> 1".

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

22
ответ дан paercebal 27 November 2019 в 20:10
поделиться

VS 2008 оптимизированная шахта к x < < 1.

    x = x * 2;
004013E7  mov         eax,dword ptr [x] 
004013EA  shl         eax,1 
004013EC  mov         dword ptr [x],eax 

РЕДАКТИРОВАНИЕ: Это использовало конфигурацию "Отладки" значения по умолчанию VS с отключенной оптимизацией (/Передозировка). Используя любой из переключателей оптимизации (/O1,/O2 (VS "Розничная продажа"), или Вол/) результаты в добавление сам кодируют отправленного Rob. Кроме того, просто в придачу я проверил x = x << 1, действительно рассматривается тот же путь как x = x * 2 компилятором статьи и в Передозировке / и в Воле/. Так, таким образом, версия 15.00.30729.01 cl.exe для обработок x86 * 2 и << 1 тождественно и я ожидаю, что почти все другие недавние компиляторы делают то же.

12
ответ дан C. Dragon 76 27 November 2019 в 20:10
поделиться

Не, если x является плаванием, он не будет.

11
ответ дан David Arno 27 November 2019 в 20:10
поделиться

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

5
ответ дан Adam Rosenfield 27 November 2019 в 20:10
поделиться

Ответ, "если это быстрее" (или меньше). Это зависит от целевой архитектуры в большой степени, а также модели использования регистра для данного компилятора. В целом ответ "да, всегда", поскольку это - очень простая локальная оптимизация для реализации и обычно является достойной победой.

5
ответ дан plinth 27 November 2019 в 20:10
поделиться

Это - только запуск того, что могут сделать оптимизаторы. Для наблюдения, что делает компилятор ищите переключатель, который заставляет его испускать ассемблерный источник. Для Цифровых компиляторов Марса выходной ассемблер может быть исследован с инструментом OBJ2ASM. Если Вы хотите изучить, как Ваш компилятор работает, смотрение на ассемблерный вывод может быть очень освещающим.

4
ответ дан Walter Bright 27 November 2019 в 20:10
поделиться

Я уверен, что они все делают подобную оптимизацию, но интересно, релевантны ли они все еще. Процессоры прежних модификаций сделали умножение путем смещения и добавления, который мог взять много циклов для завершения. Современные процессоры, с другой стороны, имеют ряд многорегистровых циклических сдвиговых устройств, которые могут сделать все необходимые сдвиги и дополнения одновременно в одном такте или меньше. Кто-либо на самом деле сравнил, помогает ли эта оптимизация действительно?

1
ответ дан Ferruccio 27 November 2019 в 20:10
поделиться

Да, они будут.

0
ответ дан Andy Lester 27 November 2019 в 20:10
поделиться

Если что-то не будет определено в стандарте языков, Вы никогда не будете получать гарантируемый ответ на такой вопрос. Когда в сомнении выложили Ваш компилятор, собирают код и проверку. Это будет единственным способом действительно знать.

0
ответ дан dwj 27 November 2019 в 20:10
поделиться

@Ferruccio Барлетта

Это - хороший вопрос. Я пошел, Гугля, чтобы попытаться найти ответ.

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

Таким образом я Погугленный AMD, и найденный старым руководством по оптимизации для Athlon с 2002, который перечисляет, который перечисляет самые быстрые способы умножить числа на константы между 2 и 32. Интересно, это зависит от числа. Некоторые - реклама, некоторые сдвиги. Это находится на страница 122 .

руководство для , Athlon 64 показывает то же самое (страница приблизительно 164). Это говорит, умножается, 3 (в 32-разрядном) или 4 (в 64-разрядном) операции цикла, где сдвиги равняются 1, и добавляет, 2.

кажется, что это все еще полезно как оптимизация.

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

, Но это - предположение.

0
ответ дан MBCook 27 November 2019 в 20:10
поделиться

Это зависит, на каком компиляторе Вы имеете. Visual C++, например, известно плох в оптимизации. При редактировании сообщения для высказывания, какой компилятор Вы используете, было бы легче ответить.

-9
ответ дан T.E.D. 27 November 2019 в 20:10
поделиться
Другие вопросы по тегам:

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