[fonc] Wrapping object references in NaN IEEE floats for performance (was Re: Linus...)

2013-01-01 Thread Paul D. Fernhout

On 1/1/13 3:43 AM, BGB wrote:

here is mostly that this still allows for type-tags in the
references, but would likely involve a partial switch to the use of
64-bit tagged references within some core parts of the VM (as a partial
switch away from magic pointers). I am currently leaning towards
putting the tag in the high-order bits (to help reduce 64-bit arithmetic
ops on x86).


One idea I heard somewhere (probably on some Squeak-related list several 
years ago) is to have all objects stored as floating point NaN instances 
(NaN == Not a Number). The biggest bottleneck in practice for many 
applications that need computer power these days (like graphical 
simulations) usually seems to be floating point math, especially with 
arrays of floating point numberls. Generally when you do most other 
things, you're already paying some other overhead somewhere already. But 
multiplying arrays of floats efficiently is what makes or breaks many 
interesting applications. So, by wrapping all other objects as instances 
of floating point numbers using the NaN approach, you are optimizing for 
the typically most CPU intensive case of many user applications. 
Granted, there is going to be tradeoffs like integer math and so looping 
might then probably be a bit slower? Perhaps there is some research 
paper already out there about the tradeoffs for this sort of approach?


For more background, see:
  http://en.wikipedia.org/wiki/NaN
For example, a bit-wise example of a IEEE floating-point standard 
single precision (32-bit) NaN would be: s111  1axx    
  where s is the sign (most often ignored in applications), a 
determines the type of NaN, and x is an extra payload (most often 
ignored in applications)


So, information about other types of objects would start in that extra 
payload part. There may be some inconsistency in how hardware 
interprets some of these bits, so you'd have to think about if that 
could be worked around if you want to be platform-independent.


See also:
  http://en.wikipedia.org/wiki/IEEE_floating_point

You might want to just go with 64 bit floats, which would support 
wrapping 32 bit integers (including as pointers to an object table if 
you wanted, even up to probably around 52 bit integer pointers); see:

  IEEE 754 double-precision binary floating-point format: binary64
  http://en.wikipedia.org/wiki/Binary64


does sometimes seem like I am going in circles at times though...


I know that feeling myself, as I've been working on semantic-related 
generally-triple-based stuff for going on 30 years, and I still feel 
like the basics could be improved. :-)


Meanwhile I'm going to think about Alan Kay's latest comments...

--Paul Fernhout
http://www.pdfernhout.net/

The biggest challenge of the 21st century is the irony of technologies 
of abundance in the hands of those thinking in terms of scarcity.

___
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc


Re: [fonc] Wrapping object references in NaN IEEE floats for performance (was Re: Linus...)

2013-01-01 Thread BGB

On 1/1/2013 6:36 PM, Paul D. Fernhout wrote:

On 1/1/13 3:43 AM, BGB wrote:

here is mostly that this still allows for type-tags in the
references, but would likely involve a partial switch to the use of
64-bit tagged references within some core parts of the VM (as a partial
switch away from magic pointers). I am currently leaning towards
putting the tag in the high-order bits (to help reduce 64-bit arithmetic
ops on x86).


One idea I heard somewhere (probably on some Squeak-related list 
several years ago) is to have all objects stored as floating point NaN 
instances (NaN == Not a Number). The biggest bottleneck in practice 
for many applications that need computer power these days (like 
graphical simulations) usually seems to be floating point math, 
especially with arrays of floating point numberls. Generally when you 
do most other things, you're already paying some other overhead 
somewhere already. But multiplying arrays of floats efficiently is 
what makes or breaks many interesting applications. So, by wrapping 
all other objects as instances of floating point numbers using the NaN 
approach, you are optimizing for the typically most CPU intensive case 
of many user applications. Granted, there is going to be tradeoffs 
like integer math and so looping might then probably be a bit slower? 
Perhaps there is some research paper already out there about the 
tradeoffs for this sort of approach?




I actually tried this already...

I had borrowed the idea originally off of Lua (a paper I was reading 
talking about it mentioned it as having been used in Lua).



the problems were, primarily on 64-bit targets:
my other code assumed value-ranges which didn't fit nicely in the 52-bit 
mantissa;

being a NaN obscured the pointers from the GC;
it added a fair bit of cost to pointer and integer operations;
...

granted, you only really need 48 bits for current pointers on x86-64, 
the problem was that other code had been already assuming using a 56-bit 
tagged space when using pointers (spaces), leaving a little bit of a 
problem of 5652.


so, everything was crammed into the mantissa somewhat inelegantly, and 
the costs regarding integer and pointer operations made it not really an 
attractive option.


all this was less of an issue with 32-bit x86, as I could essentially 
just shove the whole pointer into the mantissa (spaces and all), and 
the GC wouldn't be confused by the value.



basically, what spaces is, is that a part of the address space will 
basically be used and divided up into a number of regions for various 
dynamically typed values (the larger ones being for fixnum and flonum).


on 32-bit targets, spaces is 30 bits, and located between the 3GB and 
4GB address mark (which the OS generally reserves for itself). on 
x86-64, currently it is a 56-bit space located at 0x7F00_.




For more background, see:
  http://en.wikipedia.org/wiki/NaN
For example, a bit-wise example of a IEEE floating-point standard 
single precision (32-bit) NaN would be: s111  1axx    
  where s is the sign (most often ignored in applications), a 
determines the type of NaN, and x is an extra payload (most often 
ignored in applications)


So, information about other types of objects would start in that 
extra payload part. There may be some inconsistency in how hardware 
interprets some of these bits, so you'd have to think about if that 
could be worked around if you want to be platform-independent.


See also:
  http://en.wikipedia.org/wiki/IEEE_floating_point

You might want to just go with 64 bit floats, which would support 
wrapping 32 bit integers (including as pointers to an object table if 
you wanted, even up to probably around 52 bit integer pointers); see:

  IEEE 754 double-precision binary floating-point format: binary64
  http://en.wikipedia.org/wiki/Binary64



yep...

my current tagging scheme partly incorporates parts of double, mostly in 
the sense that some tags were chosen mostly such that a certain range of 
doubles could be passed through unmodified and with full precision.


the drawback is that 0 is special, and I haven't yet thought up a good 
way around this issue.


admittedly I am not entirely happy with the handling of fixnums either 
(more arithmetic and conditionals than I would like).



here is what I currently have:
http://cr88192.dyndns.org:8080/wiki/index.php/Tagged_references



does sometimes seem like I am going in circles at times though...


I know that feeling myself, as I've been working on semantic-related 
generally-triple-based stuff for going on 30 years, and I still feel 
like the basics could be improved. :-)




yes.

well, in this case, it is that I have bounced back and forth between 
tagged-references and magic pointers multiple times over the years.


granted, this would be the first time I am doing so using fixed 64-bit 
tagged references.



granted, on x86-64, I will probably end up later merging a lot of this 
back into the