Как влияет производительность на преобразование в bool в C ++? - PullRequest
44 голосов
/ 16 октября 2008

[Этот вопрос относится, но не совпадает с к этому .]

Мой компилятор предупреждает о неявном преобразовании или приведении определенных типов к типу bool, тогда как явные преобразования не выдают предупреждение:

long t = 0;
bool b = false;
b = t;                    // performance warning: forcing long to bool
b = (bool)t;              // performance warning
b = bool(t);              // performance warning
b = static_cast<bool>(t); // performance warning
b = t ? true : false;     // ok, no warning
b = t != 0;               // ok
b = !!t;                  // ok

Это с Visual C ++ 2008, но я подозреваю, что другие компиляторы могут иметь похожие предупреждения.

Итак, мой вопрос: каково влияние приведения / преобразования на bool на производительность? Имеет ли явное преобразование лучшую производительность в некоторых обстоятельствах (например, для определенных целевых архитектур или процессоров)? Неявное преобразование каким-то образом сбивает с толку оптимизатор?

Microsoft объяснение их предупреждения не особенно полезно. Они подразумевают, что есть веская причина, но не объясняют ее.

Ответы [ 11 ]

36 голосов
/ 16 октября 2008

Я был озадачен этим поведением, пока не нашел эту ссылку:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633

Судя по всему, разработчик Microsoft, которому принадлежит это предупреждение:

Это предупреждение удивительно полезно, и нашел ошибку в моем коде только вчера. Я думаю, что Мартин снятие «предупреждения о производительности» из контекст.

Дело не в сгенерированном коде, речь идет о том или нет программист дал понять намерение изменить значение с int на bool . За это есть штраф, и у пользователя есть выбор использовать "int" вместо "bool" последовательно (или скорее наоборот), чтобы избежать «Разрушающий» кодоген. [...]

Это старое предупреждение, и может иметь отжил свою цель, но это ведёт себя так, как задумано.

Так что мне кажется, что предупреждение больше о стиле и об избегании некоторых ошибок, чем чего-либо еще.

Надеюсь, это ответит на ваш вопрос ...

: - р

12 голосов
/ 16 октября 2008

Производительность одинакова по всем направлениям. Он включает в себя пару инструкций для x86, а может быть 3 для некоторых других архитектур.

На x86 / VC ++ все они делают

cmp DWORD PTR [whatever], 0
setne al

GCC генерирует то же самое, но без предупреждений (на любом уровне предупреждений).

5 голосов
/ 16 октября 2008

Предупреждение о производительности действительно имеет немного смысла. У меня это тоже было, и мое любопытство привело меня к расследованию с дизассемблером. Он пытается сказать вам, что компилятор должен сгенерировать некоторый код, чтобы привести значение к 0 или 1. Поскольку вы настаиваете на bool, идея старой школы C о 0 или что-либо еще не применима.

Вы можете избежать этого крошечного удара производительности, если действительно хотите. Лучший способ - полностью избежать каста и использовать bool с самого начала. Если у вас должен быть int, вы можете просто использовать if (int) вместо if (bool). Сгенерированный код будет просто проверять, является ли int 0 или нет. Нет дополнительного кода, который бы гарантировал, что значение 1, если оно не равно 0, будет сгенерировано.

3 голосов
/ 16 октября 2008

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

3 голосов
/ 16 октября 2008

Насколько я знаю, ни один другой компилятор не предупреждает об этом. Единственный способ, которым я могу думать, что это может привести к снижению производительности, - это то, что компилятор должен сравнить все целое число с 0 и затем соответствующим образом назначить bool (в отличие от преобразования, такого как char, в bool, где результат может быть скопирован, потому что bool - это один байт, и поэтому они фактически одинаковы), или интегральное преобразование, которое включает в себя копирование части или всего источника в место назначения, возможно, после нуля места назначения, если оно больше источника (с точки зрения памяти) .

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

template <typename T>
inline bool to_bool (const T& t)
  { return t ? true : false; }
1 голос
/ 30 июня 2009
long t;
bool b;
int i;
signed char c;
...

Вы получаете предупреждение, когда делаете что-либо, что было бы «свободным», если bool не требовалось быть 0 или 1. b = !! t эффективно присваивает результат (встроенный язык, не переопределяемый ) bool operator!(long)

Вы не должны ожидать! или! = операторы, которые обходятся без инструкций asm даже с оптимизирующим компилятором. Обычно верно, что int i = t обычно полностью оптимизируется. Или даже со знаком char c = t; (в x86 / amd64, если t находится в регистре% eax, после c = t использование c означает просто использование% al. amd64 имеет байтовую адресацию для каждого регистра, BTW. IIRC, в x86 некоторые регистры не имеют байтовой адресации .)

В любом случае, b = t; i = b<code>; isn't the same as <code>c = t; i = c; это i = !! t; вместо i = t & 0xff ;

Err, я думаю, что все уже знают все это из предыдущих ответов. С моей точки зрения, предупреждение имело смысл для меня, так как оно обнаруживало случаи, когда компилятору приходилось делать то, о чем вы на самом деле не говорили, например !! BOOL при возврате, потому что вы объявили функцию bool, но возвращаете целое значение это может быть правдой и! = 1. например много вещей из окон возвращает BOOL (int).

Это одно из немногих предупреждений MSVC, которого нет в G ++. Я гораздо больше привык к g ++, и он определенно предупреждает о вещах, которых нет в MSVC, но я рад, что рассказал мне об этом. Я написал заголовочный файл portab.h с заглушками для используемых MFC / Win32 классов / макросов / функций. Получилось приложение MFC, над которым я работаю для компиляции на моем компьютере с GNU / Linux дома (и с cygwin). В основном я хотел иметь возможность компилировать-тестировать то, над чем я работал дома, но в итоге я нашел предупреждения g ++ очень полезными. Это также намного строже, например. шаблоны ...

В целом по bool я не уверен, что это улучшает код при использовании в качестве возвращаемых значений и передачи параметров. Даже для местных жителей g ++ 4.3, похоже, не понимает, что ему не нужно приводить значение к 0 или 1, прежде чем переходить на него. Если это локальная переменная, и вы никогда не берете ее адрес, компилятор должен сохранять ее в любом размере, который является самым быстрым. Если он должен пролить его из регистров в стек, он также может хранить его в 4 байтах, поскольку это может быть немного быстрее. (Он использует много инструкций movsx (расширение-знак) при загрузке / хранении (нелокальных) bools, но я действительно не помню, что он делал для автоматических (локальных стеков) переменных. Я помню, что это оставляло странным количество стекового пространства (не кратное 4) в функциях, которые имеют некоторые локальные переменные bools.)

Использование флагов bool было медленнее, чем int с компилятором Digital Mars D по состоянию на прошлый год: http://www.digitalmars.com/d/archives/digitalmars/D/opEquals_needs_to_return_bool_71813.html (D очень похож на C ++, но отказывается от полного обратного компиляции C, чтобы определить некоторую приятную новую семантику и хорошую поддержку метапрограммирования шаблонов. Например, «static if» или «static assert» вместо шаблонных хаков или макросов cpp. хотел бы попробовать D когда-нибудь.:)

Для структур данных это может иметь смысл, например, если вы хотите упаковать пару флагов перед int, а затем несколько удваивается в структуре, у вас будет довольно много.

0 голосов
/ 16 октября 2008

Похоже, что Microsoft объясняет это тем, что они пытаются сказать:

Эй, если вы используете int, но хранить только правдивую или ложную информацию в это, сделай это булл!

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

И вы избавляетесь от некоторых грязных, маленьких забросков для загрузки.

0 голосов
/ 16 октября 2008

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

0 голосов
/ 16 октября 2008

В C ++ bool ISA int только с двумя значениями 0 = ложь, 1 = истина. Компилятор должен проверить только один бит. Чтобы быть совершенно ясным, true! = 0, так что любой int может переопределить bool, для этого достаточно просто циклов обработки.

Используя long, как в примере кода, вы выполняете намного больше проверок битов, что приведет к снижению производительности.

Нет, это не преждевременная оптимизация, просто безумие использовать код, который требует больше времени на обработку по всем направлениям. Это просто хорошая практика кодирования.

0 голосов
/ 16 октября 2008

Я не думаю, что здесь проблема в производительности. Причина, по которой вы получаете предупреждение, заключается в том, что информация теряется при преобразовании из int в bool.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...