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

Поиск:

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


Опытный
**


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

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



Здравствуйте !
Допустим, у нас есть такая функция, которую мы собираемся вызывать 
так много раз, что и не сосчитаешь 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 "
Всегда ли его левый сомножитель будет "вычисляться" или, при некоторых условиях, может игнорироваться ?
PM MAIL   Вверх
Alexeis
Дата 23.7.2008, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


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

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



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

  Мож под дебагом игнорируется директива __inline. 
  __inline однозначно предпочтительнее, так как там идет проверка типов на этапе компиляции и проч. Нужно попробовать дизассемблировать релизовый экзешник и сравнить код. Я думаю разницы не будет.


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

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

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


Опытный
**


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

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



Цитата(Alexeis @  23.7.2008,  17:31 Найти цитируемый пост)
Мож под дебагом игнорируется директива __inline. 
  __inline однозначно предпочтительнее, так как там идет проверка типов на этапе компиляции и проч. Нужно попробовать дизассемблировать релизовый экзешник и сравнить код. Я думаю разницы не будет. 


Попробовала запустить не из под среды.
Результат тот же: соотношение один к трем.
Сейчас попробую посмотреть в CPU-шке, правда я там себя не очень уверенно чувствую smile

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


found myself
****


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

Репутация: 2
Всего: 121



Выложи два варианта в виде exe в релиз сборке. Посмотрим на оптимизацию. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Partizan
Дата 23.7.2008, 17:58 (ссылка) |    (голосов:5) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 67



ммм...насколько я знаю компилятор оставляет за собой право не инлайнить функцию по своему усмотрению даже тогда когда явно указан модификатор __inline...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Riply
Дата 23.7.2008, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(W4FhLF @  23.7.2008,  17:49 Найти цитируемый пост)
Выложи два варианта в виде exe в релиз сборке. Посмотрим на оптимизацию.


Сейчас, только переброшу это безобразие в пустой проект.
Да, на всякий случай: я под Builder`ом. Все равно выкладывать ?

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


found myself
****


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

Репутация: 2
Всего: 121



Цитата(Riply @  23.7.2008,  17:59 Найти цитируемый пост)
Да, на всякий случай: я под Builder`ом. Все равно выкладывать ?


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

Но, Partizan, скорее всего прав. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Riply
Дата 23.7.2008, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(W4FhLF @  23.7.2008,  18:01 Найти цитируемый пост)
Ну создай какой-нибудь тестовый проект


Хорошо, только мне надо чуть времени.

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


Опытный
**


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

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



Цитата(Partizan @  23.7.2008,  16:58 Найти цитируемый пост)
ммм...насколько я знаю компилятор оставляет за собой право не инлайнить функцию по своему усмотрению даже тогда когда явно указан модификатор __inline... 

Ага... Причем, реально inline должен работать только с указателями на внешние объекты не имя собственных переменных и ничего не возвращая. Кто не совсем понимает почему пусть вспомнит какие функции компилятор делает inline по возможности без нашей просьбы. 

Цитата(Alexeis @  23.7.2008,  16:31 Найти цитируемый пост)

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

очень похоже, на недавний спор "что лучше указатель или ссылка". То, что написали в учебнике для создания первичных представлений - одно. То что следует применять в отдельном случае на практике - другое. define - 100% разменяет объем на скорость. Директива inline, да еще не к месту примененная так и останется директивой.


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


Опытный
**


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

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



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


"ничего не возвращая" в смысле не может быть и функцией в том числе ?

P.S.
 Прикрепила файл.

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  Inline_Test.rar 185,10 Kb
PM MAIL   Вверх
DRUID3
Дата 23.7.2008, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Riply @  23.7.2008,  17:56 Найти цитируемый пост)
"ничего не возвращая" в смысле не может быть и функцией в том числе ?

void... а фнкцией она само собой быть не может. Это же подстановка. Вот как только появляется хоть один атрибут функции это уже не inline... 


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


Опытный
**


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

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



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


"Нда... Сказали мы с Петром Иванычем" (с) smile

Либо у меня еще и в Delphi пробелы с образованием, либо C++ это совсем не Delphi  smile

Добавлено через 5 минут и 9 секунд
P.S.
 А как насчет произведения, о котором я спрашивала в топике ?
 Всегда ли будет вычисляться левая часть ?
PM MAIL   Вверх
mes
Дата 23.7.2008, 20:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

Репутация: 79
Всего: 250



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

насколько я понял вопрос такой: всегда ли будет происходить присваивание?  Да


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


т.е функция  inline int max(int a, int b) { return (a>b)?  a: b; } не будет инлайниться? не согласен 



Это сообщение отредактировал(а) mes - 23.7.2008, 20:49


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


Амеба
Group Icon


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

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



Цитата(mes @  23.7.2008,  19:48 Найти цитируемый пост)
т.е функция  inline int max(int a, int b) { return (a>b)?  a: b; } не будет инлайниться? не согласен 

  Мне тоже кажеться что должно работать. Возможно такое ограничение есть у одного из компиляторов. Насколько я помню есть ограничение на число машинных команд.


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

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

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


Опытный
**


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

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



Цитата(Riply @  23.7.2008,  18:16 Найти цитируемый пост)
Либо у меня еще и в Delphi пробелы с образованием, либо C++ это совсем не Delphi 

Я не знаю Delphi, и не знаю что Вам на это сказать. Я имел ввиду, что нужно применить процедуры - ничего не возвращающие функции 
void fn_foo();
Цитата(Riply @  23.7.2008,  18:16 Найти цитируемый пост)
 А как насчет произведения, о котором я спрашивала в топике ?
 Всегда ли будет вычисляться левая часть ? 

Крайний левый операнд в тринарном выражении будет вычисляться всегда - он проверяется на "0". Если он ">0" то второй оператор, а иначе - третий. Если же Вы хотите узнать будет ли повторяться бессмысленное умножение на "0" то да, будет.

Цитата(mes @  23.7.2008,  19:48 Найти цитируемый пост)
т.е функция  inline int max(int a, int b) { return (a>b)?  a: b; } не будет инлайниться? не согласен 

А баба яга - протиФФ. smile  Я рассказал когда inline будет 100% inline во всех компиляторах. Некоторые случаи возможны и в более сложных ситуациях. Зависит от "ума" компилятора, и того к чему он преобразует внутри "себя любимого". Но, например, вообще нереализуем рекурсивный inline вызов. Столкнулся пару месяцев назад - чужой проект был "глубоко оптимизирован" - перед каждой функцией стояло inline. Я с ним долбался долго, а потом дай-ка думаю посношу это... и... и нифига не изменилось, блин! Поспрашивал на electronix? там сказали почитай Саттера. Почитал - полный бред ниочем, мол может оптимизировать? а может и не оптимизировать, смотря от урожая травы в Африке smile . И я блин вспомнил, читал де, что собственные закрытые функции класса компилер сам делает inline если они работают только с полями класса. Блин... Пришлось немного пошаманить, зато inline стали настоящими подстановками.

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

Добавлено @ 21:38
Цитата(Alexeis @  23.7.2008,  20:07 Найти цитируемый пост)
Мне тоже кажеться что должно работать. Возможно такое ограничение есть у одного из компиляторов. Насколько я помню есть ограничение на число машинных команд. 

Нет, реально ограничение на целесообразность подстановки. И ее "пик" это отсутствие собственных переменных и возврата. Хоть в C а хоть в C++. Работайте с полями глобальной структуры или делайте закрытые методы обращающиеся по указателю к полям объекта - будет вам счастье. А иначе мрак хаоса описанный в книжонке Саттера...

Это сообщение отредактировал(а) DRUID3 - 23.7.2008, 21:45


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


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


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

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



Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
Суровая правда жизни

Пруфлинк?

Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
даже борланд 

 smile

Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
А это тут то причем???  

При том, что развернув рекурсию в цикл, полученное можно заинлайнить.


--------------------
PM MAIL ICQ Skype   Вверх
Любитель
Дата 24.7.2008, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Насчёт рекурсии - проверено на VC++ 2005, на VC++ 2008 тоже, думаю, сработает.

Исходный код:
Код

#include <stdio.h>

#pragma inline_recursion(on)

int __forceinline add(int a, int b)
{
    if (b == 0)
        return a;
    else
        return add(1 + a, b - 1);
}

int main()
{
    printf("%i", add(5, 7));
}


Получаем:
Код

push        0Ch     ; типа фтопку нашу функцию :)
push        offset string "%i"
call           dword ptr [__imp__printf ] 
add          esp,8 
xor           eax,eax 
ret     


Это сообщение отредактировал(а) Любитель - 24.7.2008, 17:44


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


Новичок



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

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



Цитата(varnie)

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

Цитата(DRUID3 @  24.7.2008,  19:40 Найти цитируемый пост)

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

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


Это сообщение отредактировал(а) varnie - 24.7.2008, 18:21
PM MAIL   Вверх
Lazin
Дата 24.7.2008, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(DRUID3 @ 24.7.2008,  16:40)
Цитата(Lazin @  24.7.2008,  14:30 Найти цитируемый пост)
а стек для чего?

А подстановкой мы что экономим!!!??? smile 

какой подстановкой? ты о чем?
локальные переменные размещаются в стеке, всегда... встроена функция, или нет, это не важно
PM MAIL Skype GTalk   Вверх
phprus
Дата 24.7.2008, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
вон, смотрите, даже борланд по определению не сделает inline рекурсивную функцию.

C++ компилятор от борланда на столько крив и глючен, что не достоен называться компилятором.Он отстал от жизни лет на 20.
Возьмите как образец G++, компилятор от Intel или M$ VS.


Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
Отекда у нас уже пошла речь о разложении простой рекурсии?

Хвостовая рекурсия раскладывается в цикл элементарно. Такие оптимизации уже давно не редкость.

Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
Суровая правда жизни smile ...

Это именно что ерунда. Сколько пользовался !нормальными! компиляторами никогда такого не замечал в релиз-сборках проектов.

Цитата(DRUID3 @  24.7.2008,  16:40 Найти цитируемый пост)
А подстановкой мы что экономим!!!??? smile 

Как я понимаю имеется ввиду inline-подстановка тела функции?
Если я прав, то в сад. Подстановкой мы экономим вызов функции, те переход на удаленный участок кода, которого скорее всего нет в кеше процессора и тд... А память в стеке выделяется мгновенно, ибо это всего-лишь изменение значения указателя на вершину стека и ВСЕ. Кроме того стек почти гарантированно лежит в кэше процессора, а это еще ускорит работу с используемой частью стека.
PM MAIL WWW ICQ   Вверх
Riply
Дата 25.7.2008, 07:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



"Ох, не легкая это работа - из болота тащить бегемота" (с) 
Спасибо всем тащившим  smile

P.S.
 Я много вынесла из этой ветки. 

PM MAIL   Вверх
W4FhLF
Дата 26.7.2008, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

Репутация: 2
Всего: 121



Хоть уже и не актуально, но раз уж обещал дизассемблировать примеры, то в выложенном на первой странице exe компилятор действительно проигнорировал inline, на уровне маш. кода осуществялется вызов отдельной процедуры. 

Извиняюсь за задержку, запамятовал smile 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
Riply
Дата 26.7.2008, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(W4FhLF @  26.7.2008,  14:34 Найти цитируемый пост)
Хоть уже и не актуально


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

Цитата(W4FhLF @  26.7.2008,  14:34 Найти цитируемый пост)
но раз уж обещал дизассемблировать примеры, то в выложенном на первой странице exe компилятор действительно проигнорировал inline, на уровне маш. кода осуществялется вызов отдельной процедуры


Спасибо большое. Теперь предположения, превратились в уверенность smile



Это сообщение отредактировал(а) Riply - 26.7.2008, 22:39
PM MAIL   Вверх
Supersedes
Дата 29.7.2008, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Riply, а с каким компилятором ты вообще работаешь?

Это сообщение отредактировал(а) Supersedes - 29.7.2008, 12:36
PM MAIL ICQ   Вверх
Riply
Дата 29.7.2008, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Supersedes @  29.7.2008,  12:26 Найти цитируемый пост)
Riply, а с каким компилятором ты вообще работаешь?


В данном случае, все происходило под Builder`ом.
PM MAIL   Вверх
xvr
Дата 29.7.2008, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Riply @ 29.7.2008,  19:43)
Цитата(Supersedes @  29.7.2008,  12:26 Найти цитируемый пост)
Riply, а с каким компилятором ты вообще работаешь?


В данном случае, все происходило под Builder`ом.

Кстати, о птичках - откомпилировал тест под Билдером (6.0)
Код

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>

struct UNICODE_STRING {
 ULONG MaximumLength;
 ULONG Length;
};

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
private:    // User declarations
 int v;
 UNICODE_STRING us;
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


Код

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

__inline int Us_SetLength(UNICODE_STRING* pUs, const ULONG aLength)
{
  if (pUs->MaximumLength >= aLength)
   {
     pUs->Length = aLength;
     return 0;
   };
  return 1;
};

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 v=Us_SetLength(&us,10);
}
//---------------------------------------------------------------------------
Поставил режим 'Release', все заинлайнилось:

Код

 ;    
 ;    {
 ;     v=Us_SetLength(&us,10);
 ;    
?live16385@32: ; EBX = $delflag
    mov eax,dword ptr [ebp-4]
    add eax,756
    cmp dword ptr [eax],10
    jb        short @3
    mov dword ptr [eax+4],10
    xor edx,edx
    jmp short @4
@3:
    mov edx,1
@4:
    mov eax,dword ptr [ebp-4]
    mov dword ptr [eax+752],edx
 ;    
 ;    }
Вывод - хотите производительности, включайте оптимизации и будет вам счастье  smile 
PM MAIL   Вверх
Riply
Дата 30.7.2008, 02:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(xvr @  29.7.2008,  22:41 Найти цитируемый пост)
Поставил режим 'Release', все заинлайнилось


Можете себе представить какое мнение у меня сложилось о способностях Builder`а,
после того как он отказался инлайнить такую простую функцию.
Вам удалось чуть-чуть его (это мнение) поднять . Builder должен быть Вам благодарен smile
P.S.
 И я тоже благодарна smile

PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

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

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

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

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


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

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


 




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


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

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