Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #28602 > unrolled thread

inline functions

Started by"BartC" <bc@freeuk.com>
First post2012-11-24 12:20 +0000
Last post2012-11-25 01:18 -0800
Articles 18 on this page of 58 — 20 participants

Back to article view | Back to comp.lang.c


Contents

  inline functions "BartC" <bc@freeuk.com> - 2012-11-24 12:20 +0000
    Re: inline functions SG <sgesemann@gmail.invalid> - 2012-11-24 14:52 +0100
      Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-24 14:48 +0000
        Re: inline functions Joost Kraaijeveld <J.Kraaijeveld@Askesis.nl> - 2012-11-24 15:59 +0100
        Re: inline functions Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2012-11-24 16:25 +0100
        Re: inline functions Johann Klammer <klammerj@NOSPAM.a1.net> - 2012-11-24 19:18 +0100
    Re: inline functions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-11-24 15:07 +0000
      Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-24 15:33 +0000
        Re: inline functions Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2012-11-24 17:17 +0100
          Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-24 16:39 +0000
            Re: inline functions Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2012-11-24 18:13 +0100
              Re: inline functions Jens Gustedt <jens.gustedt@loria.fr> - 2012-11-24 19:36 +0100
                Re: inline functions Sergio Durigan Junior <sergiodj@riseup.net> - 2012-12-05 03:19 -0200
                  Re: inline functions Jens Gustedt <jens.gustedt@loria.fr> - 2012-12-05 10:57 +0100
                    Re: inline functions Sergio Durigan Junior <sergiodj@riseup.net> - 2012-12-05 15:34 -0200
          Re: inline functions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-11-25 09:43 +0000
            Re: inline functions Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2012-11-25 11:32 +0100
              Re: inline functions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-11-27 21:55 +0000
          Re: inline functions "christian.bau" <christian.bau@cbau.wanadoo.co.uk> - 2012-11-26 04:16 -0800
            Re: inline functions David Brown <david@westcontrol.removethisbit.com> - 2012-11-26 14:13 +0100
              Re: inline functions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-11-28 21:27 +0000
                Re: inline functions James Kuyper <jameskuyper@verizon.net> - 2012-11-28 16:40 -0500
                  Re: inline functions Ben Pfaff <blp@cs.stanford.edu> - 2012-11-28 14:15 -0800
                    Re: inline functions Sergio Durigan Junior <sergiodj@riseup.net> - 2012-11-29 00:02 -0200
                  Re: inline functions Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-11-29 07:24 -0800
                    Re: inline functions James Kuyper <jameskuyper@verizon.net> - 2012-11-29 11:04 -0500
                      Re: inline functions Sergio Durigan Junior <sergiodj@riseup.net> - 2012-11-29 14:44 -0200
                        Re: inline functions Les Cargill <lcargill99@comcast.com> - 2012-11-29 12:44 -0600
                          Re: inline functions Sergio Durigan Junior <sergiodj@riseup.net> - 2012-11-29 20:43 -0200
                            Re: inline functions Les Cargill <lcargill99@comcast.com> - 2012-11-29 20:14 -0600
                      Re: inline functions Ian Collins <ian-news@hotmail.com> - 2012-11-30 07:44 +1300
                        Re: inline functions Sergio Durigan Junior <sergiodj@riseup.net> - 2012-11-29 20:38 -0200
                  Re: inline functions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-12-05 03:17 +0000
                    Re: inline functions Noob <root@127.0.0.1> - 2012-12-05 11:26 +0100
        Re: inline functions David Brown <david@westcontrol.removethisbit.com> - 2012-11-26 11:23 +0100
          Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-26 13:01 +0000
            Re: inline functions David Brown <david@westcontrol.removethisbit.com> - 2012-11-26 14:24 +0100
              Re: inline functions Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-11-26 05:35 -0800
                Re: inline functions Les Cargill <lcargill99@comcast.com> - 2012-11-26 07:57 -0600
                  Re: inline functions Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-11-26 07:07 -0800
                Re: inline functions Rosario1903 <Rosario@invalid.invalid> - 2012-11-27 09:46 +0100
                Re: inline functions David Brown <david@westcontrol.removethisbit.com> - 2012-11-27 10:50 +0100
              Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-26 14:14 +0000
                Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-26 15:14 +0000
                Re: inline functions Rosario1903 <Rosario@invalid.invalid> - 2012-11-27 09:46 +0100
                  Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-27 14:41 +0000
                Re: inline functions David Brown <david@westcontrol.removethisbit.com> - 2012-11-27 11:01 +0100
                  Re: inline functions "BartC" <bc@freeuk.com> - 2012-11-27 14:37 +0000
                    Re: inline functions Alain Ketterlin <alain@dpt-info.u-strasbg.fr> - 2012-11-27 18:22 +0100
                    Re: inline functions James Kuyper <jameskuyper@verizon.net> - 2012-11-27 12:55 -0500
                  Re: inline functions Jorgen Grahn <grahn+nntp@snipabacken.se> - 2012-11-27 22:06 +0000
                    Re: inline functions David Brown <david@westcontrol.removethisbit.com> - 2012-11-29 09:47 +0100
            Re: inline functions glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-11-26 14:39 +0000
    Re: inline functions Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-11-24 07:20 -0800
      Re: inline functions James Kuyper <jameskuyper@verizon.net> - 2012-11-24 10:44 -0500
    Re: inline functions James Kuyper <jameskuyper@verizon.net> - 2012-11-24 10:35 -0500
    Re: inline functions Philip Lantz <prl@canterey.us> - 2012-11-24 22:56 -0800
    Re: inline functions James Dow Allen <jdallen2000@yahoo.com> - 2012-11-25 01:18 -0800

Page 3 of 3 — ← Prev page 1 2 [3]


#28673

FromRosario1903 <Rosario@invalid.invalid>
Date2012-11-27 09:46 +0100
Message-ID<3fv8b81ul5l2cio6ommdfbbvvuv96phgfs@4ax.com>
In reply to#28662
On Mon, 26 Nov 2012 05:35:54 -0800 (PST), Malcolm McLean
<malcolm.mclean5@btinternet.com> wrote:

>On Monday, November 26, 2012 1:30:03 PM UTC, David Brown wrote:
>> On 26/11/2012 14:01, BartC wrote:
>> 
>> gcc /can/ inline calls through function pointers (which is pretty 
>> impressive, IMHO), but only when it can tell what the function will be.
>> 
>That's handy. You very frequently need something like this
>
>int trivialcompfunc(const void *e1, const void *e2)
>{
>  const int *i1 = e1;
>  const int *i2 = e2;
>
>  return *i1 - *i2;
>}
>
>void complexalgorithm(int *array, int N)
>{
>   qsort(array, N, sizeof(int), comfunc);
>}
>
>clearly if we can inline trivialcompfunc it;'s likely to have a substantial
>effect on perfomance.

easy one can "inline" it, it is enought have the algo qsort, and
rewrite qsort for that compare function...

[toc] | [prev] | [next] | [standalone]


#28676

FromDavid Brown <david@westcontrol.removethisbit.com>
Date2012-11-27 10:50 +0100
Message-ID<8e2dnWBIAsQREynNnZ2dnUVZ8oSdnZ2d@lyse.net>
In reply to#28662
On 26/11/2012 14:35, Malcolm McLean wrote:
> On Monday, November 26, 2012 1:30:03 PM UTC, David Brown wrote:
>> On 26/11/2012 14:01, BartC wrote:
>>
>> gcc /can/ inline calls through function pointers (which is pretty
>> impressive, IMHO), but only when it can tell what the function will be.
>>
> That's handy. You very frequently need something like this
>
> int trivialcompfunc(const void *e1, const void *e2)
> {
>    const int *i1 = e1;
>    const int *i2 = e2;
>
>    return *i1 - *i2;
> }
>
> void complexalgorithm(int *array, int N)
> {
>     qsort(array, N, sizeof(int), comfunc);
> }
>
> clearly if we can inline trivialcompfunc it;'s likely to have a substantial
> effect on perfomance.
>

That would be possible if and only if the compiler was also able to 
inline qsort.  I'm sure you'll see why if you think about it.

[toc] | [prev] | [next] | [standalone]


#28664

From"BartC" <bc@freeuk.com>
Date2012-11-26 14:14 +0000
Message-ID<eQKss.416451$GX.160924@fx01.am4>
In reply to#28661
"David Brown" <david@westcontrol.removethisbit.com> wrote in message 
news:q-qdnajpsMhH8y7NnZ2dnUVZ7qidnZ2d@lyse.net...
> On 26/11/2012 14:01, BartC wrote:

>> I know little about instruction caches. I wouldn't have thought all these
>> functions together were that big (the whole program is only 120K and 
>> might
>> be double that when finished). Would it help if the most common functions
>> (or perhaps the smallest), were together? (But I don't even know if gcc
>> reorders my functions anyway.)
>
> Cache sizes depend on the processor, but an Intel i7 (as an example) has 
> 32 KB level 1 instruction cache as far as I know.  I am not saying that 
> this /is/ a problem in your code, but it certainly could be (and the risk 
> gets higher as you fill out the stub functions).

OK, I thought they were of the order of 1MB or something.

One advantage of a simple interpreter, is that the code *is* localised, 
because usually a few dozen handlers are constantly being executed, no 
matter how big the target program is. So maybe I'm already benefitting!

> Yes, gcc re-orders your code (assuming, as always, you use appropriate 
> optimisation levels).
>
> Depending on the version of gcc that you are using, it might also split 
> your code automatically into "hot" and "cold" code.  "hot" code is things 
> like inner loops, while "cold" code is things like initialisation code. 
> gcc will re-arrange the order of the code to make "hot" code stick 
> together - this improves cache locality when running.  You can also mark 
> functions as "hot" or "cold" using attributes, or automatically by using 
> profiling.

The problem with an instruction dispatcher like I have is that I can't see 
how the compiler can guess which are the more heavily used functions; they 
all have equal 'weight'.

The information needed for that isn't in the structure of the C source code, 
but in the structure of the bytecode program, which is data that is read 
into the C program.

So I will try and do something with those inlining attributes when I've 
finished development (at the moment it's just a distraction, so those 
functions are kept external. Then I will know if any increase/reduction is 
speed is do with my code, rather than a different inlining strategy coming 
into play).

>>> A couple of other ideas spring to mind for the program.  One is to
>>> re-structure with a table of function pointers rather than a huge
>>> switch -
>>> it might also make the program clearer and easier to work with.

>> With both Switch and Label pointers, there is a specific call in the 
>> source
>> to each of the 350 functions, and inlining is possible. With function
>> pointers, there is just one call, so inlining can't happen. So that's a 
>> big
>> disadvantage.

> gcc /can/ inline calls through function pointers (which is pretty 
> impressive, IMHO), but only when it can tell what the function will be.

It'll have it's work cut out here:

typedef void (*(*fnptr))(void);

do {
(**(fnptr)(pcptr))();
} while (1);

I wouldn't even know where to start! (pcptr[] is an array of mixed-use 
integers, some of which will be function pointers, which is set up at 
runtime.)

-- 
bartc 

[toc] | [prev] | [next] | [standalone]


#28668

From"BartC" <bc@freeuk.com>
Date2012-11-26 15:14 +0000
Message-ID<DLLss.354287$YJ1.149133@fx09.am4>
In reply to#28664
"BartC" <bc@freeuk.com> wrote in message
news:eQKss.416451$GX.160924@fx01.am4...

> So I will try and do something with those inlining attributes when I've
> finished development (at the moment it's just a distraction, so those
> functions are kept external. Then I will know if any increase/reduction is
> speed is do with my code, rather than a different inlining strategy coming
> into play).

I decided to try something with inlining now. With all my functions in the
same file as the dispatch code, but all with 'noline' attribute, the timings
are the same as when the functions are external:

Switch:         75 seconds
Label ptrs:     66 seconds

With all functions using 'always_inline', I get:

Switch:         60 seconds
Label ptrs:     48 seconds

About 37% increase in performance (27% decrease in execution time), using
label pointers (but a switch still needs to be considered, as label pointers
are not portable).

I was a bit worried because many functions are now called in several places
(some handlers are wrappers or stubs for others), but it seemed to work out.

(I'm quite impressed. When I first tried a C version of this project, it was
about 1/3 the speed of my last (experimental) interpreter, and 1/2 the speed
of my current production interpreter. That 48 seconds makes it faster than
that latter one!

There is also a way of getting better performance: to generate C source code 
instead, a series of function calls, to a modified set of handlers. Then it 
will be faster than either, but it will no longer be quite so dynamic then 
when it's hard-coded into the C program...)

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#28674

FromRosario1903 <Rosario@invalid.invalid>
Date2012-11-27 09:46 +0100
Message-ID<8fv8b8t20l3rc190c3gmjdat1jpbv6mm69@4ax.com>
In reply to#28664
On Mon, 26 Nov 2012 14:14:58 -0000, "BartC" <bc@freeuk.com> wrote:


>typedef void (*(*fnptr))(void);
>
>do {
>(**(fnptr)(pcptr))();
>} while (1);
>

is it for a 64 bit program?

[toc] | [prev] | [next] | [standalone]


#28680

From"BartC" <bc@freeuk.com>
Date2012-11-27 14:41 +0000
Message-ID<%i4ts.673945$A%.398999@fx26.am4>
In reply to#28674

"Rosario1903" <Rosario@invalid.invalid> wrote in message 
news:8fv8b8t20l3rc190c3gmjdat1jpbv6mm69@4ax.com...
> On Mon, 26 Nov 2012 14:14:58 -0000, "BartC" <bc@freeuk.com> wrote:
>
>
>>typedef void (*(*fnptr))(void);
>>
>>do {
>>(**(fnptr)(pcptr))();
>>} while (1);
>>
>
> is it for a 64 bit program?

This interpreter is designed for a 32-bit processor. The C compiler I use I 
guess generates code for 32-bits too. (I think it must do because int and 
pointer sizes are 32-bits and I don't remember seeing 64-bit instructions in 
the output.)

64-bits wouldn't help in this case unless everything was redesigned, and 
then I might be lucky to get achieve the same speed as a 32-bit program.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#28677

FromDavid Brown <david@westcontrol.removethisbit.com>
Date2012-11-27 11:01 +0100
Message-ID<H6udnZich5mHDCnNnZ2dnUVZ8rOdnZ2d@lyse.net>
In reply to#28664
On 26/11/2012 15:14, BartC wrote:
> "David Brown" <david@westcontrol.removethisbit.com> wrote in message
> news:q-qdnajpsMhH8y7NnZ2dnUVZ7qidnZ2d@lyse.net...
>> On 26/11/2012 14:01, BartC wrote:
>
>>> I know little about instruction caches. I wouldn't have thought all
>>> these
>>> functions together were that big (the whole program is only 120K and
>>> might
>>> be double that when finished). Would it help if the most common
>>> functions
>>> (or perhaps the smallest), were together? (But I don't even know if gcc
>>> reorders my functions anyway.)
>>
>> Cache sizes depend on the processor, but an Intel i7 (as an example)
>> has 32 KB level 1 instruction cache as far as I know.  I am not saying
>> that this /is/ a problem in your code, but it certainly could be (and
>> the risk gets higher as you fill out the stub functions).
>
> OK, I thought they were of the order of 1MB or something.
>

Modern processors often have three levels of cache - plus some small and 
even faster buffers.  Successive cache levels are bigger but slower, and 
they can be split (instruction and data) or shared, and they can be 
dedicated to a core or shared among the cores.  Depending on the exact 
model, the i7 has 32K L1 data and 32K L1 instruction and 1 MB L2 
combined cache per core, along with 8 MB L3 cache shared across all cores.

Of course, details vary for different processors.  And other processes 
that are running (like the OS) use space in the cache.

In other words, it is really complicated trying to figure out the 
optimal sizes for programs or data, and you don't get exactly 
deterministic results.  But smaller programs - especially for the code 
that is running a lot - and smaller critical data areas will give more 
cache hits.

> One advantage of a simple interpreter, is that the code *is* localised,
> because usually a few dozen handlers are constantly being executed, no
> matter how big the target program is. So maybe I'm already benefitting!
>
>> Yes, gcc re-orders your code (assuming, as always, you use appropriate
>> optimisation levels).
>>
>> Depending on the version of gcc that you are using, it might also
>> split your code automatically into "hot" and "cold" code.  "hot" code
>> is things like inner loops, while "cold" code is things like
>> initialisation code. gcc will re-arrange the order of the code to make
>> "hot" code stick together - this improves cache locality when
>> running.  You can also mark functions as "hot" or "cold" using
>> attributes, or automatically by using profiling.
>
> The problem with an instruction dispatcher like I have is that I can't
> see how the compiler can guess which are the more heavily used
> functions; they all have equal 'weight'.
>
> The information needed for that isn't in the structure of the C source
> code, but in the structure of the bytecode program, which is data that
> is read into the C program.

That is why you need to use profiling.  That means you run the program 
with real-world data (in this case, typical bytecode programs), and let 
the profiler count the number of times functions really are used.  This 
profile data gets fed back to the compiler, which then knows how to 
weight different functions.

Profiling is not easy to do well (I have seldom done it myself - but 
most of my work is small-system embedded programming, and not well 
suited to that type of profiling) - but it can give very good results.

>
> So I will try and do something with those inlining attributes when I've
> finished development (at the moment it's just a distraction, so those
> functions are kept external. Then I will know if any increase/reduction
> is speed is do with my code, rather than a different inlining strategy
> coming into play).
>

[toc] | [prev] | [next] | [standalone]


#28679

From"BartC" <bc@freeuk.com>
Date2012-11-27 14:37 +0000
Message-ID<%i4ts.673944$A%.7879@fx26.am4>
In reply to#28677
"David Brown" <david@westcontrol.removethisbit.com> wrote in message 
news:H6udnZich5mHDCnNnZ2dnUVZ8rOdnZ2d@lyse.net...
> On 26/11/2012 15:14, BartC wrote:

>> The problem with an instruction dispatcher like I have is that I can't
>> see how the compiler can guess which are the more heavily used
>> functions; they all have equal 'weight'.

> That is why you need to use profiling.  That means you run the program 
> with real-world data (in this case, typical bytecode programs), and let 
> the profiler count the number of times functions really are used.  This 
> profile data gets fed back to the compiler, which then knows how to weight 
> different functions.

How does it 'get fed back to the compiler'?


-- 
Bartc

 

[toc] | [prev] | [next] | [standalone]


#28686

FromAlain Ketterlin <alain@dpt-info.u-strasbg.fr>
Date2012-11-27 18:22 +0100
Message-ID<87boej55bw.fsf@dpt-info.u-strasbg.fr>
In reply to#28679
"BartC" <bc@freeuk.com> writes:

> "David Brown" <david@westcontrol.removethisbit.com> wrote in message
> news:H6udnZich5mHDCnNnZ2dnUVZ8rOdnZ2d@lyse.net...
>> On 26/11/2012 15:14, BartC wrote:
>
>>> The problem with an instruction dispatcher like I have is that I can't
>>> see how the compiler can guess which are the more heavily used
>>> functions; they all have equal 'weight'.
>
>> That is why you need to use profiling.  That means you run the
>> program with real-world data (in this case, typical bytecode
>> programs), and let the profiler count the number of times functions
>> really are used.  This profile data gets fed back to the compiler,
>> which then knows how to weight different functions.
>
> How does it 'get fed back to the compiler'?

Depends on your compiler. With gcc, see -fprofile-generate/-fprofile-use
and friends.

-- Alain.

[toc] | [prev] | [next] | [standalone]


#28687

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-11-27 12:55 -0500
Message-ID<50B4FE86.8090404@verizon.net>
In reply to#28679
On 11/27/2012 09:37 AM, BartC wrote:
> "David Brown" <david@westcontrol.removethisbit.com> wrote in message 
> news:H6udnZich5mHDCnNnZ2dnUVZ8rOdnZ2d@lyse.net...
...
>> ...  This 
>> profile data gets fed back to the compiler, which then knows how to weight 
>> different functions.
> 
> How does it 'get fed back to the compiler'?

A compiler option tells it to retrieve that information from the file
that it's stored in. gcc, for instance, the profile data has the
extension ".gcda". You should look at the documentation for the
following gcc profile-related options:

-p
-pg
-fprofile-arcs
-fprofile-values
-fprofile-generate
-fbranch-probabilities
-freorder-functions
-fprofile-use (which enables "feedback directed optimizations, and
optimizations generally profitable only with profile feedback enabled",
including -fvpt -funroll-loops -fpeel-loops -ftracer -fno-loop-optimize)
-param min-inline-recursive-probability
-param tracer-dynamic-coverage
-param tracer-dynamic-coverage-feedback
-param tracer-min-branch-ratio
-param tracer-min-branch-ratio-feedback
-param reorder-blocks-duplicate
-param reorder-blocks-duplicate-feedback

[toc] | [prev] | [next] | [standalone]


#28697

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2012-11-27 22:06 +0000
Message-ID<slrnkbaebh.1jc.grahn+nntp@frailea.sa.invalid>
In reply to#28677
On Tue, 2012-11-27, David Brown wrote:
> On 26/11/2012 15:14, BartC wrote:
...
>> The information needed for that isn't in the structure of the C source
>> code, but in the structure of the bytecode program, which is data that
>> is read into the C program.
>
> That is why you need to use profiling.  That means you run the program 
> with real-world data (in this case, typical bytecode programs), and let 
> the profiler count the number of times functions really are used.  This 
> profile data gets fed back to the compiler, which then knows how to 
> weight different functions.

Nitpick: what you're describing is more widely known as
"profile-guided optimization" or "profiler-guided optimization".

When you say "profiling" I think of the traditional (and orthogonal!)
approach: running a profiler and reading and thinking about the
results, possibly doing manual optimization work.

/Jorgem

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#28780

FromDavid Brown <david@westcontrol.removethisbit.com>
Date2012-11-29 09:47 +0100
Message-ID<OdWdnX8RtuVfvyrNnZ2dnUVZ8uSdnZ2d@lyse.net>
In reply to#28697
On 27/11/2012 23:06, Jorgen Grahn wrote:
> On Tue, 2012-11-27, David Brown wrote:
>> On 26/11/2012 15:14, BartC wrote:
> ...
>>> The information needed for that isn't in the structure of the C source
>>> code, but in the structure of the bytecode program, which is data that
>>> is read into the C program.
>>
>> That is why you need to use profiling.  That means you run the program
>> with real-world data (in this case, typical bytecode programs), and let
>> the profiler count the number of times functions really are used.  This
>> profile data gets fed back to the compiler, which then knows how to
>> weight different functions.
>
> Nitpick: what you're describing is more widely known as
> "profile-guided optimization" or "profiler-guided optimization".
>
> When you say "profiling" I think of the traditional (and orthogonal!)
> approach: running a profiler and reading and thinking about the
> results, possibly doing manual optimization work.
>

Yes, that is correct.  Giving BartC the correct terms here might help 
him when googling for examples or tutorials - so it is a useful nitpick.

David

[toc] | [prev] | [next] | [standalone]


#28666

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2012-11-26 14:39 +0000
Message-ID<k8vuv3$nno$1@speranza.aioe.org>
In reply to#28659
BartC <bc@freeuk.com> wrote:

(snip)

> I know little about instruction caches. I wouldn't have thought all these
> functions together were that big (the whole program is only 120K and might
> be double that when finished). Would it help if the most common functions
> (or perhaps the smallest), were together? (But I don't even know if gcc
> reorders my functions anyway.)

I don't know that it is a problem in this case, but many machines have
separate instruction and data (I and D) caches, and get very slow if a
block has to switch from one to the other.

In the olden days, (say 40 to 50 years ago) it was usual for
instructions and data to be close together in a program.
(Especially for languages that didn't allow recursion, with all
data static.)

It might be that on some, the use of function pointers gets some
block to switch from one to the other. 

-- glen

[toc] | [prev] | [next] | [standalone]


#28610

FromMalcolm McLean <malcolm.mclean5@btinternet.com>
Date2012-11-24 07:20 -0800
Message-ID<4cf29216-e91e-4e0f-ace5-efbde9f737dc@googlegroups.com>
In reply to#28602
You can take the address of a function. Call it somewhere indirectly using a bit of logic the compiler can't optimise out, eg

int (*foo)(int) = notinlined;
unsigned char buff[ sizeof(foo) ];
memcpy(buff, &foo, sizeof(buff)];
x = sqrt((int)buff[0] * buff[0]));
if(x != floor(x))
  printf("%d\n", (*foo)(0));

it's a bit hacky. The compiler won't be clever enough to know that the square
root of a square is always an integer. Less drastic measures will work on 
most compilers.



 

[toc] | [prev] | [next] | [standalone]


#28616

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-11-24 10:44 -0500
Message-ID<k8qq1i$jk6$1@dont-email.me>
In reply to#28610
On 11/24/2012 10:20 AM, Malcolm McLean wrote:
> You can take the address of a function. Call it somewhere indirectly using a bit of logic the compiler can't optimise out, eg
> 
> int (*foo)(int) = notinlined;
> unsigned char buff[ sizeof(foo) ];
> memcpy(buff, &foo, sizeof(buff)];
> x = sqrt((int)buff[0] * buff[0]));
> if(x != floor(x))
>   printf("%d\n", (*foo)(0));
> 
> it's a bit hacky. The compiler won't be clever enough to know that the square
> root of a square is always an integer. Less drastic measures will work on 
> most compilers.

In the long run, you're better off looking for ways (usually
implementation-specific) to command the compiler to do what you want,
than trying to trick it into doing so. If you can figure it out, a
sufficiently clever compiler will figure it out. The only guaranteed
effect is to confuse other humans who need to read the tricky code.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#28614

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-11-24 10:35 -0500
Message-ID<k8qpgl$he4$1@dont-email.me>
In reply to#28602
On 11/24/2012 07:20 AM, BartC wrote:
> Is there a way of controlling which functions are inlined, or likely to be 
> inlined, and which ones you never want inlined?

The 'inline' keyword is only a hint; it doesn't guarantee anything. The
only way to be sure a function won't be inlined is to define it in a
different translation unit. There's no way to be sure it will be inlined
- even if you inline it yourself, manually, a sufficiently clever
compiler might reach the conclusion that that the common code used in
several different places in your program should be extracted into a
separate function.

> ... Especially with gcc...

gcc has dozens of options that contain the word "inline". I had planned
to read the description of each option, and recommend the one(s) that
seemed most relevant to your question. However, when I realized that
there were so many to choose from, I decided to let you do the reading.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#28635

FromPhilip Lantz <prl@canterey.us>
Date2012-11-24 22:56 -0800
Message-ID<MPG.2b1b6106181fe1e79896ce@news.eternal-september.org>
In reply to#28602
BartC wrote:
> 
> Is there a way of controlling which functions are inlined, or likely to be 
> inlined, and which ones you never want inlined ... with gcc?

Yes. I use the following macros

#define ALWAYS_INLINE __attribute__((always_inline))
#define NOINLINE __attribute__((noinline))

[toc] | [prev] | [next] | [standalone]


#28636

FromJames Dow Allen <jdallen2000@yahoo.com>
Date2012-11-25 01:18 -0800
Message-ID<0f3e6f23-80fd-4acd-ba7d-1d77fe38bc58@y5g2000pbi.googlegroups.com>
In reply to#28602
On Nov 24, 7:21 pm, "BartC" <b...@freeuk.com> wrote:
> Strange things are happening with performance, such as being 60%
> slower, when, for example, a function's body is populated with code (they
> start off empty), even though the function is never actually called.

The problem might be cache collisions, with two or more
pieces of executing code or data having the same low-order
address bits.  The uncalled function is linked between two
called functions whose relative addresses change.
Two experiments to investigate this possibility:
1.  Relocate the offending uncalled function: either
its position in a module, or the module's position in
load list.
2. Try *increasing* the amount of code in the uncalled function:
you'll eventually get back to a "sweet spot" where execution
is fast again.

Details may be complicated if your machine has two or more
interacting caches.  And permanent fix may be difficult even
if you identify such cache collisions as the cause of slowdown.

James

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.c


csiph-web