PDA

View Full Version : Quickest way to do an If val1 = val2 with Word variables



bcd
- 18th April 2010, 09:07
Hi There all,

I am working on a program that has an interrupt routine that need to do a very fast "if val1 = val2 then", but it seems to be taking a long time for the if..then to evaluate. Based on my measurements it is taking 60uS.

Yes I said 60uS ! This is a 16f1936 running at 32MHz. Problem is that I am in a serial interrupt routine where each character is only 36uS, so I need to see if I am at the chosen channel and if so to load it into a buffer.

I have the buffer code and it works as is, but at higher refresh rates I am loosing data and it looks like I am overflowing the buffers in the uart.

What I really want to know is taking hints from this thread : http://www.picbasic.co.uk/forum/showthread.php?t=12635
is there an easier way to compare word1 to word 2 and to do something if they are equal ??

Driving me mad !!

bill

Darrel Taylor
- 18th April 2010, 09:32
val1 VAR WORD
val2 VAR WORD

SLOW

IF val1 = val2 THEN SomeWhere

FASTer

IF val1.HighByte = val2.HighByte THEN
IF val1.LowByte = val2.LowByte THEN
GOTO SomeWhere
ENDIF
ENDIF

bcd
- 18th April 2010, 13:10
Hi Darrel,

Nope - same time. 60uS.
Think something weird might be going on here - might do some bare bones code.

bill.

Acetronics2
- 18th April 2010, 13:18
Hi, Bill

could you provide the "Guilty" interrupt code ???

easier to talk about real matter ...

Alain

PS: http://www.picbasic.co.uk/forum/showpost.php?p=84323&postcount=13 ... obviously raises some questions !!!

Phil Moore
- 19th April 2010, 12:45
Hi Bill,

How about:

if (A XORNOT B) then something

XORNOT is a logical comparison testing for equality basically...

Phil.

bcd
- 20th April 2010, 06:25
Interesting thoughts.
I think its time to do some bare bones code to see which works out to be quicker.

Bill.

bcd
- 22nd April 2010, 02:05
Hi Guys,

So I finally got some time to do some testing.

I have an admission to make - the 60uS I was seeing that started this whole process off seemed to be caused by failing to set my debug output that was watched with the logic analyser to a known state if the values didn't match...

What I did yesterday was run a few different comparison scenarios to see what sort of timing you got. Remember this is a 16f1933 running at 32Mhz, so instruction time is about 0.5us.

What I am doing is comparing the address I want to grab with the current position in the incoming data stream. I reset a counter when I see a header and then count each data packet coming in. When the address matches the count I receive the next three values into a buffer that the main code loop processes. The address can be a value from 1 - 512 so I need to use word variables.

Doing an if..then compare with two word variables takes 5.125 us


dbg_out = 1 ' set my debug line high for timing test
if current_position = current_add then

' do the buffer loading

endif
dbg_out = 0


Doing an if..then highbyte and lowbyte compare takes 2.125us


dbg_out = 1 ' set my debug line high for timing test
if current_position.highbyte = current_add.highbyte then ' 2.125 us
if current_position.lowbyte = current_add.lowbyte then

' do the buffer loading
endif
endif
dbg_out = 0



Doing an XORNOT compare takes 4.125us


dbg_out = 1 ' set my debug line high for timing test
if (current_position XORNOT current_add) then

' do the buffer loading

endif
dbg_out = 0



Doing an XORNOT Lowbyte Highbyte compare takes 7.625us


dbg_out = 1 ' set my debug line high for timing test
if (current_position.highbyte XORNOT current_add.highbyte) then
if (current_position.lowbyte XORNOT current_add.lowbyte) then

' do the buffer loading

endif
endif
dbg_out = 0


So it looks like Darell was correct that the fastest way is a If..Then with Lowbyte / Highbyte.

Bill.

Darrel Taylor
- 22nd April 2010, 02:57
http://www.pbpgroup.com/files/StickDance.gif

Ioannis
- 22nd April 2010, 08:36
In the comparissons you have made, were the two variables (either word or byte) equal?

That is important in your second case with the two If-Then's. In case the first if-then fails it will exit sooner.

Ioannis

Phil Moore
- 23rd April 2010, 01:12
Ioannis has a point (but maybe not the one I initially thought he was making... ).

What about:

if (a.highbyte xornot b.highbyte) and (a.lowbyte xornot b.lowbyte) then

' do stuff

endif

This removes an if-then macro/template from the timing equation. :)

You will always be making two comparisons to confirm equality, but there will be an overhead of potentially one unneccessary compare when a and b are not equal (but, hey, at least you know for sure how fast the code operates)

I'm sort of attached to xornot now...don't want to let it go...

Phil.

and I wish I had a stickfigure that did the 'dance of the happy programmer' :):)

Darrel Taylor
- 23rd April 2010, 02:00
The separate IF/THEN "templates" make it quicker.

When you have multiple AND's/OR's/XORNOT's etc. on the same line, then intermediate variables (T1+) are used to keep track of each "Term".
And T1+ variables are WORDs (LONGs for PBPL).
So while it looks shorter in the code listing, it really takes longer.<hr>

Well, I was trying to keep it straight PBP.
Which is why the previous example only got a "FASTer" rating.

But, if you want the "FASTest", ya gotta drop down to ASM with bank0/system variables.



val1 VAR WORD BANK0 SYSTEM
val2 VAR WORD BANK0 SYSTEM

ASM
movf val1+1, W
subwf val2+1, W
btfss STATUS, Z
goto NotEqual
movf val1, W
subwf val2, W
btfss STATUS, Z
goto NotEqual
L?GOTO _UserRoutine ; val1 = val2
NotEqual
ENDASM


UserRoutine:
;... yadda yadda ...


Of course, someone will probably find a "FASTest.er" way ... I hope. :)<hr>

ADDED:
The above can only be used once without modification.
But if you turn it into a Macro, it can be used multiple times, with different variables. (as long as they're in bank0)


val1 VAR WORD BANK0 SYSTEM
val2 VAR WORD BANK0 SYSTEM

ASM
DT_EQUAL macro v1, v2, label
local NotEqual
movf v1+1, W
subwf v2+1, W
btfss STATUS, Z
goto NotEqual
movf v1, W
subwf v2, W
btfss STATUS, Z
goto NotEqual
L?GOTO label ; v1 = v2
NotEqual
endm
ENDASM

;--- usage -------------------------
@ DT_EQUAL val1, val2, _UserRoutine ; IF val1 = val2 THEN UserRoutine


UserRoutine:
;... yadda yadda ...


hth,

sayzer
- 23rd April 2010, 07:46
Darrel,

Using the same way, (or a similar logic) can it be done to compare two words whether they are smaller or bigger?

Highy byte can always be bigger but low byte can be smaller.


___________

sayzer
- 24th April 2010, 14:09
I now see that my question already has the answer in itself.
Just compare the high byte, skip comparing the low; so in fact no need to compare the whole word.

:)

PickyBiker
- 24th April 2010, 16:44
Than's not a dancing stick figure, that's the skeleton of the internet dancing baby.4290