View previous topic :: View next topic |
Author |
Message |
TorAtle
Joined: 03 May 2004 Posts: 5
|
ROM, RAM and optimiser... |
Posted: Mon May 03, 2004 7:07 am |
|
|
PIC16F877.
Question: when near the limits of RAM usage, why does ROM start to suffer? I am trying to understand what the optimiser is thinking. Scenario:
ROM=7361, RAM worst case=276
Introducing int16 test[20] globally makes perfectly sense - ROM=7369, RAM worst case=316 (87%)
However increasing the size of the array above 20 will result in ROM usage, and I get out of ROM very quickly.
I can only assume that even though it looks like there's more RAM available the compiler makes use of it for optimising purposes. Can anyone shed any light on this and perhaps offer any workarounds? |
|
|
SteveS
Joined: 27 Oct 2003 Posts: 126
|
|
Posted: Mon May 03, 2004 7:41 am |
|
|
I think I know why, but I'm not sure; but here's how to figure it out:
Compile both ways and compare the listings. Then you'll know exactly what the compiler was thinking...
I suggest "Freediff" at http://www.saltybrine.com/ if you don't already have a file compare program.
- SteveS |
|
|
TorAtle
Joined: 03 May 2004 Posts: 5
|
|
Posted: Mon May 03, 2004 8:26 am |
|
|
Not very easy to see, as the addresses at the beginning of each line differs from a certain point and thus makes everything after that point "different".
I have 5 int16 arrays (none of them large). From what I could see, it moved one of them from one bank to another.
Btw, there's only one function which uses these arrays, and it takes a pointer to one of them as input. Could the code of this function be duplicated or something like this due to the input parameter pointing to different memory banks? |
|
|
Ttelmah Guest
|
Re: ROM, RAM and optimiser... |
Posted: Mon May 03, 2004 8:28 am |
|
|
TorAtle wrote: | PIC16F877.
Question: when near the limits of RAM usage, why does ROM start to suffer? I am trying to understand what the optimiser is thinking. Scenario:
ROM=7361, RAM worst case=276
Introducing int16 test[20] globally makes perfectly sense - ROM=7369, RAM worst case=316 (87%)
However increasing the size of the array above 20 will result in ROM usage, and I get out of ROM very quickly.
I can only assume that even though it looks like there's more RAM available the compiler makes use of it for optimising purposes. Can anyone shed any light on this and perhaps offer any workarounds? |
The obvious 'probability', is that the compiler is having to add more RAM bank switching, when extra variables are added. It prabably shifted something else, used more commonly, into another bank, to make room for the array. You can often 'improve' things yourself in this regard, by declaring registers that are used a lot early in the code, and thereby placing these in bank0.
Best Wishes |
|
|
Guest
|
|
Posted: Mon May 03, 2004 3:13 pm |
|
|
Ttelmah,
thanks a lot for that advice, you were spot on!
After some head scratching I came to the conclusion that finding the optimum memory bank for all the variables would be an impossible task, so what to do? Brute force!
I now have a little utility crunching away, testing every combination. Only 5% done so far but already I've saved over 300 bytes. That's about 5% less program memory used. Will report the final result when the utility is done. |
|
|
TorAtle
Joined: 03 May 2004 Posts: 5
|
|
Posted: Mon May 03, 2004 6:34 pm |
|
|
Sorry for failing to log in before my last post (above).
The utility I mentioned is now finished. First of all - the algorithm was flawed . It didn't go through all the combinations, not even close. In my case I had 72 global vars, the utility tested 72*71 combination. The correct answer is 72!, so quite a long way from it.
The idea was ok, though. In my case the difference between worst and best case was around 800 bytes (not including those combinations who resulted in 'out of rom'), or 10% of total program memory.
At this point I am unsure how to make a more clever algorithm, or in fact it it's worth the trouble. Two approaches that might yield reasonable results:
1) Count and sort the global vars; most used at the top.
2) Random order. Stop the utility when you're satisfied with the result. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue May 04, 2004 1:49 am |
|
|
This is a great idea! A tool for computing the optimal memory layout!
How did you do this?
Do you have all your global variables in a separate file and are you shuffling the lines in this file around?
I try to implement my programs with the concept of object orientation in mind, so I have a lot of separate files. I don't like to have my global variables in one single file, but in the CCS compiler this seems the only way to have some control over the memory layout. I also like to make some variables static to a function but ran into the same memory mapping problems.
What if we can play around a bit with your idea of a tool, and then ask CCS to integrate it in the compiler? The compiler is much more versatile and knows about all global variables, then you don't have to collect them in a single place but can scatter them all over your source files where they belong.
I like this concept!
Of course it should be possible to turn this optimization on/off. |
|
|
Ttelmah Guest
|
|
Posted: Tue May 04, 2004 2:04 am |
|
|
TorAtle wrote: | Sorry for failing to log in before my last post (above).
The utility I mentioned is now finished. First of all - the algorithm was flawed . It didn't go through all the combinations, not even close. In my case I had 72 global vars, the utility tested 72*71 combination. The correct answer is 72!, so quite a long way from it.
The idea was ok, though. In my case the difference between worst and best case was around 800 bytes (not including those combinations who resulted in 'out of rom'), or 10% of total program memory.
At this point I am unsure how to make a more clever algorithm, or in fact it it's worth the trouble. Two approaches that might yield reasonable results:
1) Count and sort the global vars; most used at the top.
2) Random order. Stop the utility when you're satisfied with the result. |
A brilliant idea.
The amount of the saving, is pretty impressive, even with the 'flawed' code, and relative to the versions you couldn' compile (with 'out of ROM'), must be even higher.
I think option '1', will do most to improve performance, so using this to choose between the best half dozen solutions, would seem to be a good 'performance/space' compromise solution.
Best Wishes |
|
|
TorAtle
Joined: 03 May 2004 Posts: 5
|
|
Posted: Tue May 04, 2004 6:03 am |
|
|
I have implemented the other 2 approaches I mentioned:
1) Count & sort - very good. Did better in my case than the flawed BruteForce method by 4 bytes...
2) Random - I won't say "better" or "worse" but I let it run overnight and it produced the best result. The reason for this is of course that it found a better combination than the flawed BruteForce. By luck! :-)
So...the Count&Sort looks like the best option - it's very fast and produces a good result.
I can clean up the code a bit and include all 3 methods if anyone would like to play? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue May 04, 2004 6:46 am |
|
|
Sounds good! I'm interrested in the count&sort method.
Thanks for sharing this knowledge with us! |
|
|
TorAtle
Joined: 03 May 2004 Posts: 5
|
|
Posted: Tue May 04, 2004 9:01 am |
|
|
http://home.c2i.net/toratlel/opt
Get opt.exe and save it in your project folder. To use the Count & Sort method, you will also need grep.exe and wc.exe, so download these too.
Grep.exe, wc.exe and also ccsc.exe (the compiler) must be somewhere referenced to by the %PATH% environment variable.
What you need to do:
Backup your files first!
1) Move all the global vars to <MyProject>.h
No tab's. Comments must ble placed after the declaration like so:
int16 iNumber; // comment here
Clear lines will degrade speed for the flawed BruteForce method.
2) Move all #define's and struct definitions to <MyProject>_define.h
3) Include those two files in your main source code file like so:
#include "myproject_define.h"
#include "myproject_opt.h"
Run opt.exe in a console window. To see the options, just run opt.exe without any arguments.
Let me say straight away that error handling is limited. If you have any questions or get any error messages you can't sort then email me at [email protected] |
|
|
|