Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 06, 2016 std.math API rework | ||||
---|---|---|---|---|
| ||||
Effective work with std.experimental.ndslice and and mir.ndslice.array requires half of std.math be an exactly aliases to LLVM intrinsics (for LDC). To enable vectorization for mir.ndslice.algorithm I created internal math module [1] in Mir. But this is weird, because third side packages like DCV [2] requires to use the module too. Also, some optimisation for std.complex and future std.exprimental.color would be very ugly without proposed change. Proposed change is very simple: Each math function listed in [1] should be a template for DMD/GDC and an alias for LDC in std.math. If some one has strong arguments against it, please let me know now. [1] https://github.com/libmir/mir/blob/master/source/mir/internal/math.d [2] https://github.com/ljubobratovicrelja/dcv Best regards, Ilya |
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Yaroshenko | On Thursday, 6 October 2016 at 16:53:54 UTC, Ilya Yaroshenko wrote:
> Effective work with std.experimental.ndslice and and mir.ndslice.array requires half of std.math be an exactly
>
EDIT: mir.ndslice.algorithm
|
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Yaroshenko | On 6 October 2016 at 18:53, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> Effective work with std.experimental.ndslice and and mir.ndslice.array requires half of std.math be an exactly aliases to LLVM intrinsics (for LDC).
>
> To enable vectorization for mir.ndslice.algorithm I created internal math module [1] in Mir. But this is weird, because third side packages like DCV [2] requires to use the module too. Also, some optimisation for std.complex and future std.exprimental.color would be very ugly without proposed change.
>
> Proposed change is very simple:
> Each math function listed in [1] should be a template for DMD/GDC and an
> alias for LDC in std.math.
>
> If some one has strong arguments against it, please let me know now.
>
> [1] https://github.com/libmir/mir/blob/master/source/mir/internal/math.d [2] https://github.com/ljubobratovicrelja/dcv
>
> Best regards,
> Ilya
If you can prove that llvm intrinsics are pure (gcc math intrinsics are not) and that llvm intrinsics pass the unittest (gcc math intrinsics aren't guaranteed to due to the vagary of libm implementations and quirky cpu support that trades correctness for efficiency).
I have a reasonable belief to say that the answer is no on both parts. Even if some llvm intrinsics lower to native instructions on x86, most other platforms will just forward it to an impure, mixed bag of long double support libm. :-)
If you need it specialized, do it yourself. Phobos seems more of a place for generalized application support, from what I gather, and how I approach it.
Iain.
|
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Iain Buclaw | On Thursday, 6 October 2016 at 20:07:19 UTC, Iain Buclaw wrote: > On 6 October 2016 at 18:53, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote: >> [...] > > If you can prove that llvm intrinsics are pure (gcc math intrinsics are not) and that llvm intrinsics pass the unittest (gcc math intrinsics aren't guaranteed to due to the vagary of libm implementations and quirky cpu support that trades correctness for efficiency). > > [...] LLVM math functions are pure :P http://llvm.org/docs/LangRef.html I can do a Phobos fork. But I hope I can fix it. |
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Yaroshenko | On 6 October 2016 at 22:31, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote: > On Thursday, 6 October 2016 at 20:07:19 UTC, Iain Buclaw wrote: >> >> On 6 October 2016 at 18:53, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote: >>> >>> [...] >> >> >> If you can prove that llvm intrinsics are pure (gcc math intrinsics are not) and that llvm intrinsics pass the unittest (gcc math intrinsics aren't guaranteed to due to the vagary of libm implementations and quirky cpu support that trades correctness for efficiency). >> >> [...] > > > LLVM math functions are pure :P http://llvm.org/docs/LangRef.html > I picked a random example. http://llvm.org/docs/LangRef.html#llvm-sin-intrinsic """ Semantics: This function returns the sine of the specified operand, returning the same values as the libm sin functions would, and handles error conditions in the same way. """ This would have me believe that they are infact not pure. ;-) But, I've never looked under the hood of LLVM, so I can only believe those who have. In any case, IMO, you should focus on getting this into core.math. That's where compiler intrinsics should go. The intrinsics of std.math are historical baggage and are probably due a deprecation - that is, in the sense that their symbols be converted into aliases. Iain. |
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Iain Buclaw | On Thursday, 6 October 2016 at 20:45:24 UTC, Iain Buclaw wrote:
> On 6 October 2016 at 22:31, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>> On Thursday, 6 October 2016 at 20:07:19 UTC, Iain Buclaw wrote:
>>>
>>> On 6 October 2016 at 18:53, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>>
>>>> [...]
>>>
>>>
>>> If you can prove that llvm intrinsics are pure (gcc math intrinsics are not) and that llvm intrinsics pass the unittest (gcc math intrinsics aren't guaranteed to due to the vagary of libm implementations and quirky cpu support that trades correctness for efficiency).
>>>
>>> [...]
>>
>>
>> LLVM math functions are pure :P http://llvm.org/docs/LangRef.html
>>
>
> I picked a random example.
>
> http://llvm.org/docs/LangRef.html#llvm-sin-intrinsic
>
> """
>
> Semantics:
>
> This function returns the sine of the specified operand, returning the same values as the libm sin functions would, and handles error conditions in the same way.
>
> """
>
> This would have me believe that they are infact not pure. ;-)
>
> But, I've never looked under the hood of LLVM, so I can only believe those who have. In any case, IMO, you should focus on getting this into core.math. That's where compiler intrinsics should go. The intrinsics of std.math are historical baggage and are probably due a deprecation - that is, in the sense that their symbols be converted into aliases.
>
> Iain.
Current code is (please look in LDC's fork):
version(LDC)
{
real cos(real x) @safe pure nothrow @nogc { return llvm_cos(x); }
///ditto
double cos(double x) @safe pure nothrow @nogc { return llvm_cos(x); }
///ditto
float cos(float x) @safe pure nothrow @nogc { return llvm_cos(x); }
}
else
{
real cos(real x) @safe pure nothrow @nogc { pragma(inline, true); return core.math.cos(x); }
//FIXME
///ditto
double cos(double x) @safe pure nothrow @nogc { return cos(cast(real)x); }
//FIXME
///ditto
float cos(float x) @safe pure nothrow @nogc { return cos(cast(real)x); }
}
So, I don't see a reason why this change break something, hehe
|
October 07, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Yaroshenko | On 6 October 2016 at 22:55, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On Thursday, 6 October 2016 at 20:45:24 UTC, Iain Buclaw wrote:
>>
>> On 6 October 2016 at 22:31, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>> On Thursday, 6 October 2016 at 20:07:19 UTC, Iain Buclaw wrote:
>>>>
>>>>
>>>> On 6 October 2016 at 18:53, Ilya Yaroshenko via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>>>
>>>>>
>>>>> [...]
>>>>
>>>>
>>>>
>>>> If you can prove that llvm intrinsics are pure (gcc math intrinsics are not) and that llvm intrinsics pass the unittest (gcc math intrinsics aren't guaranteed to due to the vagary of libm implementations and quirky cpu support that trades correctness for efficiency).
>>>>
>>>> [...]
>>>
>>>
>>>
>>> LLVM math functions are pure :P http://llvm.org/docs/LangRef.html
>>>
>>
>> I picked a random example.
>>
>> http://llvm.org/docs/LangRef.html#llvm-sin-intrinsic
>>
>> """
>>
>> Semantics:
>>
>> This function returns the sine of the specified operand, returning the
>> same values as the libm sin functions would, and handles error conditions in
>> the same way.
>>
>> """
>>
>> This would have me believe that they are infact not pure. ;-)
>>
>> But, I've never looked under the hood of LLVM, so I can only believe those who have. In any case, IMO, you should focus on getting this into core.math. That's where compiler intrinsics should go. The intrinsics of std.math are historical baggage and are probably due a deprecation - that is, in the sense that their symbols be converted into aliases.
>>
>> Iain.
>
>
> Current code is (please look in LDC's fork):
>
> version(LDC)
> {
> real cos(real x) @safe pure nothrow @nogc { return llvm_cos(x); }
> ///ditto
> double cos(double x) @safe pure nothrow @nogc { return llvm_cos(x); }
> ///ditto
> float cos(float x) @safe pure nothrow @nogc { return llvm_cos(x); }
> }
> else
> {
>
> real cos(real x) @safe pure nothrow @nogc { pragma(inline, true); return
> core.math.cos(x); }
> //FIXME
> ///ditto
> double cos(double x) @safe pure nothrow @nogc { return cos(cast(real)x); }
> //FIXME
> ///ditto
> float cos(float x) @safe pure nothrow @nogc { return cos(cast(real)x); }
>
> }
>
> So, I don't see a reason why this change break something, hehe
Well, sure, I could mark all gcc intrinsics as pure so you can use
__builtin_print() or malloc() in pure code. Doesn't mean the compiler
is honest in allowing it. ;-)
Get this in core.math, there's no place for compiler-specific code in phobos.
Iain.
|
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Yaroshenko | On Thursday, 6 October 2016 at 20:55:55 UTC, Ilya Yaroshenko wrote:
> So, I don't see a reason why this change break something, hehe
No, Iain is right. These LLVM intrinsics are most often simple forwarders to the C runtime functions; I was rather negatively surprised to find out a while ago.
|
October 06, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ilya Yaroshenko | On 10/6/16 12:53 PM, Ilya Yaroshenko wrote: > Effective work with std.experimental.ndslice and and mir.ndslice.array > requires half of std.math be an exactly aliases to LLVM intrinsics (for > LDC). Why? > To enable vectorization for mir.ndslice.algorithm I created internal > math module [1] in Mir. But this is weird, because third side packages > like DCV [2] requires to use the module too. Also, some optimisation for > std.complex and future std.exprimental.color would be very ugly without > proposed change. I'd love to understand this point better. In particular, how do you reconcile it with kinke's assertion that some of these intrinsics simply format to C routines? Our high-level view is that doing efficient work should not require one to fork the standard library. On the other hand, the traditional place for compiler-specific code is in the core runtime, not the standard library. (There is a tiny bit of stdlib code that depends on dmd to be fair.) So I'd like to be reasonably confident the right rocks are put in the right places. Have you considered (per Iain) migrating these symbols to core.math and then forward those in stdlib to them? Thanks, Andrei |
October 07, 2016 Re: std.math API rework | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Friday, 7 October 2016 at 01:53:27 UTC, Andrei Alexandrescu wrote: > On 10/6/16 12:53 PM, Ilya Yaroshenko wrote: >> Effective work with std.experimental.ndslice and and mir.ndslice.array >> requires half of std.math be an exactly aliases to LLVM intrinsics (for >> LDC). > > Why? > >> To enable vectorization for mir.ndslice.algorithm I created internal >> math module [1] in Mir. But this is weird, because third side packages >> like DCV [2] requires to use the module too. Also, some optimisation for >> std.complex and future std.exprimental.color would be very ugly without >> proposed change. > > I'd love to understand this point better. In particular, how do you reconcile it with kinke's assertion that some of these intrinsics simply format to C routines? > > Our high-level view is that doing efficient work should not require one to fork the standard library. On the other hand, the traditional place for compiler-specific code is in the core runtime, not the standard library. (There is a tiny bit of stdlib code that depends on dmd to be fair.) > > So I'd like to be reasonably confident the right rocks are put in the right places. Have you considered (per Iain) migrating these symbols to core.math and then forward those in stdlib to them? > > > Thanks, > > Andrei For example, SUM_i of sqrt(fabs(a[i])) can be vectorised using mir.ndslice.algorithm. vxorps instruction can be used for fabs. vsqrtps instruction can be used for sqrt. LDC's @fastmath allows to re-associate summation elements. Depend on data cache level this allows to speed up iteration 8 times for single precision floating point number for AVX (16 times for AVX512?). Furthermore, at least for x86, @fastmath flag does not break any math logic. It allows only to re-associate elementes (i mean exactly this example for x86). Current std.math has following problems: 1. Math funcitons are not templates -> Phobos should be linked. 1.a I strongly decided to move forward without DRuntime. A phobos as source library is partially OK, but no linking dependencies should be. BetterC mode is what required for Mir to replace OpenBLAS and Eigen. New cpuid, threads and mutexes should be provided too. New cpuid [1] is already implemented (I just need to replace module constructor with explicit initialization function). My strong opinion is that a D library for D is a wrong direction. A numeric D library should be a product for other languages too, like many C libraries does. One my client is thinking to invest to nothrow @nogc async I/O for production, so it may help to move to betterC direction too. 2.b In context of 1.a, linking multiple binaries compiled with different DRuntime/Phobos versions may cause significant problems. DRuntime is not so stable like std C lib. One may say that I am doing something wrong if I need to link libraries compiled with different DRuntimes. But this is what will happen often with D in real world if D start to replace C libraries (1.a). So, betterC without DRuntime / Phobos linking dependencies is a direction to move forward. nothrow @nogc generic Phobos code seems to be OK. 2. Math funcitons are not templates -> They are not inlined -> No vectorization + function calls in a loop body. One day this may be fixed, but (1.a, 1.b). 3. Math funcitons are not aliases for LDC -> LDC's @fastmath would not work for them. To enable @fastmath for this functions they should be annotated with @fastmath, which is not acceptable. If a function is an alias for llvm intrinsics, than @fastmath flag can be applied to a function, which calls it. [1] https://github.com/libmir/cpuid Best regards, Ilya |
Copyright © 1999-2021 by the D Language Foundation