What about others?
--
Cheers, www.indiegamedesign.com
Brandon Van Every Seattle, WA
"The pioneer is the one with the arrows in his back."
- anonymous entrepreneur
> Which MLs support 32-bit ints and/or 32-bit floats? To my knowledge:
> - SML/NJ, MLton support both
Unfortunately, this is not correct: SML/NJ does not have 32-bit floats
at this time. Maybe you are refering to the FFI which can -- on the
fly -- promote C's 32-bit floats to ML 64-bit reals. (OTOH, you can
can manipulate C's 32-bit floats from ML through the FFI.)
Implementing 32-bit float support in SML/NJ would be straightforward,
though. Someone just has to sit down and do it...
Cheers,
Matthias
I would say that 32-bit ints are supported in O'Caml:
http://caml.inria.fr/ocaml/htmlman/libref/Int32.html
cheers,
William
I stand corrected. It also seems that int32 is a boxed type, given the
notes on memory space and performance. Probably wouldn't matter for
straightforward computations, but it could definitely be a problem for C
structure packing. While I'm learning things, what MLs can support unboxed
C structures? How about unboxed arrays of such C structures? Such arrays
are very common in 3D graphics applications.
--
Cheers, www.indiegamedesign.com
Brandon Van Every Seattle, WA
20% of the world is real.
80% is gobbledygook we make up inside our own heads.
> [...] While I'm learning things, what MLs can support unboxed
> C structures? How about unboxed arrays of such C structures? Such arrays
> are very common in 3D graphics applications.
The interesting thing is that OpenGL does not use structures, and this
was a deliberate design decision. If your FFI has support for passing
arrays of raw floats and/or doubles without copying, you should be ready
to go.
(It is also time for me to (re)visit this issue. Just gotta get past
that next deadline...)
-thant
> William Lovas wrote:
> > In article <cci06f$39$1...@wolfberry.srv.cs.cmu.edu>, Brandon J. Van
> > Every wrote:
> >> Which MLs support 32-bit ints and/or 32-bit floats? To my knowledge:
> >> - SML/NJ, MLton support both
> >> - OCaml does not support either
> >
> > I would say that 32-bit ints are supported in O'Caml:
> >
> > http://caml.inria.fr/ocaml/htmlman/libref/Int32.html
>
> I stand corrected. It also seems that int32 is a boxed type, given the
> notes on memory space and performance. Probably wouldn't matter for
> straightforward computations, but it could definitely be a problem for C
> structure packing. While I'm learning things, what MLs can support unboxed
> C structures? How about unboxed arrays of such C structures? Such arrays
> are very common in 3D graphics applications.
This is definitely a problem. In SML/NJ you could hack around it
using the (NL)FFI, but in the long run this is going to be awkward.
For general ideas you should get in touch with John Reppy. Within the
SML/NJ team he is probably the one who knows most about the
interaction with graphics applications.
Matthias
> Which MLs support 32-bit ints and/or 32-bit floats? To my knowledge:
> - SML/NJ, MLton support both
> - OCaml does not support either
I think SML/NJ supports only 31-bit ints, not 32-bit ints.
This is wrong. SML/NJ currently supports 31-bit ints (default),
32-bit ints (often boxed in memory, but the compiler will try to keep
them unboxed in registers as much as it can), infinite precision ints,
31-bit words (default), 32-bit words, 8-bit words, and 64-bit reals.
Support for 64-bit ints and words as well as 32-bit reals is planned.
Matthias
Nobody uses the OpenGL function call interfaces who cares about performance.
Such people use the array interface. That was another "deliberate design
decision," created in later versions of OpenGL after the function call
interface proved to be a detriment to performance. ;-) And I can tell you,
having optimized those function calls in OpenGL device drivers, yes it
matters.
The array interface is expressed with pointers, offsets, and strides, so you
could implement either Array Of Structures (as most people do) or Structure
of Arrays (as some people do). To implement AoS you will certainly need
regularized, predictable memory footprints. I do not know if strictly
speaking they would need to be unboxed, but you'd certainly have to know
exactly where everything is.
Implementing SoA would be easier in various MLs, but bad when working with
other people's languages, code, and implementation practices. SoA is a
highly invasive programming design choice, you don't just mix and match it
with AoS code. It also exhibits poor memory coherence for long arrays. You
will always go outside your cache, unless you have a truly exotic
scatter-gather DMA architecture, or are willing to segment your arrays. In
contrast, AoS is always locally memory coherent (barring megabyte-sized
structures) and the programming interface is simple, no segmentation
required to get the performance.
That's what I was talking about. You do not pass in an array of
"structures" in the C sense. They are arrays of homogeneous floats or
doubles. And like I said, if your ML FFI handles pointers to arrays of
raw floats or doubles without copying, you can in theory now put OpenGL
to use efficiently. I think MLTon can do it, but I haven't tried yet.
-thant
> > I think SML/NJ supports only 31-bit ints, not 32-bit ints.
> This is wrong. SML/NJ currently supports 31-bit ints (default),
> 32-bit ints (often boxed in memory, but the compiler will try to keep
> them unboxed in registers as much as it can), infinite precision ints,
> 31-bit words (default), 32-bit words, 8-bit words, and 64-bit reals.
> Support for 64-bit ints and words as well as 32-bit reals is planned.
Do you mean that the type named "int" can be 31 or 32 bits long under
different circumstances, or do you mean that there are various integer types
with various sizes (and presumably various names such as int32)?
> "Matthias Blume" <fi...@my.address.elsewhere> wrote in message
> news:ccmqe0$ifb$1...@wolfberry.srv.cs.cmu.edu...
> > "Andrew Koenig" <a...@acm.org> writes:
>
> > > I think SML/NJ supports only 31-bit ints, not 32-bit ints.
>
> > This is wrong. SML/NJ currently supports 31-bit ints (default),
> > 32-bit ints (often boxed in memory, but the compiler will try to keep
> > them unboxed in registers as much as it can), infinite precision ints,
> > 31-bit words (default), 32-bit words, 8-bit words, and 64-bit reals.
> > Support for 64-bit ints and words as well as 32-bit reals is planned.
>
> Do you mean that the type named "int" can be 31 or 32 bits long under
> different circumstances,
I don't know what you mean here. The name "int" can mean arbitrary
things under different circumstances. For example, I can say things like:
type int = unit * bool
or
open IntInf
Both of these redefine "int" to something other than the default
31-bit integer type (Int31.int aka. Int.int).
> or do you mean that there are various integer types
> with various sizes (and presumably various names such as int32)?
That's what I mean. They are all named "int", though, but live in
different structures such as Int31, Int32, LargeInt, FixedInt, and
IntInf. Some of these structures are aliased to each other.
Matthias
the later
There are Int{N} structures defined in the SML Baisis
Int.int has implementation defined percision.
BTW newer versions of MLTon happens to have Int{N} and Word{N} structures
for *all* values of N between 2 and 32!
Yes you do. The OpenGL array interface is flexible enough that you could
use it to specify SoA or AoS. AoS is just a different bunch of offsets and
strides, as far as the interface is concerned. I reiterate the
disadvantages of SoA in industrial practice. For one thing, all the driver
writers are optimizing for AoS.
Are you talking about something other than glVertexPointer? The issue as
far as SML is concerned has nothing to do with stride. It has to do with
how you access *inhomogeneous* data types within a C structure, which in
the case of OpenGL you don't have to do regardless of whether you choose
a stride or not.
void VertexPointer(int size,
enum type,
sizei stride,
sizei count,
const void* pointer);
The "pointer" is always going to point at a homogeneous array of
doubles, floats, ints, or shorts.
Maybe for vertex data you're thinking you have to make an SML array of
tuples or something, and although that would be nice, it's not at all
necessary.
(Look, I don't have time right now to make my point with an actual
working example, but I hope to soon...)
-thant
Maybe I should have said, "Yes you can pass AoS style C structures through
the OpenGL array interface, and you should." You are not required to, but
as I said, driver writers and HW architects are expecting AoS. For good
reasons.
> Are you talking about something other than glVertexPointer?
> [confusing terminology about 'inhomogeneity' snipped]
You use the following functions in concert:
void glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid
*pointer);
void glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
void glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid
*pointer);
void glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const
GLvoid *pointer);
void glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
void glFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer);
void glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const
GLvoid *pointer);
void glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer);
OpenGL 1.4 added FogCoord and SecondaryColor; the rest have been available
since 1.1. You can specify just about anything you want through this
interface. Specifying AoS vs. SoA is left as an exercise to the reader.
There's nothing stopping you from interlacing your vertex, normal,
color, etc. data in a single homogeneous array in SML to improve
performance. Yes, it's not as clean code-design-wise, but my point is
that (I think) it's not a barrier to using SML for high-performance 3D
graphics anymore. (And it will only buy you something if your
application is vertex bound, which isn't always true--especially as your
vertex and fragment programs grow in complexity.)
[...]
-thant
SML may like it better, but you will not improve performance at the driver
layer. 3D drivers do not want this. They want AoS C structs and you are
bucking what industry does. Those drivers are going to sit around
translating your SoA code into AoS, so I hope you don't mind that
under-the-hood hit.
You may feel that SoA is a perfectly good choice in your own clean slate,
control everything design. If you ever want to utilize other people's
industry standard C/C++ 3D libraries, or sell to customers who write code
according to the predominant industry practices, your SoA code is going to
be a serious PITA. Possibly to the point of being a dealbreaker, depending
on the application and how smart / dumb your clients are.
But by all means if you've got some personally compelling reason to "do your
own thing" in your own code, go right ahead. There are just few compelling
reasons to do so. SoA offers either cache misses, segmented arrays, or
short arrays. Why do you want to make those tradeoffs? With AoS you don't
have to. Do you just want whatever's naively easy to do in SML? Are you
just such a high level language guy that you really don't care about
performance hits? 3D graphics is "fast enough for you" nowadays?
I don't think you're getting the point I'm trying to make.
SoA lays out memory like this:
First array:
vertex
vertex
vertex
...
Second array:
normal
normal
normal
...
Third array:
texCoord
texCoord
texCoors
...
AoS lays out memory like this:
One big array:
vertex
normal
texCoord
vertex
normal
texCoord
vertex
normal
texCoord
...
You can lay out your vertex data into a single SML homogeneous array of
reals like this and it will look *exactly* like AoS as far as the OpenGL
functions are concerned. You don't have to give up the performance
advantages AoS if you don't want to.
I'll say it again: You don't have to give up the performance advantages
of AoS if you don't want to.
-thant
Unless you are saying that all SML homogeneous array implementations lay out
SoA as AoS, what you're saying makes no sense. The performance hit comes
from how memory is actually laid out, not the API semantics.
--
Cheers, www.indiegamedesign.com
Brandon Van Every Seattle, WA
On Usenet, if you're not an open source hippie who
likes to download and play with programming toys
all day long, there's something wrong with you.
No, that's not what I'm saying. Forget structures for a moment. OpenGL
doesn't know from structures. Just fill your array with your data in
that order. The array doesn't care that the first three elements are
vertex coordinates, and the next three elements are the normal
components, and the next two are texture coordinates. What I'm
suggesting is way simpler than I think you think it is.
-thant
If that is what you've been trying to say all along, we've done the most
spectacular job of talking past each other. :-)
What you are proposing is an AoS architecture, accessed through an array
only interface. It has various flaws: (1) tacky access semantics. You'd
have to define offset constants for accessing the array elements, in essence
"faking" structures. Can you tell me some syntactic sugar in some ML that
fixes this? (2) Color types aren't necessarily 32-bit floats, they're often
expressed as a 32-bit RGBA integer. (3) Data passed to vertex shaders could
be either float or int, it's an arbitrary choice of the underlying shader
program. So, can you cast your types in C-ish fashion to whatever you want?
That's what you'd have to do if your array access semantics are "all floats"
or "all ints." Such casting strikes me as decidedly un-MLish, but I admit
to not knowing any of the languages well yet.
Anyways, in summary, you must successfully deal with heterogeneous C
structures on modern 3D HW. If you want the performance.
[...]
> What you are proposing is an AoS architecture, accessed through an array
> only interface. It has various flaws: [...]
Yes. Maybe. Let me get back to this topic in two or three weeks,
hopefully with some real SML code. Too busy right now.
> Anyways, in summary, you must successfully deal with heterogeneous C
> structures on modern 3D HW. If you want the performance.
It depends on the situation. If your application is significantly
fill-bound for example, there's no point.
-thant
If your application is file bound, and it's an interactive 3D graphics
application, then you're dealing with overwhelmingly large datasets. Ergo,
you will need your performance in order to maniplate your views of the
datasets. I really don't see any scenario where you're both interested in
interactive 3D graphics, filebound, and somehow that justifies low
interactive performance. I can see one choosing low performance in favor of
prototyping / writing code faster / less time spent on optimization. But
that really says nothing about what you should do if you actually want
performance. If you don't want performance, you can do anything you like.
[...]
I said "fill-bound" not "file-bound." As in pixel-fill-bound. Are you
just teasing me?
-thant
No, I misread what you wrote, sorry. People usually talk about being
"fill-rate limited" or about "file-bound IO," which is why I made the error.
I would be cautious about making assumptions about what your bottleneck
really is, or will be. Unless you are grossly, disgustingly fill-rate
limited, or can easily prove you will be on the back of an envelope. And,
what happens if you fix the fill-rate bottleneck? You just gonna accept
your new C structure translation bottleneck?
> > Do you mean that the type named "int" can be 31 or 32 bits long under
> > different circumstances,
>
> I don't know what you mean here. The name "int" can mean arbitrary
> things under different circumstances. For example, I can say things like:
>
> type int = unit * bool
>
> or
>
> open IntInf
I mean the type that most people think of as "int", namely the one to which
"int" is bound in the standard, top-level environment.
> > Do you mean that the type named "int" can be 31 or 32 bits long under
> > different circumstances, or do you mean that there are various integer
types
> > with various sizes (and presumably various names such as int32)?
>
> the later
The original question was whether SML supported 32-bit ints, so I guess I
should stand by my answer :-)
If the question were whether SML came with a type that could be used to
represent 32-bit integers, I would have answered differently.
In that case the answer is no. (There is no overloading on type names.)
However, many commonly used operators which can be applied to int
values are overloaded and, thus, will also work -- depending on
context -- with Int32.int, word, real, etc. The same is true for
literals. (There continues to be a syntactic difference between
integers, words, and reals. So "1" can stand for an int of any
precision, but not for a word and not for a real.)
For example, if you want to implement factorial with
arbitrary-precision integeres you can write:
fun fac 0 = 1 : IntInf.int
| fac n = n * fac (n - 1)
Notice that the only difference to the default 31-bit integer version
is the presence of the type constraint on 1.
If you want to "optimize" this by letting the argument be a normal int
(31 bit), then you write, e.g.,
fun fac 0 = 1
| fac n = IntInf.fromInt n * fac (n - 1)
Matthias
> "Daniel C. Wang" <danw...@hotmail.com> wrote in message
> news:ccqovp$69k$1...@wolfberry.srv.cs.cmu.edu...
> > Andrew Koenig wrote:
>
> > > Do you mean that the type named "int" can be 31 or 32 bits long under
> > > different circumstances, or do you mean that there are various integer
> types
> > > with various sizes (and presumably various names such as int32)?
> >
> > the later
>
> The original question was whether SML supported 32-bit ints, so I guess I
> should stand by my answer :-)
Well, this is silly nitpicking. I have not seen /any/ language where
type names are overloaded like this. Moreover, SML (the language)
does support 32-bit ints. In other words, implementations are free to
choose a 32-bit precision for the default int type.