Jump to page: 1 2
Thread overview
Re: half datatype?
Nov 18, 2012
Artur Skawina
Nov 18, 2012
Manu
Nov 18, 2012
Artur Skawina
Nov 18, 2012
Manu
Nov 18, 2012
Artur Skawina
Nov 19, 2012
Manu
Nov 19, 2012
Walter Bright
Nov 19, 2012
Manu
Nov 23, 2012
xenon325
Nov 23, 2012
Walter Bright
Nov 26, 2012
xenon325
Nov 23, 2012
Manu
Nov 26, 2012
xenon325
Nov 21, 2012
Artur Skawina
November 18, 2012
On 11/18/12 12:21, Manu wrote:
> I've often wondered about having an official 'half' type.
> It's very common in rendering/image processing, supported by most video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
> 
> ARM for instance supports 'half's in hardware, and GCC has an __fp16 type which would map nicely if D supported the type in the front end.
> 
> The alternative us to use ushort everywhere, which is awkward, because it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
> It would be nice if: cast(half)someFloat would yield the proper value, even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
> 
> It could be done in a library, but then GCC couldn't map it properly to the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
> someFloat = someHalf <- doesn't work, because a cast operator expects an explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
> 
> Thoughts?

   version (GNU) alias half = @gcc[mode(HF)] float;

But of course this won't work right now, cause that kind of type attributes
aren't supported yet. 'pragma' can't be used on types either (otherwise
something like "alias half = pragma(attribute, mode("HF")) float;" could be
made to work).

And - yes - the /proper/ way would be eg

   alias half = @core[size=2] float;
         // or '@core.size(2)' or any other syntax.

For now, a struct + alias-this-getter might be enough, for a s/w implementation.

artur
November 18, 2012
On 18 November 2012 14:51, Artur Skawina <art.08.09@gmail.com> wrote:

> On 11/18/12 12:21, Manu wrote:
> > I've often wondered about having an official 'half' type.
> > It's very common in rendering/image processing, supported by most video
> cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
> >
> > ARM for instance supports 'half's in hardware, and GCC has an __fp16
> type which would map nicely if D supported the type in the front end.
> >
> > The alternative us to use ushort everywhere, which is awkward, because
> it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
> > It would be nice if: cast(half)someFloat would yield the proper value,
> even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
> >
> > It could be done in a library, but then GCC couldn't map it properly to
> the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
> > someFloat = someHalf <- doesn't work, because a cast operator expects an
> explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
> >
> > Thoughts?
>
>    version (GNU) alias half = @gcc[mode(HF)] float;
>
> But of course this won't work right now, cause that kind of type attributes
> aren't supported yet. 'pragma' can't be used on types either (otherwise
> something like "alias half = pragma(attribute, mode("HF")) float;" could be
> made to work).
>
> And - yes - the /proper/ way would be eg
>
>    alias half = @core[size=2] float;
>          // or '@core.size(2)' or any other syntax.
>
> For now, a struct + alias-this-getter might be enough, for a s/w implementation.
>

Yes, that's what I and everyone else does, but that's not the point of the
topic...
I think it's a fundamental datatype, and it deserves the same casting/type
conversion/type safety rules as ints and floats, and it would also be
useful to map it to hardware (which GDC can easily do).


November 18, 2012
On 11/18/12 13:58, Manu wrote:
> On 18 November 2012 14:51, Artur Skawina <art.08.09@gmail.com <mailto:art.08.09@gmail.com>> wrote:
> 
>     On 11/18/12 12:21, Manu wrote:
>     > I've often wondered about having an official 'half' type.
>     > It's very common in rendering/image processing, supported by most video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
>     >
>     > ARM for instance supports 'half's in hardware, and GCC has an __fp16 type which would map nicely if D supported the type in the front end.
>     >
>     > The alternative us to use ushort everywhere, which is awkward, because it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
>     > It would be nice if: cast(half)someFloat would yield the proper value, even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
>     >
>     > It could be done in a library, but then GCC couldn't map it properly to the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
>     > someFloat = someHalf <- doesn't work, because a cast operator expects an explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
>     >
>     > Thoughts?
> 
>        version (GNU) alias half = @gcc[mode(HF)] float;
> 
>     But of course this won't work right now, cause that kind of type attributes
>     aren't supported yet. 'pragma' can't be used on types either (otherwise
>     something like "alias half = pragma(attribute, mode("HF")) float;" could be
>     made to work).
> 
>     And - yes - the /proper/ way would be eg
> 
>        alias half = @core[size=2] float;
>              // or '@core.size(2)' or any other syntax.
> 
>     For now, a struct + alias-this-getter might be enough, for a s/w implementation.
> 
> 
> Yes, that's what I and everyone else does, but that's not the point of the topic...
> I think it's a fundamental datatype, and it deserves the same casting/type conversion/type safety rules as ints and floats, and it would also be useful to map it to hardware (which GDC can easily do).

All of the 'half' definitions above would give you a 'fundamental' datatype -- -- there is no reason to make it a /language/-defined type. The work required to implement things like implicit conversions can be done more generically; right now the problem is the lack of a way to define such types.

   alias fp24 = @core[exp=7, mant=16] float; // It's only a matter of time until
                                             // someone asks for it&co...

Also, *every* user- (or in this case more likely lib-) defined data type deserves the same control over casting and conversions as built-in types. No, D doesn't have that and yes - it is a problem.

I actually think these types /should/ be done as structs, but
a) it isn't currently possible (also for reasons other than the above mentioned ones)
and
b) such aliases would /still/ be useful for mapping to "magic" compiler-supported
   h/w types.

artur
November 18, 2012
On 18 November 2012 16:33, Artur Skawina <art.08.09@gmail.com> wrote:

> On 11/18/12 13:58, Manu wrote:
> > On 18 November 2012 14:51, Artur Skawina <art.08.09@gmail.com <mailto:
> art.08.09@gmail.com>> wrote:
> >
> >     On 11/18/12 12:21, Manu wrote:
> >     > I've often wondered about having an official 'half' type.
> >     > It's very common in rendering/image processing, supported by most
> video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
> >     >
> >     > ARM for instance supports 'half's in hardware, and GCC has an
> __fp16 type which would map nicely if D supported the type in the front end.
> >     >
> >     > The alternative us to use ushort everywhere, which is awkward,
> because it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
> >     > It would be nice if: cast(half)someFloat would yield the proper
> value, even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
> >     >
> >     > It could be done in a library, but then GCC couldn't map it
> properly to the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
> >     > someFloat = someHalf <- doesn't work, because a cast operator
> expects an explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
> >     >
> >     > Thoughts?
> >
> >        version (GNU) alias half = @gcc[mode(HF)] float;
> >
> >     But of course this won't work right now, cause that kind of type
> attributes
> >     aren't supported yet. 'pragma' can't be used on types either
> (otherwise
> >     something like "alias half = pragma(attribute, mode("HF")) float;"
> could be
> >     made to work).
> >
> >     And - yes - the /proper/ way would be eg
> >
> >        alias half = @core[size=2] float;
> >              // or '@core.size(2)' or any other syntax.
> >
> >     For now, a struct + alias-this-getter might be enough, for a s/w
> implementation.
> >
> >
> > Yes, that's what I and everyone else does, but that's not the point of
> the topic...
> > I think it's a fundamental datatype, and it deserves the same
> casting/type conversion/type safety rules as ints and floats, and it would also be useful to map it to hardware (which GDC can easily do).
>
> All of the 'half' definitions above would give you a 'fundamental'
> datatype --
> -- there is no reason to make it a /language/-defined type. The work
> required
> to implement things like implicit conversions can be done more generically;
> right now the problem is the lack of a way to define such types.
>
>    alias fp24 = @core[exp=7, mant=16] float; // It's only a matter of time
> until
>                                              // someone asks for it&co...
>
> Also, *every* user- (or in this case more likely lib-) defined data type
> deserves
> the same control over casting and conversions as built-in types. No, D
> doesn't
> have that and yes - it is a problem.
>
> I actually think these types /should/ be done as structs, but
> a) it isn't currently possible (also for reasons other than the above
> mentioned ones)
> and
> b) such aliases would /still/ be useful for mapping to "magic"
> compiler-supported
>    h/w types.
>

I don't necessarily disagree, but you can take that logic and run with it
as far as you like.
long can easily be implemented as a struct with 2 ints, why bother with a
builtin type for that? Any answer or counter argument you can possibly give
me applies equally to half.

D needs quite a few tweaks to be able to create a user defined type that is capable of performing like a builtin type. The main limiters are custom implicit conversion, and literal syntax definition, but it also seems really nasty to hook a library, suppress it, and alias it to a hardware type in the case of GDC for instance. Who's to say the GDC type behaves in exactly the same way as those defined by the D front end?

Point is, this type should behave in EXACTLY the same way as expected when
dealing with builtin float types, it's not just some user type, it's an
established, industry-recognised precision of float. In reality it's
probably significantly easier to define it wherever the others are defined
rather than in a new library all on its own.
I'd also argue that 'half' is far more valuable to modern computing than
'real'.

Anyway, the point is, we all already use libraries for half, offering
library solutions misses the point of the topic.
The question I raised is: SHOULD half be a builtin type?


November 18, 2012
On 11/18/12 16:32, Manu wrote:
> On 18 November 2012 16:33, Artur Skawina <art.08.09@gmail.com <mailto:art.08.09@gmail.com>> wrote:
> 
>     On 11/18/12 13:58, Manu wrote:
>     > On 18 November 2012 14:51, Artur Skawina <art.08.09@gmail.com <mailto:art.08.09@gmail.com> <mailto:art.08.09@gmail.com <mailto:art.08.09@gmail.com>>> wrote:
>     >
>     >     On 11/18/12 12:21, Manu wrote:
>     >     > I've often wondered about having an official 'half' type.
>     >     > It's very common in rendering/image processing, supported by most video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
>     >     >
>     >     > ARM for instance supports 'half's in hardware, and GCC has an __fp16 type which would map nicely if D supported the type in the front end.
>     >     >
>     >     > The alternative us to use ushort everywhere, which is awkward, because it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
>     >     > It would be nice if: cast(half)someFloat would yield the proper value, even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
>     >     >
>     >     > It could be done in a library, but then GCC couldn't map it properly to the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
>     >     > someFloat = someHalf <- doesn't work, because a cast operator expects an explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
>     >     >
>     >     > Thoughts?
>     >
>     >        version (GNU) alias half = @gcc[mode(HF)] float;
>     >
>     >     But of course this won't work right now, cause that kind of type attributes
>     >     aren't supported yet. 'pragma' can't be used on types either (otherwise
>     >     something like "alias half = pragma(attribute, mode("HF")) float;" could be
>     >     made to work).
>     >
>     >     And - yes - the /proper/ way would be eg
>     >
>     >        alias half = @core[size=2] float;
>     >              // or '@core.size(2)' or any other syntax.
>     >
>     >     For now, a struct + alias-this-getter might be enough, for a s/w implementation.
>     >
>     >
>     > Yes, that's what I and everyone else does, but that's not the point of the topic...
>     > I think it's a fundamental datatype, and it deserves the same casting/type conversion/type safety rules as ints and floats, and it would also be useful to map it to hardware (which GDC can easily do).
> 
>     All of the 'half' definitions above would give you a 'fundamental' datatype --
>     -- there is no reason to make it a /language/-defined type. The work required
>     to implement things like implicit conversions can be done more generically;
>     right now the problem is the lack of a way to define such types.
> 
>        alias fp24 = @core[exp=7, mant=16] float; // It's only a matter of time until
>                                                  // someone asks for it&co...
> 
>     Also, *every* user- (or in this case more likely lib-) defined data type deserves
>     the same control over casting and conversions as built-in types. No, D doesn't
>     have that and yes - it is a problem.
> 
>     I actually think these types /should/ be done as structs, but
>     a) it isn't currently possible (also for reasons other than the above mentioned ones)
>     and
>     b) such aliases would /still/ be useful for mapping to "magic" compiler-supported
>        h/w types.
> 
> 
> I don't necessarily disagree, but you can take that logic and run with it as far as you like.
> long can easily be implemented as a struct with 2 ints, why bother with a builtin type for that? Any answer or counter argument you can possibly give me applies equally to half.

   alias long = @core[size(int.sizeof*2)] int;

I'm saying that there's no point in defining '__fp16' when '@core[size(2)] float'
will also do the job. Just as "string" is not a built-in type in D.
Now, this can't be done today, so until it /is/ possible, the struct solution
is an option. No, it isn't perfect. But is it unusable? (honest question)
Would exposing the raw __fp16 type in GDC really be a better long-term solution?

[Of course that 'long' D definition is not a good one, but that's another topic]

> D needs quite a few tweaks to be able to create a user defined type that is capable of performing like a builtin type. The main limiters are custom implicit conversion, and literal syntax definition,

I know, and I'm not sure I'd use the words 'a few tweaks". :)

> but it also seems really nasty to hook a library, suppress it, and alias it to a hardware type in the case of GDC for instance. Who's to say the GDC type behaves in exactly the same way as those defined by the D front end?

The types MUST be compatible - this is also true for any "built-in" type.
Any operation that isn't portable, compiler- or h/w-wise, must be either
disallowed, emulated or specced as undefined behavior. Which is actually
part of the reason why I'd like it wrapped in a struct - that way the compiler
doesn't have to handle all the special cases and the *user* can choose between
"raw" (hw-supported) versions and more generic ones that may fallback to s/w
on platforms that require that.

> Point is, this type should behave in EXACTLY the same way as expected when dealing with builtin float types, it's not just some user type, it's an established, industry-recognised precision of float. In reality it's probably significantly easier to define it wherever the others are defined rather than in a new library all on its own.
> I'd also argue that 'half' is far more valuable to modern computing than 'real'.
> 
> Anyway, the point is, we all already use libraries for half, offering library solutions misses the point of the topic. The question I raised is: SHOULD half be a builtin type?

Well, no - it shouldn't. For a simple reason - it's not universally available. And the people using it won't usually be ok with pure s/w emulation. But, yes - it should be accessible on platforms that do support it.

artur
November 19, 2012
On 18 November 2012 20:57, Artur Skawina <art.08.09@gmail.com> wrote:

> On 11/18/12 16:32, Manu wrote:
> > On 18 November 2012 16:33, Artur Skawina <art.08.09@gmail.com <mailto:
> art.08.09@gmail.com>> wrote:
> >
> >     On 11/18/12 13:58, Manu wrote:
> >     > On 18 November 2012 14:51, Artur Skawina <art.08.09@gmail.com<mailto:
> art.08.09@gmail.com> <mailto:art.08.09@gmail.com <mailto: art.08.09@gmail.com>>> wrote:
> >     >
> >     >     On 11/18/12 12:21, Manu wrote:
> >     >     > I've often wondered about having an official 'half' type.
> >     >     > It's very common in rendering/image processing, supported by
> most video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
> >     >     >
> >     >     > ARM for instance supports 'half's in hardware, and GCC has
> an __fp16 type which would map nicely if D supported the type in the front end.
> >     >     >
> >     >     > The alternative us to use ushort everywhere, which is
> awkward, because it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
> >     >     > It would be nice if: cast(half)someFloat would yield the
> proper value, even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
> >     >     >
> >     >     > It could be done in a library, but then GCC couldn't map it
> properly to the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
> >     >     > someFloat = someHalf <- doesn't work, because a cast
> operator expects an explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
> >     >     >
> >     >     > Thoughts?
> >     >
> >     >        version (GNU) alias half = @gcc[mode(HF)] float;
> >     >
> >     >     But of course this won't work right now, cause that kind of
> type attributes
> >     >     aren't supported yet. 'pragma' can't be used on types either
> (otherwise
> >     >     something like "alias half = pragma(attribute, mode("HF"))
> float;" could be
> >     >     made to work).
> >     >
> >     >     And - yes - the /proper/ way would be eg
> >     >
> >     >        alias half = @core[size=2] float;
> >     >              // or '@core.size(2)' or any other syntax.
> >     >
> >     >     For now, a struct + alias-this-getter might be enough, for a
> s/w implementation.
> >     >
> >     >
> >     > Yes, that's what I and everyone else does, but that's not the
> point of the topic...
> >     > I think it's a fundamental datatype, and it deserves the same
> casting/type conversion/type safety rules as ints and floats, and it would also be useful to map it to hardware (which GDC can easily do).
> >
> >     All of the 'half' definitions above would give you a 'fundamental'
> datatype --
> >     -- there is no reason to make it a /language/-defined type. The work
> required
> >     to implement things like implicit conversions can be done more
> generically;
> >     right now the problem is the lack of a way to define such types.
> >
> >        alias fp24 = @core[exp=7, mant=16] float; // It's only a matter
> of time until
> >                                                  // someone asks for
> it&co...
> >
> >     Also, *every* user- (or in this case more likely lib-) defined data
> type deserves
> >     the same control over casting and conversions as built-in types. No,
> D doesn't
> >     have that and yes - it is a problem.
> >
> >     I actually think these types /should/ be done as structs, but
> >     a) it isn't currently possible (also for reasons other than the
> above mentioned ones)
> >     and
> >     b) such aliases would /still/ be useful for mapping to "magic"
> compiler-supported
> >        h/w types.
> >
> >
> > I don't necessarily disagree, but you can take that logic and run with
> it as far as you like.
> > long can easily be implemented as a struct with 2 ints, why bother with
> a builtin type for that? Any answer or counter argument you can possibly give me applies equally to half.
>
>    alias long = @core[size(int.sizeof*2)] int;
>
> I'm saying that there's no point in defining '__fp16' when '@core[size(2)]
> float'
> will also do the job. Just as "string" is not a built-in type in D.
> Now, this can't be done today, so until it /is/ possible, the struct
> solution
> is an option. No, it isn't perfect. But is it unusable? (honest question)
>

I've already agreed that existing solutions (via structs) are usable, but
that's not the point.
They feel artificial. They're just not orthogonal with existing primitive
types, this causes template problems.

Would exposing the raw __fp16 type in GDC really be a better long-term
> solution?
>

No, exposing a GDC type is not acceptable. I'll only use it if it's defined
by the front end, for portability.
Mapping GDC types to a type defined by the front end is another question
though, since the front end will define the rules in that case.

[Of course that 'long' D definition is not a good one, but that's another
> topic]
>
> > D needs quite a few tweaks to be able to create a user defined type that
> is capable of performing like a builtin type. The main limiters are custom implicit conversion, and literal syntax definition,
>
> I know, and I'm not sure I'd use the words 'a few tweaks". :)
>
> > but it also seems really nasty to hook a library, suppress it, and alias
> it to a hardware type in the case of GDC for instance. Who's to say the GDC type behaves in exactly the same way as those defined by the D front end?
>
> The types MUST be compatible - this is also true for any "built-in" type.
> Any operation that isn't portable, compiler- or h/w-wise, must be either
> disallowed, emulated or specced as undefined behavior. Which is actually
> part of the reason why I'd like it wrapped in a struct - that way the
> compiler
> doesn't have to handle all the special cases and the *user* can choose
> between
> "raw" (hw-supported) versions and more generic ones that may fallback to
> s/w
> on platforms that require that.
>

How would the user 'choose' a hw-supported version under your vision? What would such code look like?

> Point is, this type should behave in EXACTLY the same way as expected when dealing with builtin float types, it's not just some user type, it's an established, industry-recognised precision of float. In reality it's probably significantly easier to define it wherever the others are defined rather than in a new library all on its own.
> > I'd also argue that 'half' is far more valuable to modern computing than
> 'real'.
> >
> > Anyway, the point is, we all already use libraries for half, offering
> library solutions misses the point of the topic.
> > The question I raised is: SHOULD half be a builtin type?
>
> Well, no - it shouldn't. For a simple reason - it's not universally available.
>

Neither is real, or long. Should they be removed? Reverted to libraries? (serious question. though obviously the language isn't capable of producing a seamless library implementation of a primitive type atm)

And the people using it won't usually be ok with pure s/w emulation.


Actually, they probably will. People using it will need to use it regardless of how it's implemented. Hardware support it great when available, but realistically, it's used when processing data for execution on another processor that does support it in hardware (typically a GPU). Use of fp16 is probably not optional; it doubles your bandwidth wherever the loss of precision is acceptable.

But, yes - it should be accessible on platforms that do support it.


November 19, 2012
On 11/18/2012 4:23 PM, Manu wrote:
> Actually, they probably will. People using it will need to use it regardless of
> how it's implemented. Hardware support it great when available, but
> realistically, it's used when processing data for execution on another processor
> that does support it in hardware (typically a GPU). Use of fp16 is probably not
> optional; it doubles your bandwidth wherever the loss of precision is acceptable.

Doing implicit conversions on them implies doing them on the x86 CPU, which has no hardware support for the type. All operations would require software emulation.

If it is a storage-only format, then what role do implicit conversions play?
November 19, 2012
On 19 November 2012 06:06, Walter Bright <newshound2@digitalmars.com> wrote:

> On 11/18/2012 4:23 PM, Manu wrote:
>
>> Actually, they probably will. People using it will need to use it
>> regardless of
>> how it's implemented. Hardware support it great when available, but
>> realistically, it's used when processing data for execution on another
>> processor
>> that does support it in hardware (typically a GPU). Use of fp16 is
>> probably not
>> optional; it doubles your bandwidth wherever the loss of precision is
>> acceptable.
>>
>
> Doing implicit conversions on them implies doing them on the x86 CPU, which has no hardware support for the type. All operations would require software emulation.
>

It would just make the experience seamless, and also implement the expected casting/data-loss rules. It's the type safety/casting rules that I find most valuable, and the ability to use them in templates without specialising the half path.

I guess it would be nicer/simpler to perform actual work as floats and then re-pack it on write back, rather than emulating all the operations in half space. This wouldn't strictly retain half precision though, it would be slightly higher precision since the intermediates were full precision (which is surely preferable?).

If it is a storage-only format, then what role do implicit conversions play?
>

It saves pack/unpack calls whenever interacting with them in structs or
streams, which helps generic code. And also encourages use of the type in
structs, as it is not an 'inconvenience' as such. Where I'm from,
memory/bandwidth is often far more scarce than processing time.
x86 can do half conversion fairly efficiently (about 5 opcodes, possibly
one of the reasons it hasn't found it's way into SSE yet). But it's no
surprise that platforms like ARM implemented the conversion operations in
hardware, there's no time to waste on mobile devices.

I've also seen a few threads on this forum before about people targeting GPU backends to do GPGPU processing with D. Has that ever actually been used? Found useful in practise?


November 21, 2012
On 11/19/12 01:23, Manu wrote:
> On 18 November 2012 20:57, Artur Skawina <art.08.09@gmail.com <mailto:art.08.09@gmail.com>> wrote:
> 
>     On 11/18/12 16:32, Manu wrote:
>     > On 18 November 2012 16:33, Artur Skawina <art.08.09@gmail.com <mailto:art.08.09@gmail.com> <mailto:art.08.09@gmail.com <mailto:art.08.09@gmail.com>>> wrote:
>     >
>     >     On 11/18/12 13:58, Manu wrote:
>     >     > On 18 November 2012 14:51, Artur Skawina <art.08.09@gmail.com <mailto:art.08.09@gmail.com> <mailto:art.08.09@gmail.com <mailto:art.08.09@gmail.com>> <mailto:art.08.09@gmail.com <mailto:art.08.09@gmail.com> <mailto:art.08.09@gmail.com <mailto:art.08.09@gmail.com>>>> wrote:
>     >     >
>     >     >     On 11/18/12 12:21, Manu wrote:
>     >     >     > I've often wondered about having an official 'half' type.
>     >     >     > It's very common in rendering/image processing, supported by most video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
>     >     >     >
>     >     >     > ARM for instance supports 'half's in hardware, and GCC has an __fp16 type which would map nicely if D supported the type in the front end.
>     >     >     >
>     >     >     > The alternative us to use ushort everywhere, which is awkward, because it is neither unsigned, nor is it an integer, and it's not typesafe (allows direct assignment to ints and stuff)...
>     >     >     > It would be nice if: cast(half)someFloat would yield the proper value, even if it is performed in software in most architectures, it could be mapped to hardware for those that do it.
>     >     >     >
>     >     >     > It could be done in a library, but then GCC couldn't map it properly to the hardware type, and since D has no way to describe implicit casts (that I know of?) it becomes awkward to use.
>     >     >     > someFloat = someHalf <- doesn't work, because a cast operator expects an explicit cast, even though this is a lossless conversion and should be exactly the same as someDouble = someFloat.
>     >     >     >
>     >     >     > Thoughts?
>     >     >
>     >     >        version (GNU) alias half = @gcc[mode(HF)] float;
>     >     >
>     >     >     But of course this won't work right now, cause that kind of type attributes
>     >     >     aren't supported yet. 'pragma' can't be used on types either (otherwise
>     >     >     something like "alias half = pragma(attribute, mode("HF")) float;" could be
>     >     >     made to work).
>     >     >
>     >     >     And - yes - the /proper/ way would be eg
>     >     >
>     >     >        alias half = @core[size=2] float;
>     >     >              // or '@core.size(2)' or any other syntax.
>     >     >
>     >     >     For now, a struct + alias-this-getter might be enough, for a s/w implementation.
>     >     >
>     >     >
>     >     > Yes, that's what I and everyone else does, but that's not the point of the topic...
>     >     > I think it's a fundamental datatype, and it deserves the same casting/type conversion/type safety rules as ints and floats, and it would also be useful to map it to hardware (which GDC can easily do).
>     >
>     >     All of the 'half' definitions above would give you a 'fundamental' datatype --
>     >     -- there is no reason to make it a /language/-defined type. The work required
>     >     to implement things like implicit conversions can be done more generically;
>     >     right now the problem is the lack of a way to define such types.
>     >
>     >        alias fp24 = @core[exp=7, mant=16] float; // It's only a matter of time until
>     >                                                  // someone asks for it&co...
>     >
>     >     Also, *every* user- (or in this case more likely lib-) defined data type deserves
>     >     the same control over casting and conversions as built-in types. No, D doesn't
>     >     have that and yes - it is a problem.
>     >
>     >     I actually think these types /should/ be done as structs, but
>     >     a) it isn't currently possible (also for reasons other than the above mentioned ones)
>     >     and
>     >     b) such aliases would /still/ be useful for mapping to "magic" compiler-supported
>     >        h/w types.
>     >
>     >
>     > I don't necessarily disagree, but you can take that logic and run with it as far as you like.
>     > long can easily be implemented as a struct with 2 ints, why bother with a builtin type for that? Any answer or counter argument you can possibly give me applies equally to half.
> 
>        alias long = @core[size(int.sizeof*2)] int;
> 
>     I'm saying that there's no point in defining '__fp16' when '@core[size(2)] float'
>     will also do the job. Just as "string" is not a built-in type in D.
>     Now, this can't be done today, so until it /is/ possible, the struct solution
>     is an option. No, it isn't perfect. But is it unusable? (honest question)
> 
> 
> I've already agreed that existing solutions (via structs) are usable, but that's not the point.
> They feel artificial. They're just not orthogonal with existing primitive types, this causes template problems.
> 
>     Would exposing the raw __fp16 type in GDC really be a better long-term solution?
> 
> 
> No, exposing a GDC type is not acceptable. I'll only use it if it's defined by the front end, for portability.
> Mapping GDC types to a type defined by the front end is another question though, since the front end will define the rules in that case.
> 
>     [Of course that 'long' D definition is not a good one, but that's another topic]
> 
>     > D needs quite a few tweaks to be able to create a user defined type that is capable of performing like a builtin type. The main limiters are custom implicit conversion, and literal syntax definition,
> 
>     I know, and I'm not sure I'd use the words 'a few tweaks". :)
> 
>     > but it also seems really nasty to hook a library, suppress it, and alias it to a hardware type in the case of GDC for instance. Who's to say the GDC type behaves in exactly the same way as those defined by the D front end?
> 
>     The types MUST be compatible - this is also true for any "built-in" type.
>     Any operation that isn't portable, compiler- or h/w-wise, must be either
>     disallowed, emulated or specced as undefined behavior. Which is actually
>     part of the reason why I'd like it wrapped in a struct - that way the compiler
>     doesn't have to handle all the special cases and the *user* can choose between
>     "raw" (hw-supported) versions and more generic ones that may fallback to s/w
>     on platforms that require that.
> 
> 
> How would the user 'choose' a hw-supported version under your vision? What would such code look like?

By choosing one of several available types (structs/aliases/template args). The alternative would be having one or more of the types "built-in" - considering that these hardwired types would be either unportable or offer extremely limited functionality - not a good idea.

>     > Point is, this type should behave in EXACTLY the same way as expected when dealing with builtin float types, it's not just some user type, it's an established, industry-recognised precision of float. In reality it's probably significantly easier to define it wherever the others are defined rather than in a new library all on its own.
>     > I'd also argue that 'half' is far more valuable to modern computing than 'real'.
>     >
>     > Anyway, the point is, we all already use libraries for half, offering library solutions misses the point of the topic.
>     > The question I raised is: SHOULD half be a builtin type?
> 
>     Well, no - it shouldn't. For a simple reason - it's not universally available.
> 
> 
> Neither is real, or long. Should they be removed? Reverted to libraries? (serious question. though obviously the language isn't capable of producing a seamless library implementation of a primitive type atm)

Yes, I don't think 'real' necessarily deserves a keyword (practically - it's too late to remove it now, there would no real gain). Of course it needs to be available (at least where hw supported), but that could be done using  custom floats, just like 'half'. 'long' is relatively widely available, either directly or via mostly trivial software emulation (most platforms with a CF).

>     And the people using it won't usually be ok with pure s/w emulation.
> 
> 
> Actually, they probably will. People using it will need to use it regardless of how it's implemented. Hardware support it great when available, but realistically, it's used when processing data for execution on another processor that does support it in hardware (typically a GPU). Use of fp16 is probably not optional; it doubles your bandwidth wherever the loss of precision is acceptable.

But if it's just for storage and I/O then I don't see why a struct wouldn't be enough. Using 'float' for calculations is going to be faster than emulating 'half'. Introducing all the extra complexity for something which will have almost no use? IIUC you'd want a 'half op half" expression to return a 'half', which implicitly converts to a 'float'? If the h/w doesn't support the half ops directly, this wouldn't really be much different from 'struct half'. If some platform does support 'half' you still need a fallback for the rest ("People using it will need to use it regardless of how it's implemented").

artur
November 23, 2012
On Monday, 19 November 2012 at 15:48:23 UTC, Manu wrote:
> This wouldn't strictly retain half precision though, it would be
> slightly higher precision since the intermediates were full precision
> (which is surely preferable?).

I would think it's actually not preferable.
Imagine you developed and tuned all the code on x86 and everything is fine. Then run it on ARM and suddenly all computations are inaccurate.


« First   ‹ Prev
1 2