must be a faster way (in SPIN)
Bobb Fwed
Posts: 1,119
I am generating a hash value to use as a table address. I want it to return an even number between (and including) 0 and less than the specified table size (which is a multiple of 32 or 64). For example, the table size can be 128, and I want the hash to give me an even value between 0 and 126 (inclusive).
In the past, I required the table size to be a value that was a exponential value of 2. This allowed me to just binary-AND it to the value range I need.
[hash is a generated value that can be any 32-bit value]
Previous code:
In the past, I required the table size to be a value that was a exponential value of 2. This allowed me to just binary-AND it to the value range I need.
[hash is a generated value that can be any 32-bit value]
Previous code:
hash &= constant(table_size - 2) ' takes 1008 cyclesNow, with the new number requirement, this is the fastest/best I can think of in the half hour I've been pondering it as I program other things:
hash := (||hash // constant(table_size / 2)) << 1 ' takes 1760 cycles (175% of the original time)This is way slower than before, and I was hoping someone on the forum here would know a faster way to get the same result. Even the smallest increase in speed would be helpful, as this method is called constantly throughout the object.
Comments
Andre'
-Phil
"table_size >> 1", instead of "table_size / 2" That will be a nice speed boost to the expression you showed us right there.
Shift right = divide by two, shift left = multiply by two. Another speed boost would be to get rid of the modulo, using shifts and adds to get to the proper table size. A few of those is quicker than one modulo, so you might see another gain doing that.
Best speed is a table that is a power of two, as was noted above.
This will be a non-booster ;o) He put the division into a constant statement, so it won't be executed at runtime at all. Nevertheless the tip is valid for other code.
And Bobb came from a power to two table size.
@Bobb:
Don't have the time currently to think about the problem in detail but here are my intermediate thoughts:
Create a bitmask dereived from table_size by simply setting all the least significant bits to 1 except bit 0 which is always 0. For example
table_size = %1001_1101 would then give a mask %1111_1110
This you can do by defining it as constant or if the table_size can change during runtime you'd only do at the time the size changes.
Then you and the hash with this mask as you did it with power of two table sizes.
Then you only need an if statement which checks if the hash is bigger than table_size and if so subtract the table_size from the hash.
Maybe this is faster.
Massimo
Since your table_size is essentially a power of 2, you can use the bitwise AND operator rather than the Modulus operator. That shaves 512 cycles off of your 1760.
He's doing it right. The range 0 .. strsize - 1 covers all the bytes.
-Phil
Yes, the reworked loop speeds things up. I remember now wanting to do that at one point, but it affects the output, so I didn't. But now I am requiring the tables to be rewritten after this version, because there are too many changes, so it's all good.
@Beau, I am trying to remove the power of two requirement. Currently it is required, but I'm trying to make the program more flexible to allow more precise use of the EEPROM.