From: Keith H Duggar on
On Jun 7, 11:09 am, Saeed Amrollahi <amrollahi.sa...(a)gmail.com> wrote:
> On Jun 7, 11:14 am, Keith H Duggar <dug...(a)alum.mit.edu> wrote:
> > On Jun 6, 6:15 pm, Saeed Amrollahi <amrollahi.sa...(a)gmail.com> wrote:
>
> > > On Jun 5, 11:50 pm, albert kao <albertk...(a)gmail.com> wrote:
> > > 3. There is no performance gain by rewriting bigger() with function
> > > object. Calling member function is almost as efficient as
> > > calling global function.
>
> > That is wrong. For most implementations of the STL you will find
> > that function objects can be /faster/ than passing free function
> > references/pointers. In the ops case
>
> > struct Bigger
> > {
> > bool operator ( ) ( int i ) const { return abs(i) >= D ; }
> > } ;
> > ...
> > count += count_if(diff + 1, diff + N, Bigger());
>
> > is likely to be much faster than
>
> > bool bigger(int i) { return abs(i) >= D; }
> > ...
> > count += count_if(diff + 1, diff + N, bigger);
>
> > Also, on many platforms
>
> > struct Bigger
> > {
> > bool operator ( ) ( int i ) const { return i >= D || i <= -
> > D ; }
> > } ;
>
> > will be faster still. Give it a try and you will see. By the way,
> > if you put the count_if into a loop you will get better sampling
> > and higher signal to noise. For example:
>
> > int count = 0 ;
> > for ( int k = 0 ; k < 1024 ; ++k ) {
> > count += count_if(diff + 1, diff + N, Bigger()) ;
> > }
>
> > KHD
>
> Hi Keith
>
> You are right. Of course we take advantage of inline expansion of
> operator(). In this case we have %25 performance improvement.
> For non-inline defintion (I mean defining function outside
> structure), the results are identical.
> The interesting question is:
> In case #1, when I declare bigger() with inline specifier, there is
> no performance improvement. Why?

Hi Saeed, given that Daniel and Alf have already explained the
reasons I will just mention that you can also work around this
issue and (usually) achieve the same performance by wrapping a
free function with a unique type viz:

bool bigger ( int i ) { return i >= D || i <= -D ; }

template < bool ( & func ) ( int i ) >
struct FuncWrap
{
bool operator ( ) ( int i ) const { return func(i) ; }
} ;

....

count += count_if(diff + 1, diff + N, FuncWrap<bigger>()) ;

The function reference is now a static argument and thus more
likely to be optimized as a direct call.

Unfortunately (AFAIK) you will need C++0x support in order to
do away with the non-type parameter explicit type declaration
(using auto and decltype).

KHD


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 17 Jun., 00:02, Keith H Duggar <dug...(a)alum.mit.edu> wrote:
> On Jun 7, 11:09 am, Saeed Amrollahi <amrollahi.sa...(a)gmail.com> wrote:

[..]

> given that Daniel and Alf have already explained the
> reasons I will just mention that you can also work around this
> issue and (usually) achieve the same performance by wrapping a
> free function with a unique type viz:
>
> bool bigger ( int i ) { return i >= D || i <= -D ; }
>
> template < bool ( & func ) ( int i ) >
> struct FuncWrap
> {
> bool operator ( ) ( int i ) const { return func(i) ; }
> } ;
>
> ...
>
> count += count_if(diff + 1, diff + N, FuncWrap<bigger>()) ;
>
> The function reference is now a static argument and thus more
> likely to be optimized as a direct call.
>
> Unfortunately (AFAIK) you will need C++0x support in order to
> do away with the non-type parameter explicit type declaration
> (using auto and decltype).

Or just use a normal wrapper functor:

struct BiggerWrap
{
bool operator()(int i) const { return bigger(i); }
};

[..]

count += count_if(diff + 1, diff + N, BiggerWrap()) ;

The pro is, that it works independent on the language
linkage of bigger,[1] the con is, that it scales badly
because I need a separate class for each function.

In C++ we can eat the sweet part of the fruit without
the sour part, if we take advantage of lambda
expressions:

count += count_if(diff + 1, diff + N, [](int i){ return bigger(i); });

Greetings from Bremen,

Daniel Kr�gler

[1] This is especially important, if you need to wrap
a standard C library function like int abs(int), where
it is implementation-defined, whether the linkage is
extern "C" or extern "C++".


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]