2010-03-03 3 views
6

Что в среднем быстрее - проверьте значение, если необходимо, назначьте или просто назначьте? Или, в терминах C++:Прочитайте тогда условную запись против записи

bool b; 
if(b) 
    b = false; 

или

b = false; 

Предположим, что если() условие истинно с 50% вероятностью. Ответ будет, скорее всего, сильно зависимым от архитектуры - пожалуйста, выскажите свои соображения низкого уровня. Написание всегда dirtties строки кэша - правильно? Поэтому, избегая записи, мы избегаем сброса кеша в 0,5 случаях. Но достаточно умный кеш может обнаружить тривиальную запись, а не грязную. Но безусловная запись - это всегда одна операция с памятью, а чтение-запись - в среднем 1,5 операции.

Отказ от ответственности: это вопрос любопытства, а не проблема, с которой я действительно сталкиваюсь.

+0

логически имеет значение, что такое b, если они заканчиваются, что b должен быть ложным? –

+0

@Fuzzy: речь идет об оптимизации, а не о логике. –

+0

да, но второй легче читать и рассказывать, что на мой взгляд. – Earlz

ответ

4

Филиалы стоят дорого на современных процессорах, а доступ к памяти дорог на встроенных/старых процессорах. Таким образом, квартира только что правопреемником всегда будет быстрее, если у вас есть какой-то своего рода странные памяти, что занимает больше времени, чтобы написать, чем чтение (подсказка: вы не)

Это хуже, по этим причинам именно:

  • Инструкция ветвления. Это может быть предсказано процессором, но оно по-прежнему несет дополнительную возможность.
  • 2 доступа к памяти вместо 1. Чтение и запись на большинстве форм памяти - это одна и та же скорость, так почему же это делать дважды, когда вы можете сделать это один раз?
  • Дополнительные накладные расходы. это микро один, но требуется больше инструкций для выполнения инструкции if.Таким образом, это означает, что чтение дополнительной пары памяти и лишнее пространство в кэше излишне потребляются.
  • И пессимистический, это может означать, что компилятор C++ решает поставить эту переменную в регистр вместо других более необходимых переменных ..
  • Кроме того, если предположить, что b помещается в регистр. Регистрация чтения/записи очень дешевы, но они не свободны ..
+0

Хороший вопрос о предсказании ветви (mis); он по-прежнему применяется на процессорах ARM, где if(), как это, реализованы без какого-либо ветвления? –

+0

Он все равно будет медленнее из-за чтения дополнительной памяти. Даже если у вас есть какая-то волшебная команда «read-and-set-false-if-true», процессор все равно должен прочитать значение из памяти, чтобы проверить, если это правда. А для ветвления на ARM нет, ветви промахов действительно не применяются для условного присвоения. в x86 'ccmov' не имеет ветви, я не верю. – Earlz

+0

Итак, большой провал R-W - неверное предсказание ветвления - не применяется к ARM. Большой downer W-cache flush - все еще делает, не так ли? –

1

Было бы целесообразно профилировать это на разных архитектурах, чтобы получить фактические результаты.

1

Это зависит от различных факторов:

  • как предсказуемый ветвь (в первом случае)
  • ли б уже в регистре
  • какая архитектура используется
1

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

0

Если вы выполняете присвоение указателя, ссылочного или базового значения типа, я лично считаю, что прямое назначение будет быстрее (желание увидеть результат на профилировщике). В 50% -ной вероятностной среде вы сможете выполнить намного больше инструкций, которые помещают значение в регистр. Назначение объекта struct или класса, запускающего оператор присваивания, будет самым дорогостоящим. Условная логика также вводит больше инструкций и добавляет к метрикам сложности кода.

1

Недавно я читал статьи по очень быстрым методам сжатия, и ребята подчеркнули необходимость избегать ветвления, чтобы добиться максимальной производительности. Причиной этого является конвейерная обработка CPU. Использование if s разбивает много оптимизаций, которые процессор может выполнять для параллельного выполнения частей кода. Итак, если у вас было много таких операций, возможно, было бы быстрее использовать b = false.

1

На современном конвейерного процессора вы должны принять это во внимание:

  • ошибочные ветви стоит много
  • хранилища и нагрузки занимают много времени
  • кеши могут ускорять как чтение, так и запись, но если это архитектура с несколькими кешами и b изменяется в более чем одном кеше, многократные записи могут означать выселение нескольких кешей и могут компенсировать производительность кэша.

чтение с условной записью имеет по крайней мере, один доступа памяти и ветвь, которая может mispredict. Предполагая, что ветвь занята в 50% случаев, у вас в среднем 1,5 обращения к памяти, плюс вероятность ошибочного предсказания.

Безусловная запись имеет точно один доступ к памяти и никакой ветви вообще.

Теперь вам нужно сбалансировать стоимость неправильного прогнозирования со стоимостью магазина, которая изменяется в зависимости от того, сколько у вас кеш-агентов.

+0

Приятный расчет! – pajton