Re: complex arithmetic in D: multiple questions

2018-03-09 Thread J-S Caux via Digitalmars-d-learn

On Friday, 9 March 2018 at 13:56:33 UTC, Nicholas Wilson wrote:
- I would expect the D `Complex!double` case to work faster 
than the `real` one. Why is it the other way around? [I can 
accept (and use) D with Complex!real running 1/3 the speed of 
C++ (but with increased accuracy), but I'd also love to be 
able to run D with `Complex!double` at C++ speeds, since the 
tradeoff might be worth it for some calculations]


because the double version is doing the exact same work as the 
real
except that it is also converting between real and double for 
atan2 (from arg). 
https://github.com/dlang/phobos/blob/master/std/math.d#L1352


I'm really not sure why phobos does that, it should't.


Is this a case for a bug report? Seems pretty bizarre to do that, 
like an oversight/neglect.


- what is the best way to correct the unfortunate (to be 
polite) omission of many standard mathematical functions from 
std.complex? [if I may be frank, this is a real pain for us 
scientists] There exists 
https://gist.github.com/Biotronic/17af645c2c9b7913de1f04980cd22b37 but can this be integrated (after improvements) in the language, or should I (re)build my own?


It will be much faster to build your own that just forward to 
the C functions (or LLVM intrinsics) see 
https://github.com/libmir/mir-algorithm/blob/master/source/mir/math/common.d#L126 for a starting point (we'd greatly appreciate pull requests for anything missing).
Even if the decision to make std.math behave at the appropriate 
precision is accepted, it will still take an entire release 
cycle (unless you use dmd master), and I'm not so sure it will.




OK thanks. I looked at libmir, and saw many good things there. I 
was wondering: is it still actively developed/maintained? How 
will it fit with the "core" D in the future? [I don't want to 
build dependencies to libraries which aren't there to stay in the 
long run, I want code which can survive for decades]. It would 
seem to me that some of the things included in there should be 
part of D core/std anyway.


Going further, I'm really wondering what the plan is as far as 
Complex is concerned. Right now it just feels neglected 
(half-done/aborted transition from creal etc to Complex, lots of 
missing basic functions etc), and is one major blocking point as 
far as adoption (among scientists) is concerned. Julia is really 
taking off with many of my colleagues, mostly because due respect 
was given to maths. I'd certainly choose Julia if it wasn't for 
the fact that I can't get my exploratory/testing codes to run 
faster than about 1/10th of my C++ stuff. It seems D could have 
such an appeal in the realm of science, but these little things 
are really blocking adoption (including for myself).



[related questions:


Did you press send too soon?


No, the related questions were linked in my previous post (just 
copied & pasted it further above, but didn't delete these last 
couple of words properly).


Thanks a lot Nicholas!



complex arithmetic in D: multiple questions

2018-03-09 Thread J-S Caux via Digitalmars-d-learn

Please bear with me, this is a long question!
To explain, I'm a scientist considering switching from C++ to D, 
but before I do, I need to ensure that I can:
- achieve execution speeds comparable to C++ (for the same 
accuracy; I can accept a slight slowdown, call it 30%, to get a 
few more digits (which I typically don't need))
- easily perform all standard mathematical operations on complex 
numbers
- (many other things not relevant here: memory use, 
parallelization, etc).


In the two files linked below, I compare execution speed/accuracy 
between D and C++ when using log on complex variables:


https://www.dropbox.com/s/hfw7nkwg25mk37u/test_cx.d?dl=0
https://www.dropbox.com/s/hfw7nkwg25mk37u/test_cx.d?dl=0

The idea is simple: let a complex variable be uniformly 
distributed around the unit circle. Summing the logs should give 
zero.


In the D code, I've defined an "own" version of the log, log_cx, 
since std.complex (tragically!) does not provide this function 
(and many others, see recent threads 
https://forum.dlang.org/post/dewzhtnpqkaqkzxwp...@forum.dlang.org 
and 
https://forum.dlang.org/thread/lsnuevdefktulxlto...@forum.dlang.org, and issue https://issues.dlang.org/show_bug.cgi?id=18571).


First, speed/accuracy (times for 1M points in all cases):
D:
dmd, no flags:
Complex!real: re, im (should be 0): 
-9.24759400999786151942e-15	6.26324079407839123978e-14

time for 100 pts: 190 ms, 508 μs, and 9 hnsecs
Complex!double: re, im (should be 0): 
-1.96986871259241524967e-12	5.46260919029144254022e-09

time for 100 pts: 455 ms, 888 μs, and 7 hnsecs

dmd -release -inline -O:
Complex!real: re, im (should be 0): 
-9.24759400999786151942e-15	6.26324079407839123978e-14

time for 100 pts: 175 ms, 352 μs, and 3 hnsecs
Complex!double: re, im (should be 0): 
-4.23880765557105362133e-14	5.46260919029144254022e-09

time for 100 pts: 402 ms, 965 μs, and 7 hnsecs

ldc2, no flags:
Complex!real: re, im (should be 0): 
-9.24759400999786151942e-15	6.26324079407839123978e-14

time for 100 pts: 184 ms, 353 μs, and 9 hnsecs
Complex!double: re, im (should be 0): 
-1.96986871259241524967e-12	5.46260919029144254022e-09

time for 100 pts: 436 ms, 526 μs, and 8 hnsecs

ldc2 -release -O:
Complex!real: re, im (should be 0): 
-9.24759400999786151942e-15	6.26324079407839123978e-14

time for 100 pts: 108 ms and 966 μs
Complex!double: re, im (should be 0): 
-1.96986871259241524967e-12	5.46260919029144254022e-09

time for 100 pts: 330 ms, 421 μs, and 8 hnsecs

As expected accuracy with Complex!real is about 4 digits better, 
and the best combo is ldc2 with flags.


Now C++:
GCC 7.1.0, -O3:
complex: re, im (should be 0): 
(8.788326118779445e-13,1.433519814600731e-11)

time for 100 pts: 0.042751 seconds.

Apple LLVM version 9.0.0 (clang-900.0.39.2), -O3:
complex: re, im (should be 0): 
(-3.0160318686967e-12,1.433519814600731e-11)

time for 100 pts: 0.038715 seconds.

So simple C++ is thrice as fast as the best-achieved D I managed.

Now for my questions:
- I would expect the D `Complex!double` case to work faster than 
the `real` one. Why is it the other way around? [I can accept 
(and use) D with Complex!real running 1/3 the speed of C++ (but 
with increased accuracy), but I'd also love to be able to run D 
with `Complex!double` at C++ speeds, since the tradeoff might be 
worth it for some calculations]
- what is the best way to correct the unfortunate (to be polite) 
omission of many standard mathematical functions from 
std.complex? [if I may be frank, this is a real pain for us 
scientists] There exists 
https://gist.github.com/Biotronic/17af645c2c9b7913de1f04980cd22b37 but can this be integrated (after improvements) in the language, or should I (re)build my own?
- for my education, why was the decision made to go from the 
built-in types `creal` etc to the `Complex` type?


[related questions:


Re: log for complex

2018-03-07 Thread J-S Caux via Digitalmars-d-learn

On Wednesday, 7 March 2018 at 10:28:23 UTC, Simen Kjærås wrote:

On Wednesday, 7 March 2018 at 10:10:49 UTC, J-S Caux wrote:

On Wednesday, 7 March 2018 at 08:04:36 UTC, Simen Kjærås wrote:

auto log(T)(Complex!T x) {
import std.math : log;
return Complex!T(log(abs(x)), arg(x));
}


Yes indeed I can do this, but isn't this inefficient as 
compared to what it should be? The internals of arg are 
presumable already doing part of/all the necessary work.


arg is just atan2 in disguise, and doesn't do any logarithms. I 
mean, in a way it does, but it's really just a fpatan 
instruction. I don't expect there to be many optimization 
opportunities here.


--
  Simen


OK thanks Simen. Should your suggestion for repairing this 
omission be filed as a bugreport? I can of course implement it 
locally for myself, but the language should really provide this 
function directly.


Re: log for complex

2018-03-07 Thread J-S Caux via Digitalmars-d-learn

On Wednesday, 7 March 2018 at 08:04:36 UTC, Simen Kjærås wrote:

On Wednesday, 7 March 2018 at 07:42:37 UTC, J-S Caux wrote:

Simple question: how do I get the log of a complex number?

If I try the simple
logtest = log(complex(1.0, 2.0))

I get the compiler error

Error: function core.stdc.math.log(double x) is not callable 
using argument types (Complex!double)


Some basic functions are described in 
https://dlang.org/phobos/std_complex.html, but not the log...


That seems like an oversight. For now, this should work:

auto log(T)(Complex!T x) {
import std.math : log;
return Complex!T(log (abs(x)), arg(x));
}

--
  Simen


Yes indeed I can do this, but isn't this inefficient as compared 
to what it should be? The internals of arg are presumable already 
doing part of/all the necessary work.




log for complex

2018-03-06 Thread J-S Caux via Digitalmars-d-learn

Simple question: how do I get the log of a complex number?

If I try the simple
logtest = log(complex(1.0, 2.0))

I get the compiler error

Error: function core.stdc.math.log(double x) is not callable 
using argument types (Complex!double)


Some basic functions are described in 
https://dlang.org/phobos/std_complex.html, but not the log...


Re: Speed of math function atan: comparison D and C++

2018-03-06 Thread J-S Caux via Digitalmars-d-learn

On Tuesday, 6 March 2018 at 07:12:57 UTC, Robert M. Münch wrote:

On 2018-03-05 20:11:06 +, H. S. Teoh said:

Walter has been adamant that we should always compute 
std.math.*
functions with the `real` type, which on x86 maps to the 
non-IEEE 80-bit
floats.  However, 80-bit floats have been deprecated for a 
while now,


Hi, do you have a reference for this? I can't believe this, as 
the 80-bit are pretty important for a lot of optimization 
algorithms. We use it all the time and it's absolutly necessary.


and pretty much nobody cares to improve their performance on 
newer CPUs,


Really?

focusing instead on SSE/MMX performance with 64-bit doubles.  
People
have been clamoring for using 64-bit doubles by default rather 
than

80-bit floats, but so far Walter has refused to budge.


IMO this is all driven by the GPU/AI hype that just (seems) to 
be happy with rough precision.


Speaking for myself, the reason why I haven't made the switch 
from C++ to D many years ago for all my scientific work is that 
for many computations, 64 bit precision is certainly sufficient, 
and the performance I could get out of D (factor 4 to 6 slower in 
my tests) was simply insufficient.


Now, with Uknown's trick of using the C math functions, I can 
reconsider. It's a bit of a "patch" but at least it works.


In an ideal world, I'd like the language I use to:
- have double-precision arithmetic with equal performance to C/C++
- have all basic mathematical functions implemented, including 
for complex types
- *big bonus*: have the ability to do extended-precision 
arithmetic (integer, but most importantly (complex) 
floating-point) on-the-fly if I so wish, without having to rely 
on external libraries.


C++ was always fine, with external libraries for extended 
precision, but D is so much more pleasant to use. Many of my 
colleagues are switching to e.g. Julia despite the performance 
costs, because it is by design a very maths/science-friendly 
language. D is however much closer to a whole stack of existing 
codebases, so switching to it would involve much less extensive 
refactoring.


Re: Speed of math function atan: comparison D and C++

2018-03-05 Thread J-S Caux via Digitalmars-d-learn

On Monday, 5 March 2018 at 09:48:49 UTC, Uknown wrote:

Depending on your platform, the size of `double` could be 
different between C++ and D. Could you check that the size and 
precision are indeed the same?
Also, benchmark method is just as important as benchmark code. 
Did you use DMD or LDC as the D compiler? In this case it 
shouldn't matter, but try with LDC if you haven't. Also ensure 
that you've used the right flags:

`-release -inline -O`.

If the D version is still slower, you could try using the C 
version of the function
Simply change `import std.math: atan;` to `core.stdc.math: 
atan;` [0]


[0]: https://dlang.org/phobos/core_stdc_math.html#.atan


Thanks all for the info.

I've tested these two very basic representative codes:
https://www.dropbox.com/s/b5o4i8h43qh1saf/test.cc?dl=0
https://www.dropbox.com/s/zsaikhdoyun3olk/test.d?dl=0

Results:

C++:
g++ (Apple LLVM version 7.3.0):  9.5 secs
g++ (GCC 7.1.0):  10.7 secs

D:
dmd :  35.5 secs
dmd -release -inline -O : 29.5 secs
ldc2 :  34.4 secs
ldc2 -release -O : 31.5 secs

But now: using the core.stdc.math atan as per Uknown's suggestion:
D:
dmd:  9 secs
dmd -release -inline -O :  6.8 secs
ldc2 : 10 secs
ldc2 -release -O :  6.5 secs   <- best

So indeed the difference is between the `std.math atan` versus 
the `core.stdc.math atan`. Thanks Uknown! Just knowing this trick 
could make the difference between me and other scientists 
switching over to D...


But now comes the question: can the D fundamental maths functions 
be propped up to be as fast as the C ones?


Re: Speed of math function atan: comparison D and C++

2018-03-04 Thread J-S Caux via Digitalmars-d-learn

On Monday, 5 March 2018 at 05:40:09 UTC, rikki cattermole wrote:

On 05/03/2018 6:35 PM, J-S Caux wrote:
I'm considering shifting a large existing C++ codebase into D 
(it's a scientific code making much use of functions like 
atan, log etc).


I've compared the raw speed of atan between C++ (Apple LLVM 
version 7.3.0 (clang-703.0.29)) and D (dmd v2.079.0, also ldc2 
1.7.0) by doing long loops of such functions.


I can't get the D to run faster than about half the speed of 
C++.


Are there benchmarks for such scientific functions published 
somewhere


Gonna need to disassemble and compare them.

atan should work out to only be a few instructions (inline 
assembly) from what I've looked at in the source.


Also you should post the code you used for each.


So the codes are trivial, simply some check of raw speed:

  double x = 0.0;
  for (int a = 0; a < 10; ++a) x += atan(1.0/(1.0 + 
sqrt(1.0 + a)));


for C++ and

  double x = 0.0;
  for (int a = 0; a < 1_000_000_000; ++a) x += atan(1.0/(1.0 + 
sqrt(1.0 + a)));


for D. C++ exec takes 40 seconds, D exec takes 68 seconds.


Speed of math function atan: comparison D and C++

2018-03-04 Thread J-S Caux via Digitalmars-d-learn
I'm considering shifting a large existing C++ codebase into D 
(it's a scientific code making much use of functions like atan, 
log etc).


I've compared the raw speed of atan between C++ (Apple LLVM 
version 7.3.0 (clang-703.0.29)) and D (dmd v2.079.0, also ldc2 
1.7.0) by doing long loops of such functions.


I can't get the D to run faster than about half the speed of C++.

Are there benchmarks for such scientific functions published 
somewhere?