Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #28602 > unrolled thread
| Started by | "BartC" <bc@freeuk.com> |
|---|---|
| First post | 2012-11-24 12:20 +0000 |
| Last post | 2012-11-25 01:18 -0800 |
| Articles | 18 on this page of 58 — 20 participants |
Back to article view | Back to comp.lang.c
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]
| From | Rosario1903 <Rosario@invalid.invalid> |
|---|---|
| Date | 2012-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]
| From | David Brown <david@westcontrol.removethisbit.com> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | Rosario1903 <Rosario@invalid.invalid> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | David Brown <david@westcontrol.removethisbit.com> |
|---|---|
| Date | 2012-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]
| From | "BartC" <bc@freeuk.com> |
|---|---|
| Date | 2012-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]
| From | Alain Ketterlin <alain@dpt-info.u-strasbg.fr> |
|---|---|
| Date | 2012-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-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]
| From | Jorgen Grahn <grahn+nntp@snipabacken.se> |
|---|---|
| Date | 2012-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]
| From | David Brown <david@westcontrol.removethisbit.com> |
|---|---|
| Date | 2012-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]
| From | glen herrmannsfeldt <gah@ugcs.caltech.edu> |
|---|---|
| Date | 2012-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]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-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]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2012-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]
| From | Philip Lantz <prl@canterey.us> |
|---|---|
| Date | 2012-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]
| From | James Dow Allen <jdallen2000@yahoo.com> |
|---|---|
| Date | 2012-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