|
|
View previous topic :: View next topic |
Author |
Message |
evsource
Joined: 21 Nov 2006 Posts: 129
|
Slow compares with int16's |
Posted: Sat May 22, 2010 11:20 pm |
|
|
I'm trying to speed up a section of code, and noticed that the following surprised me with the number of instructions it involves:
Code: | if(first_variable > second_variable) third_variable = fourth_variable; |
All variables in the example are int16's.
The list file:
Code: |
07DFC: BTFSC x1B.7
07DFE: BRA 7E26
07E00: MOVLB 1
07E02: MOVF x9A,W
07E04: MOVLB 8
07E06: SUBWF x1B,W
07E08: BNC 7E26
07E0A: BNZ 7E1C
07E0C: MOVF x1A,W
07E0E: MOVLB 1
07E10: SUBWF x99,W
07E12: BTFSS FD8.0
07E14: BRA 7E1A
07E16: MOVLB 8
07E18: BRA 7E26
07E1A: MOVLB 8
07E1C: MOVFF 19A,7D
07E20: MOVFF 199,7C
|
Is there a faster way to do the compares? Or do they just really take that long to perform? |
|
|
vinniewryan
Joined: 29 Jul 2009 Posts: 154 Location: at work
|
|
Posted: Sun May 23, 2010 1:28 am |
|
|
That's just what it takes, as far as I know from how the condition works, it's comparing each bit from the highest of the int16 to the lowest, so it will compare each bit until it reaches the conclusion to the condition.
If firstvar is significantly greater than secondvar, it may be faster to use the following:
instead of:
if(first_variable > second_variable) //this should check each bit backwards until it reaches 'second_variable'
use:
if(second_variable < first_variable) //this should check each bit backwards until it reaches 'first variable'
Otherwise if you can use int8 instead of int16, it will also speed things up. _________________ Vinnie Ryan |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sun May 23, 2010 2:35 am |
|
|
It is basically 'what it takes'.
It doesn't do any form of bitwise comparison, it just performs a 16bit subtraction. However it is already quite efficient, in that lumps of the code are skipped if they "can't" apply.
Where you can save cycles, is in where the values are stored.
Nearly half the code, is basically switching banks to address the two values.
Two things apply. You will save a couple of instructions straight away, if the two values are in the same bank (declare them together). You can save more, by ensuring that they are in the bottom bank. Basically as a general 'layout' thing, declare the values which have the biggest effect on your code timing 'early' in your variable declarations. A search here, will find threads about the effect on speed of variable declaration order.
Best Wishes |
|
|
sjb
Joined: 13 Apr 2010 Posts: 34 Location: UK
|
|
Posted: Sun May 23, 2010 2:48 am |
|
|
Well, I get...
Code: | .................... if(first_variable>second_variable)
00078: MOVF 08,W
0007A: SUBWF 06,W
0007C: BNC 008E
0007E: BNZ 0086
00080: MOVF 05,W
00082: SUBWF 07,W
00084: BC 008E
.................... third_variable=fourth_variable;
00086: MOVFF 0C,0A
0008A: MOVFF 0B,09
.................... |
Which is shorted. I was just working with some 18F8722 code. would it depend on the processor/series.
EDIT:
But if I use signed int16 rather than int16 I get....
Code: | .................... if(first_variable>second_variable)
00078: BTFSS 08.7
0007A: BRA 0082
0007C: BTFSS 06.7
0007E: BRA 0094
00080: BRA 0086
00082: BTFSC 06.7
00084: BRA 009C
00086: MOVF 08,W
00088: SUBWF 06,W
0008A: BNC 009C
0008C: BNZ 0094
0008E: MOVF 05,W
00090: SUBWF 07,W
00092: BC 009C
.................... third_variable=fourth_variable;
00094: MOVFF 0C,0A
00098: MOVFF 0B,09
.................... |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sun May 23, 2010 7:20 am |
|
|
As I said, memory placement.
The big difference here, is that your two variables are adjacent, right at the bottom of memory.
So, if I simply declare two variables at the start of the code, placing them nice and low in memory, I get:
Code: |
.................... if(first_variable > second_variable) third_variable = fourth_variable;
0024: MOVF 07,W
0026: SUBWF 05,W
0028: BNC 003A
002A: BNZ 0032
002C: MOVF 04,W
002E: SUBWF 06,W
0030: BC 003A
0032: MOVFF 0B,09
0036: MOVFF 0A,08
|
However if I now locate 'first_variable' up to address 0x100, and 'second_variable' to 0x280, the code changes to:
Code: |
.................... if(first_variable > second_variable) third_variable = fourth_variable;
0024: MOVLB 2
0026: MOVF x81,W
0028: MOVLB 1
002A: SUBWF x01,W
002C: BNC 0048
002E: BNZ 0040
0030: MOVF x00,W
0032: MOVLB 2
0034: SUBWF x80,W
0036: BTFSS FD8.0
0038: BRA 003E
003A: MOVLB 1
003C: BRA 0048
003E: MOVLB 1
0040: MOVFF 07,05
0044: MOVFF 06,04
|
As I said, nearly half the code, is involved in handling bank switching, because of the location of the variables.
If you move the variables so they are adjacent (0x280, and 0x282), though not 'quite' as good as the version with them right at the bottom of memory, you get:
Code: |
0024: MOVLB 2
0026: MOVF x83,W
0028: SUBWF x81,W
002A: BNC 003C
002C: BNZ 0034
002E: MOVF x80,W
0030: SUBWF x82,W
0032: BC 003C
0034: MOVFF 07,05
0038: MOVFF 06,04
|
Only one extra instruction.
Memory placement is _everything_ on bank addressed chips like this.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|