massive inline
От: Аноним  
Дата: 30.09.09 17:59
Оценка:
Доброго времени суток!

Недавно столкнулся с кодом, в ряде мест которого очень интенсивно используется inline. Код критичен к скорости.
Очень широко используются такие конструкции:

class Foo
{
public:
  inline Foo() { ... }
  inline int getSomething() const { ... }
  inline void setSomething(...) { ... }
};


практически все функции рассматриваемого кода небольшого размера и описаны непосредственно по месту объявления, т.е. в теле описания класса.

Код рассчитан на Desktop-приложения (Mac, Linux, Windows) и приложения для встраиваемых устройств уровня современных КПК. Компиляторы — MSVC v. >= 6.0 и g++ v. >= 3.4.5

На мой взгляд широкое использование inline загрязняет код и не приводит к существенному изменению качества сгенерированного кода.

Так же я часто встречал в литературе (например у Саттера) рекомендации не использовать inline (со ссылками на то, что компилятор и так достаточно умен, чтобы соптимизировать такой код, а так же, что любая функция объявленная в теле класса считается встроенной безотносительно наличия квалификатора inline).

Однако люди писавшие этот код — очень хорошие профессионалы.
В связи с чем вопрос — есть ли достоверные сведения о том, что от квалификатора inline можно безболезненно отказаться в случае использования вышеупомянутых компиляторов (интересует информация хотя бы по g++ версии 4 и выше).
Re: massive inline
От: denisko http://sdeniskos.blogspot.com/
Дата: 30.09.09 18:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Однако люди писавшие этот код — очень хорошие профессионалы.

А>В связи с чем вопрос — есть ли достоверные сведения о том, что от квалификатора inline можно безболезненно отказаться в случае использования вышеупомянутых компиляторов (интересует информация хотя бы по g++ версии 4 и выше).
Нет, представление компилятора об уме может разниться с твоим, в MSVC 7.0 да и вроде 2008-2010 студиях оставлена директива __forceinline. И она таки работает.
<Подпись удалена модератором>
Re: massive inline
От: Анатолий Широков СССР  
Дата: 30.09.09 18:49
Оценка: 1 (1)
Если тело функции-члена находится в теле класса, то inline излишен, поскольку такие функции и так трактуются как inline:

9.3 Member functions
...
2 A member function may be defined (8.4) in its class definition, in which case it is an inline member function
(7.1.2),...


Поэтому код
class Foo
{
public:
  Foo() { ... }
  int getSomething() const { ... }
  void setSomething(...) { ... }
};

будет эквивалентен ранее приведенному вами.

Другой вопрос — встроит или нет такие функции компилятор? Здесь гарантий никаких нет. Но и бить тревогу раньше времени тоже не стоит. Если профилировщик укажет, что узким местом системы является одна из этих функции, тогда и стоит что-либо предпринимать.
Re[2]: massive inline
От: StevenIvanov США  
Дата: 30.09.09 19:28
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Если тело функции-члена находится в теле класса, то inline излишен, поскольку такие функции и так трактуются как inline:

...
АШ>Другой вопрос — встроит или нет такие функции компилятор? Здесь гарантий никаких нет. Но и бить тревогу раньше времени тоже не стоит. Если профилировщик укажет, что узким местом системы является одна из этих функции, тогда и стоит что-либо предпринимать.

я, в общем-то, так и думал. Спасибо за ссылку из стандарта.

В общем меня интересовало — имеет ли какой-то вес для компилятора добавочное объевление inline для методов реализованных по месту объявления. Видимо стоит задать такой вопрос разработчикам компилятора...
Re[3]: massive inline
От: StevenIvanov США  
Дата: 01.10.09 08:17
Оценка:
Здравствуйте, StevenIvanov, Вы писали:

SI>Здравствуйте, Анатолий Широков, Вы писали:

...
SI>В общем меня интересовало — имеет ли какой-то вес для компилятора добавочное объевление inline для методов реализованных по месту объявления. Видимо стоит задать такой вопрос разработчикам компилятора...

разработчики GCC ответили то же самое...

> I mean whether the code
>
> class A
> {
> inline void foo() { ... }
> };
>
> is absolutely equal to
>
> class A
> {
> void foo() { ... }
> };
>
> in *any* circumstances or not?

They are the same unless you do -fno-default-inline and then the
second version is not marked as inline.

Re: massive inline
От: Тролль-323  
Дата: 01.10.09 08:29
Оценка:
Может, они делают так: объявляют платформенно-зависимый

#define inline

чтобы сделать inline, который по-настоящему работает, а не просто дает «совет» компилятору.

Для MSVC это будет

#define inline        __forceinline

а для GCC

#define inline        __attribute__((always_inline))
Re[2]: massive inline
От: StevenIvanov США  
Дата: 01.10.09 09:21
Оценка:
Здравствуйте, Тролль-323, Вы писали:

Т3>Может, они делают так: объявляют платформенно-зависимый


Т3>
#define inline

Т3>чтобы сделать inline, который по-настоящему работает, а не просто дает «совет» компилятору.

Т3>Для MSVC это будет


Т3>
#define inline        __forceinline

Т3>а для GCC

Т3>
#define inline        __attribute__((always_inline))


нет, этого не делается. Плюс к тому для GCC все-таки следует использовать конструкцию вида

inline {function-definition}  __attribute__((always_inline))


к тому же последняя конструкция не всегда хорошо работает на gcc 3.4.x (иногда могут возникать ошибки компиляции — "sorry — inlining failed")
Re[2]: massive inline
От: Кодт Россия  
Дата: 01.10.09 09:49
Оценка:
Здравствуйте, Тролль-323, Вы писали:

Т3>Может, они делают так: объявляют платформенно-зависимый

Т3>
#define inline

Т3>чтобы сделать inline, который по-настоящему работает, а не просто дает «совет» компилятору.

inline (явный или неявный, как в случае классов и шаблонов) — это не только совет, но и указание компилятору относительно линковки. В VC ему соответствует __declspec(selectany).

Настоящие профессионалы, вместо хака с переопределением ключевого слова, лучше бы ввели своё #define FORCEINLINE
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: massive inline
От: Кодт Россия  
Дата: 01.10.09 09:54
Оценка:
Здравствуйте, StevenIvanov, Вы писали:

SI>к тому же последняя конструкция не всегда хорошо работает на gcc 3.4.x (иногда могут возникать ошибки компиляции — "sorry — inlining failed")


Никакое указание относительно встраивания не может всегда хорошо работать. Есть вещи, которые в принципе не получится встроить — например, рекурсию или косвенный вызов.
Другое дело, что VC к этому относится снисходительно — не встроил, ну и ладно. А gcc ругается.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[3]: massive inline
От: Erop Россия  
Дата: 01.10.09 10:10
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Настоящие профессионалы, вместо хака с переопределением ключевого слова, лучше бы ввели своё #define FORCEINLINE


Дык эти вроде хаком и не пользовались...

А код насколько старый? Или кросс-платформенный?
Может это борьба с глюками какого-то редкого/старого транслятора?

А ещё такое использование слова inline может быть полезно, чтобы искать подставляемые функции грепом...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: massive inline
От: Кодт Россия  
Дата: 01.10.09 13:10
Оценка:
Здравствуйте, Erop, Вы писали:

К>>Настоящие профессионалы, вместо хака с переопределением ключевого слова, лучше бы ввели своё #define FORCEINLINE

E>Дык эти вроде хаком и не пользовались...

Переопределять ключевые слова — не хак?

E>А код насколько старый? Или кросс-платформенный?

E>Может это борьба с глюками какого-то редкого/старого транслятора?

Вот это больше похоже на правду.

E>А ещё такое использование слова inline может быть полезно, чтобы искать подставляемые функции грепом...


Э? Почему inline foo() лучше для грепа, чем FORCEINLINE foo() ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[4]: massive inline
От: COFF  
Дата: 01.10.09 13:56
Оценка:
Здравствуйте, Erop, Вы писали:


E>А код насколько старый? Или кросс-платформенный?

E>Может это борьба с глюками какого-то редкого/старого транслятора?

Может быть, кстати, просто эстетической причудой конкретного разработчика. В конце-концов, необязательно не значит нежелательно или нельзя :)
Re: massive inline
От: Sergey Chadov Россия  
Дата: 01.10.09 13:57
Оценка: 5 (2) +1
А>Так же я часто встречал в литературе (например у Саттера) рекомендации не использовать inline (со ссылками на то, что компилятор и так достаточно умен, чтобы соптимизировать такой код, а так же, что любая функция объявленная в теле класса считается встроенной безотносительно наличия квалификатора inline).

А>Однако люди писавшие этот код — очень хорошие профессионалы.

А>В связи с чем вопрос — есть ли достоверные сведения о том, что от квалификатора inline можно безболезненно отказаться в случае использования вышеупомянутых компиляторов (интересует информация хотя бы по g++ версии 4 и выше).

1. В общем случае, компилятор недостаточно умен. По крайней мере вдумчивое расставление __forceinlinе для MSVC не раз приводило к заметному приросту производительности на критических участках.
2. модификатор inline в С++ имеет и другие эффекты кроме встраивания функций
3. Возможно, модификатор inline в коде написан с целью документирования того какие функции по мнению авторов должны быть заинлайнены, чтобы к примеру упростить портирование.
4. Ну и вполне возможно что авторы просто привыкли писать не то что "можно", а то, что они имели ввиду
--
Sergey Chadov

... << RSDN@Home 1.2.0 alpha rev. 685>>
Re[5]: massive inline
От: Erop Россия  
Дата: 01.10.09 17:01
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Переопределять ключевые слова — не хак?

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

E>>Может это борьба с глюками какого-то редкого/старого транслятора?

К>Вот это больше похоже на правду.
Мне эта версия, пока что, представляется самой правдаподобной...

E>>А ещё такое использование слова inline может быть полезно, чтобы искать подставляемые функции грепом...

К>Э? Почему inline foo() лучше для грепа, чем FORCEINLINE foo() ?

Какой такой FORCEINLINE?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: massive inline
От: Тролль-323  
Дата: 01.10.09 18:57
Оценка:
SI>нет, этого не делается. Плюс к тому для GCC все-таки следует использовать конструкцию вида

SI>
SI>inline {function-definition}  __attribute__((always_inline))
SI>


Так, как я написал, тоже можно (в документации GCC написано).

SI>к тому же последняя конструкция не всегда хорошо работает на gcc 3.4.x (иногда могут возникать ошибки компиляции — "sorry — inlining failed")


Да, есть такое дело.

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

Кстати, тов. Саттер врет, что компилятор сам знает, когда инлайнить функции. Как показывает практика, ничего он не знает, и это одна из причин, по которой, например, STL тормозит. Из-за этого, например, фирма Electronic Arts написала свою реализацию STL.
Re[2]: massive inline
От: Тролль-323  
Дата: 01.10.09 19:01
Оценка:
SC>1. В общем случае, компилятор недостаточно умен. По крайней мере вдумчивое расставление __forceinlinе для MSVC не раз приводило к заметному приросту производительности на критических участках.

На самом деле, он часто не то, чтобы недостаточно умен, а просто откровенно туп. Например, может не заинлайнить крайне часто вызывающуюся функцию по каким-то неизвестным причинам, что катастрофически может сказаться на производительности программы.
Re[3]: massive inline
От: Кодт Россия  
Дата: 01.10.09 19:21
Оценка:
Здравствуйте, Тролль-323, Вы писали:

Т3>На самом деле, он часто не то, чтобы недостаточно умен, а просто откровенно туп. Например, может не заинлайнить крайне часто вызывающуюся функцию по каким-то неизвестным причинам, что катастрофически может сказаться на производительности программы.


Когда ему нужно выбрать между оптимизацией размера и оптимизацией скорости — кто знает, что он предпочтёт?
Можно, конечно, поиграть с опциями favor speed / favor size и посмотреть.
Перекуём баги на фичи!
Re[4]: massive inline
От: Sergey Chadov Россия  
Дата: 02.10.09 06:24
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Когда ему нужно выбрать между оптимизацией размера и оптимизацией скорости — кто знает, что он предпочтёт?

К>Можно, конечно, поиграть с опциями favor speed / favor size и посмотреть.

Ни разу я от этой галочки никакого видимого профиту не поимел
Re[4]: massive inline
От: CreatorCray  
Дата: 02.10.09 08:41
Оценка:
Здравствуйте, Тролль-323, Вы писали:

Т3>Кстати, тов. Саттер врет, что компилятор сам знает, когда инлайнить функции. Как показывает практика, ничего он не знает, и это одна из причин, по которой, например, STL тормозит. Из-за этого, например, фирма Electronic Arts написала свою реализацию STL.

Это смотря какой компилер. ICC например отлично справляется если ему разрешить (/Ob2)
А писать свой STL обычно приходится потому, что зачастую надо добавить во главу угла такие первоочередной важности параметры как быстродействие и потребление памяти.
Бо в стандарте на STL про них почти не упомянуто. EA — крупные игроделы, а крупным игроделам производительность и потребление очень важны.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.