Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> inline и define - выбор 
:(
    Опции темы
Torsten
Дата 23.7.2008, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 10.6.2008
Где: Pskov

Репутация: нет
Всего: 7



Цитата(Riply @  23.7.2008,  17:23 Найти цитируемый пост)
Какой из этих двух вариантов (если конечно они не содержат ошибок) предпочтительней для использования ?

Использовать define для этого точно не нужно, эта замена функции и в этом случае только усложнит сопровождение и отладку.
Хотя бы вот такой код, уже приведет к неправельным действиям :
Код

_Us_SetLength(pUnicodeString, nLength+1)


Использование inline - это лишь подсказка компилятору о том, что эту функцию стоит сделать inline, и совершенно не факт, что он это сделает.


Цитата(Riply @  23.7.2008,  17:23 Найти цитируемый пост)
(первый в три раза медленнее второго, но второй как-то ненадежно выглядит )

Каким профайлером производились замеры ?
--------------------
We have no begining, we have no end. We are infinite.
PM MAIL   Вверх
Riply
Дата 23.7.2008, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: нет
Всего: 32



Цитата(Torsten @  23.7.2008,  23:01 Найти цитируемый пост)
Хотя бы вот такой код, уже приведет к неправельным действиям :


Не поняла, почему и что имеется ввиду под nLength+1 ? Может аLength+1 ?
Это не страшно: изменим имя параметра.  smile 
Меня больше волновало _Us_SetLength(pUnicodeString, pUnicodeString->Length + 1),
но вроде все нормально. 



Цитата(Torsten @  23.7.2008,  23:01 Найти цитируемый пост)
Каким профайлером производились замеры ?


Да простым QueryPerformanceCounter - ом

PM MAIL   Вверх
Torsten
Дата 23.7.2008, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 174
Регистрация: 10.6.2008
Где: Pskov

Репутация: нет
Всего: 7



Цитата(Riply @  23.7.2008,  23:17 Найти цитируемый пост)
Да простым QueryPerformanceCounter - ом

Лучше профайлером, тогда более менее точно станет понятно, на что именно больше всего тратится ресурсов.


Цитата(Riply @  23.7.2008,  23:17 Найти цитируемый пост)
Не поняла, почему и что имеется ввиду под nLength+1 ? Может аLength+1 ?Это не страшно: изменим имя параметра.   Меня больше волновало _Us_SetLength(pUnicodeString, pUnicodeString->Length + 1),но вроде все нормально. 

Ну, тогда продолжайте использовать. Мое дело предупредить ^_^
--------------------
We have no begining, we have no end. We are infinite.
PM MAIL   Вверх
Alexeis
Дата 23.7.2008, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 4
Всего: 459



Цитата(Riply @  23.7.2008,  22:17 Найти цитируемый пост)
Не поняла, почему и что имеется ввиду под nLength+1 ? Может аLength+1 ?
Это не страшно: изменим имя параметра. 

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


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
bilbobagginz
Дата 24.7.2008, 01:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Naughtius Maximus
****


Профиль
Группа: Экс. модератор
Сообщений: 8813
Регистрация: 2.3.2004
Где: Israel

Репутация: нет
Всего: 317



Цитата(Riply @  23.7.2008,  17:23 Найти цитируемый пост)
Какой из этих двух вариантов (если конечно они не содержат ошибок) предпочтительней для использования ?
(первый в три раза медленнее второго, но второй как-то ненадежно выглядит smile)

с т.з. скорости ?
думаю тот, который побыстрей.
если критерий проверки - скорость.
как тут ранее написали, читабельность чуток понижается, 
следовательно такой кусок стоит объяснить.
но в принципе он ничего сложного не делает, поэтому такой кусок объяснять - время убивать зря.
Цитата(Riply @  23.7.2008,  17:23 Найти цитируемый пост)

Например, в нем используется выражение " ((_pus)->Length = _cbLen) * 0 "
Всегда ли его левый сомножитель будет "вычисляться" или, при некоторых условиях, может игнорироваться ?

множиться будет всегда, но можно сделать и быстрее, если не умножать, а делать побитовый & с нулём.
поэтому,  при условии, что длИны - представляются целыми типами,  мой вариант таков:
Код

#define _Us_SetLength(_pus, _cbLen) (((_pus)->MaximumLength >= (_cbLen)) ? \
                                     (((_pus)->Length = (_cbLen)) & 0) : \
                                     STATUS_NAME_TOO_LONG)

_cbLen тут стоит запихать в скобочки, как сказал тов. Alexeis, но не обязательно.
В данном конкретном случае это не страшно: 
  • сравнение вычисляется слева-направо
  • сравнение имеет более низкий приоритет, чем сложение.
т.е. в предложенном случае, ваше оригинальное макро:
Код

_Us_SetLength(_pus,_cbLen+1)

поведёт себя "хорошо", т.е х>y+z будет всегда идентично x>(y+z). 
НО, т.к. иногда действия с операндами, которые запихивают в макро дают нежелаемые результаты,  не засовывать "операнды" макро в скобочки - плохой вкус.



--------------------
Я ещё не демон. Я только учусь.
PM WWW   Вверх
Lazin
Дата 24.7.2008, 08:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



не стоит использовать define, нервные клетки не восстанавливаются...
Обычная функция делающая то-же самое будет не медленнее.
Компилятор в состоянии разобраться, в каком контексте вызывается функция, если она вызывается один раз, то встраивание ничего не даст кроме увеличения объема кода.
Если функция вызывается в цикле, то даст, и скорее всего она будет встроена. Так зачем брать на себя работу компилятора?
PM MAIL Skype GTalk   Вверх
DRUID3
Дата 24.7.2008, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 463
Регистрация: 20.6.2005
Где: Kyyiv

Репутация: нет
Всего: 9



Цитата(Lazin @  24.7.2008,  07:34 Найти цитируемый пост)
Обычная функция делающая то-же самое будет не медленнее.

Это как???  smile "На глазок"?

Цитата(Lazin @  24.7.2008,  07:34 Найти цитируемый пост)
Компилятор в состоянии разобраться, в каком контексте вызывается функция, если она вызывается один раз, то встраивание ничего не даст кроме увеличения объема кода.
Если функция вызывается в цикле, то даст, и скорее всего она будет встроена. Так зачем брать на себя работу компилятора? 

 Нет, он не всегда, причем далеко не всегда в состоянии разобраться...


--------------------
Every time if you use Linux, you are joined to the communism...
практика - критерий истины ... отделенной от нас пропастью субъективного восприятия...
PM MAIL WWW Skype   Вверх
Lazin
Дата 24.7.2008, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(DRUID3 @  24.7.2008,  09:22 Найти цитируемый пост)
Это как???  smile "На глазок"?

нет smile 

Цитата(DRUID3 @  24.7.2008,  09:22 Найти цитируемый пост)
Нет, он не всегда, причем далеко не всегда в состоянии разобраться... 

с тем примером в 2 строчки он пожалуй сможет разобраться.
вообще чем меньше функция, тем больше шансов что она будет заинлайнена, если функция большая и выполняется долго, то стоимость ее вызова, по сравнению с выполнением самой функциии незначительна и встраивать смысла нет...
Но все эти аспекты анализировать самостоятельно - занятие неблагодарное, так что лучше доверить это компилятору.
Плюс функции в том, что в одном случае она будет встроена, в другом нет. Если она вызывается из 100 разных мест, то реально встраивать нужно в одном - двух, там где она часто вызывается и стоимость вызова большая. В остальных случаях проще вызвать... Ну а макрос на 100% разменяет объем на скорость, при этом разницы в скорости не будет, так как там где нужно функция будет то-же встроена...
PM MAIL Skype GTalk   Вверх
Alexeis
Дата 24.7.2008, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 4
Всего: 459



Вот выдержка из справки по билдеру
Цитата

The compiler cannot inline a function if: 


  • The function or its caller is compiled with /Ob0 (the default option for debug builds). 
  • The function and the caller use different types of exception handling (C++ exception handling in one, structured exception handling in the other). 
  • The function has a variable argument list.
  • The function uses inline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
  • The function is recursive and not accompanied by #pragma inline_recursion(on). With the pragma, recursive functions are inlined to a default depth of 16 calls. To reduce the inlining depth, use inline_depth pragma.
  • The function is virtual and is called virtually. Direct calls to virtual functions can be inlined.
  • The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
  • The function is also marked with the naked __declspec modifier.




Ни каких ограничений на то что функция не может возвращать значения или создавать локальные переменные. Это могут быть только ограничения отдельно взятого хилого компилятора.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
xvr
Дата 24.7.2008, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(Riply @ 23.7.2008,  17:23)
Здравствуйте !
Допустим, у нас есть такая функция, которую мы собираемся вызывать 
так много раз, что и не сосчитаешь smile
Код

__inline NTSTATUS Us_SetLength(const PUNICODE_STRING pUs, const ULONG aLength)
{
  if (pUs->MaximumLength >= aLength)
   {
     pUs->Length = aLength;
     return STATUS_SUCCESS;
   };
  return STATUS_NAME_TOO_LONG;
};

Пробуем написать ее аналог, используя "дефайны"
Код

#define _Us_SetLength(_pus, _cbLen) ((_pus)->MaximumLength >= _cbLen) ?    \
((_pus)->Length = _cbLen) * 0 : STATUS_NAME_TOO_LONG


Какой из этих двух вариантов (если конечно они не содержат ошибок) предпочтительней для использования ?

Первый
Цитата

(первый в три раза медленнее второго, но второй как-то ненадежно выглядит smile)
Нормальный компилятор должен сделать не медленнее
Цитата

Например, в нем используется выражение " ((_pus)->Length = _cbLen) * 0 "
Всегда ли его левый сомножитель будет "вычисляться" или, при некоторых условиях, может игнорироваться ?
Рекомендую заменить это 'выражение' на (((_pus)->Length = (_cbLen)) , 0) Хотя нормальный компилятор сделает практически тоже самое

Проверил - сделал вызовы обоих версих функции, скормил все это Intel компилятору (на Linux) - код АБСОЛЮТНО одинаковый! (см атач)

Кроме того, у define'а есть еще один ОГРОМНЫЙ подводный камень:
Код

// Somewhere in .h was defined:
__inline NTSTATUS Us_SetLength(const PUNICODE_STRING pUs, const ULONG aLength)
{...}

// Somewhere in .cpp is -
int Us_SetLength(MyStruct* pUs, int mylen)
{...}
Это нормально откомпилится и будет работать (С++ допускает функции с одинаковыми именами но разными параметрами). Если бы у вас был #define вместо первой функции - вы получили бы маловразумительные сообщения о массе ошибок на месте определения второй функции.


Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  tst.zip 1,35 Kb
PM MAIL   Вверх
DRUID3
  Дата 24.7.2008, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 463
Регистрация: 20.6.2005
Где: Kyyiv

Репутация: нет
Всего: 9



Цитата(Lazin @  24.7.2008,  08:36 Найти цитируемый пост)
нет

а как?
Цитата(Lazin @  24.7.2008,  08:36 Найти цитируемый пост)
с тем примером в 2 строчки он пожалуй сможет разобраться.
вообще чем меньше функция, тем больше шансов что она будет заинлайнена, если функция большая и выполняется долго, то стоимость ее вызова, по сравнению с выполнением самой функциии незначительна и встраивать смысла нет...
Но все эти аспекты анализировать самостоятельно - занятие неблагодарное, так что лучше доверить это компилятору.
Плюс функции в том, что в одном случае она будет встроена, в другом нет. Если она вызывается из 100 разных мест, то реально встраивать нужно в одном - двух, там где она часто вызывается и стоимость вызова большая. В остальных случаях проще вызвать... Ну а макрос на 100% разменяет объем на скорость, при этом разницы в скорости не будет, так как там где нужно функция будет то-же встроена... 

да, вобщем-то верно. За тем исключением, что "вобщем-то". Иногда нужно четко что-то встроить. И очень не хочется "балансировать" на грани встроенного в компилятор автомата, который решает - встраивать или нет. 

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

Я же свои злоключения высказал, они могут пригодиЦЦо и другим идущим по этому пути.  smile 

Вообще было бы очень клево, если бы кто-то не поленился, посидел с дизассемблером и несколькими компиляторами и накатал статейку "о том, как не надо применять inline"  smile 


--------------------
Every time if you use Linux, you are joined to the communism...
практика - критерий истины ... отделенной от нас пропастью субъективного восприятия...
PM MAIL WWW Skype   Вверх
Любитель
Дата 24.7.2008, 15:18 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: нет
Всего: 92



Цитата(DRUID3 @  23.7.2008,  18:05 Найти цитируемый пост)
Ага... Причем, реально inline должен работать только с указателями на внешние объекты не имя собственных переменных и ничего не возвращая. Кто не совсем понимает почему пусть вспомнит какие функции компилятор делает inline по возможности без нашей просьбы. 

Цитата(DRUID3 @  23.7.2008,  19:03 Найти цитируемый пост)
void... а фнкцией она само собой быть не может. Это же подстановка. Вот как только появляется хоть один атрибут функции это уже не inline

ЭТо кто вам такую ерунду сказал?1 smile 

Цитата(DRUID3 @  23.7.2008,  21:34 Найти цитируемый пост)
Я рассказал когда inline будет 100% inline во всех компиляторах. Некоторые случаи возможны и в более сложных ситуациях. 

Ничего подобного. 100% на всех компиляторах - инлайна никогда не будет. Есть всякие форсирующие директивы, есть ключевое слово inline - хинт компилеру, есть оптимизатор.

Цитата(DRUID3 @  23.7.2008,  21:34 Найти цитируемый пост)
Но, например, вообще нереализуем рекурсивный inline вызов.

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


--------------------
PM MAIL ICQ Skype   Вверх
Lazin
Дата 24.7.2008, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(DRUID3 @  24.7.2008,  11:39 Найти цитируемый пост)
Врать не буду с борландом йа не работаю и не намереваюсь. Очень возможно, что он, например, преобразует внутри себя локальные переменные в глобалные и работает с их адресами и т.д...

а стек для чего?

Цитата(DRUID3 @  24.7.2008,  11:39 Найти цитируемый пост)
Вообще было бы очень клево, если бы кто-то не поленился, посидел с дизассемблером и несколькими компиляторами и накатал статейку "о том, как не надо применять inline"

вот xvr написал исчерпывающий пост, что еще нужно?
сидеть с дизассемблером не нужно, достаточно в release версии программы поставить брэйкпоинт в место вызова функции, например в цикле и когда он сработает клацнуть Show Disassembly, бегая отладчиком по рилиз версии, очень хорошо видно что и когда оптимизатор встраивает даже без дизассемблера, так как отладчик в заинлайненые функции не заходит. 
PM MAIL Skype GTalk   Вверх
varnie
Дата 24.7.2008, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 27.9.2007

Репутация: нет
Всего: 0



Effective C++, Глава 1:
Правило 1:
Цитата

предпочитайте const и inline использованию #define

PM MAIL   Вверх
DRUID3
Дата 24.7.2008, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 463
Регистрация: 20.6.2005
Где: Kyyiv

Репутация: нет
Всего: 9



Цитата(Любитель @  24.7.2008,  14:18 Найти цитируемый пост)
ЭТо кто вам такую ерунду сказал?

Суровая правда жизни smile ...
Цитата(Любитель @  24.7.2008,  14:18 Найти цитируемый пост)
Ничего подобного. Простые рекурсии (читай - рекурсии, которые были не в тему) - любой хороший комплер в состоянии развернуть. 

А это тут то причем???  smile вон, смотрите, даже борланд по определению не сделает inline рекурсивную функцию. Отекда у нас уже пошла речь о разложении простой рекурсии?
Цитата(Lazin @  24.7.2008,  14:30 Найти цитируемый пост)
а стек для чего?

А подстановкой мы что экономим!!!??? smile 
Цитата(varnie @  24.7.2008,  14:46 Найти цитируемый пост)
предпочитайте const и inline использованию #define

угу... А еще надо хорошо учиться и слушать папу и маму... smile 


--------------------
Every time if you use Linux, you are joined to the communism...
практика - критерий истины ... отделенной от нас пропастью субъективного восприятия...
PM MAIL WWW Skype   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0747 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.