passing a variadic parameter to randomSample

2022-01-25 Thread forkit via Digitalmars-d-learn
so I'm trying to write (or rather learn how to write) a 'variadic 
template function', that returns just one of its variadic 
parameter, randomly chosen.


But can't get my head around the problem here :-(

.. Error: template `std.random.randomSample` cannot deduce 
function from argument types `


// --

module test;
import std;

string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}

// --


Re: passing a variadic parameter to randomSample

2022-01-25 Thread vit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 09:48:25 UTC, forkit wrote:
so I'm trying to write (or rather learn how to write) a 
'variadic template function', that returns just one of its 
variadic parameter, randomly chosen.


But can't get my head around the problem here :-(

.. Error: template `std.random.randomSample` cannot deduce 
function from argument types `


// --

module test;
import std;

string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}

// --


`r` is not input range, try this:

```d
module test;
import std;


string RandomChoice1(R...)(R r)
{
auto rnd = MinstdRand0(unpredictableSeed);
return only(r).randomSample(1, rnd).front;
}

string RandomChoice2(R...)(R r)@nogc
{
auto rnd = MinstdRand0(unpredictableSeed);

switch(rnd.front % R.length){
static foreach(enum I, alias arg; r){
case I:
return arg;
}

default:
assert(0, "no impl");
}
}

void main()
{
writeln( RandomChoice1("typeA", "typeB", "typeC") );
writeln( RandomChoice2("typeA", "typeB", "typeC") );
}
```



How to create a function that behaves like std.stdio.writeln but prepends output with __FILE__:_LINE_

2022-01-25 Thread JG via Digitalmars-d-learn

Any ideas how one can achieve what is written in the subject line?

f below does achieve this but I one would expect that it produces
significant template bloat.

g achieves the aim but isn't very elegant.

import std;
void f(string file=__FILE__,size_t line=__LINE__,R...)(R r)
{
  writeln(file,":",line," ",r);
}
void g(T)(T t,string file=__FILE__,size_t line=__LINE__)
{
 writeln(file,":",line," ",t.expand);
}

void main()
{
   f("hello ", 123);
   g(tuple("hello ",123));
}


Re: How to create a function that behaves like std.stdio.writeln but prepends output with __FILE__:_LINE_

2022-01-25 Thread Dennis via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 12:11:01 UTC, JG wrote:
Any ideas how one can achieve what is written in the subject 
line?


```D
void f(T...)(auto ref T args, string file = __FILE__, int line = 
__LINE__)

{
writeln(file, ":", line, ": ", args);
}
```


Re: passing a variadic parameter to randomSample

2022-01-25 Thread WebFreak001 via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 09:48:25 UTC, forkit wrote:
so I'm trying to write (or rather learn how to write) a 
'variadic template function', that returns just one of its 
variadic parameter, randomly chosen.


But can't get my head around the problem here :-(

.. Error: template `std.random.randomSample` cannot deduce 
function from argument types `


// --

module test;
import std;

string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}

// --


With R... each value could be of different type, so passing 
`RandomChoice("typeA", 4)` would break the current code.


I think there are 2 different ways that can solve this elegantly:

1) restrict the parameters to all be the same parameter type:

```d
string RandomChoice(T)(T[] r...)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}
```

and code compiles with no changes. Instead of using 
.to!string you could also return the parameter type itself if you 
want to get the value itself:


```d
T RandomChoice(T)(T[] r...)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).front;
}
```

2) generate a random number between 0 and `r.length`, add a 
switch case and dynamically generate a case for each number 
(static foreach) and return the processed value using .to!string:


```d
string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
switch (uniform(0, R.length, rnd))
{
static foreach (i, value; r)
{
case i: // this code is duplicated for each 
parameter
	// use this if you want to support different 
argument types

return value.to!string;
}
default: assert(false);
}
}
```


Re: How to create a function that behaves like std.stdio.writeln but prepends output with __FILE__:_LINE_

2022-01-25 Thread WebFreak001 via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 12:27:16 UTC, Dennis wrote:

On Tuesday, 25 January 2022 at 12:11:01 UTC, JG wrote:
Any ideas how one can achieve what is written in the subject 
line?


```D
void f(T...)(auto ref T args, string file = __FILE__, int line 
= __LINE__)

{
writeln(file, ":", line, ": ", args);
}
```


note: default arguments after variadic arguments are supported 
since D 2.079.0: 
https://dlang.org/changelog/2.079.0.html#default_after_variadic


Re: passing a variadic parameter to randomSample

2022-01-25 Thread WebFreak001 via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 09:48:25 UTC, forkit wrote:
so I'm trying to write (or rather learn how to write) a 
'variadic template function', that returns just one of its 
variadic parameter, randomly chosen.


But can't get my head around the problem here :-(

.. Error: template `std.random.randomSample` cannot deduce 
function from argument types `


// --

module test;
import std;

string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}

// --


On Tuesday, 25 January 2022 at 09:48:25 UTC, forkit wrote:
so I'm trying to write (or rather learn how to write) a 
'variadic template function', that returns just one of its 
variadic parameter, randomly chosen.


But can't get my head around the problem here :-(

.. Error: template `std.random.randomSample` cannot deduce 
function from argument types `


// --

module test;
import std;

string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
}

// --


With R... each value could be of different type, so passing 
`RandomChoice("typeA", 4)` would break the current code.


I think there are 2 different ways that can solve this elegantly:

1) restrict the parameters to all be the same parameter type:

```d
string RandomChoice(T)(T[] r...)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).to!string;
}
```

and code compiles with no changes. Instead of using 
.to!string you could also return the parameter type itself if you 
want to get the value itself:


```d
T RandomChoice(T)(T[] r...)
{
auto rnd = MinstdRand0(42);
return r.randomSample(1, rnd).front;
}
```

2) generate a random number between 0 and `r.length`, add a 
switch case and dynamically generate a case for each number 
(static foreach) and return the processed value using .to!string:


```d
string RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(42);
switch (uniform(0, R.length, rnd))
{
static foreach (i, value; r)
{
case i: // this code is duplicated for each 
parameter
	// use this if you want to support different 
argument types

return value.to!string;
}
default: assert(false);
}
}
```


Re: How to create a function that behaves like std.stdio.writeln but prepends output with __FILE__:_LINE_

2022-01-25 Thread JG via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 12:27:16 UTC, Dennis wrote:

On Tuesday, 25 January 2022 at 12:11:01 UTC, JG wrote:
Any ideas how one can achieve what is written in the subject 
line?


```D
void f(T...)(auto ref T args, string file = __FILE__, int line 
= __LINE__)

{
writeln(file, ":", line, ": ", args);
}
```


Thank you very much.


gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn
Sorry for being vague and not giving the code here but a program I wrote 
about spelling-out parts of a number (in Turkish) as in "1 milyon 42" 
runs much faster with gdc.


The program integer-divides the number in a loop to find quotients and 
adds the word next to it. One obvious optimization might be to use POSIX 
div() and friends to get the quotient and the remainder at one shot but 
I made myself believe that the compilers already do that. (But still not 
sure. :o) )


I am not experienced with dub but I used --build=release-nobounds and 
verified that -O3 is used for both compilers. (I also tried building 
manually with GNU 'make' with e.g. -O5 and the results were similar.)


For a test run for 2 million numbers:

ldc: ~0.95 seconds
gdc: ~0.79 seconds
dmd: ~1.77 seconds

I am using compilers installed by Manjaro Linux's package system:

ldc: LDC - the LLVM D compiler (1.28.0):
  based on DMD v2.098.0 and LLVM 13.0.0

gdc: dc (GCC) 11.1.0

dmd: DMD64 D Compiler v2.098.1

I've been mainly a dmd person for various reasons and was under the 
impression that ldc was the clear winner among the three. What is your 
experience? Does gdc compile faster programs in general? Would ldc win 
if I took advantage of e.g. link-time optimizations?


Ali


Re: gdc or ldc for faster programs?

2022-01-25 Thread Johan via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 19:52:17 UTC, Ali Çehreli wrote:


I am not experienced with dub but I used 
--build=release-nobounds and verified that -O3 is used for both 
compilers. (I also tried building manually with GNU 'make' with 
e.g. -O5 and the results were similar.)


`-O5` does not do anything different than `-O3` for LDC.


For a test run for 2 million numbers:

ldc: ~0.95 seconds
gdc: ~0.79 seconds
dmd: ~1.77 seconds

I am using compilers installed by Manjaro Linux's package 
system:


ldc: LDC - the LLVM D compiler (1.28.0):
  based on DMD v2.098.0 and LLVM 13.0.0

gdc: dc (GCC) 11.1.0

dmd: DMD64 D Compiler v2.098.1

I've been mainly a dmd person for various reasons and was under 
the impression that ldc was the clear winner among the three. 
What is your experience? Does gdc compile faster programs in 
general? Would ldc win if I took advantage of e.g. link-time 
optimizations?


Tough to say. Of course DMD is not a serious contender, but I 
believe the difference between GDC and LDC is very small and 
really in the details, i.e. you'll have to look at assembly to 
find out the delta.

Have you tried `--enable-cross-module-inlining` with LDC?

-Johan




Re: gdc or ldc for faster programs?

2022-01-25 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 19:52:17 UTC, Ali Çehreli wrote:

ldc: ~0.95 seconds
gdc: ~0.79 seconds
dmd: ~1.77 seconds


Not surprising at all: gdc is excellent and underrated in the 
community.


Re: gdc or ldc for faster programs?

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 11:52:17AM -0800, Ali Çehreli via Digitalmars-d-learn 
wrote:
> Sorry for being vague and not giving the code here but a program I
> wrote about spelling-out parts of a number (in Turkish) as in "1
> milyon 42" runs much faster with gdc.
> 
> The program integer-divides the number in a loop to find quotients and
> adds the word next to it. One obvious optimization might be to use
> POSIX div() and friends to get the quotient and the remainder at one
> shot but I made myself believe that the compilers already do that.
> (But still not sure. :o))

Don't guess at what the compilers are doing; disassemble the binary and
see for yourself exactly what the difference is. Use run.dlang.io for a
convenient interface that shows you exactly how the compilers translated
your code. Or if you're macho, use `objdump -d` and search for _Dmain
(or the specific function if you know how it's mangled).


> I am not experienced with dub but I used --build=release-nobounds and
> verified that -O3 is used for both compilers. (I also tried building
> manually with GNU 'make' with e.g. -O5 and the results were similar.)
> 
> For a test run for 2 million numbers:
> 
> ldc: ~0.95 seconds
> gdc: ~0.79 seconds
> dmd: ~1.77 seconds

For measurements under 1 second, I'm skeptical of the accuracy, because
there could be all kinds of background noise, CPU interrupts and stuff
that could be skewing the numbers.  What about do a best-of-3-runs with
20 million numbers (expected <20 seconds per run) and see how the
numbers look?

Though having said all that, I can say at least that dmd's relatively
poor performance seems in line with my previous observations. :-P The
difference between ldc and gdc is harder to pinpoint; they each have
different optimizers that could work better or worse than the other
depending on the specifics of what the program is doing.


[...]
> I've been mainly a dmd person for various reasons and was under the
> impression that ldc was the clear winner among the three. What is your
> experience? Does gdc compile faster programs in general? Would ldc win
> if I took advantage of e.g. link-time optimizations?
[...]

I'm not sure LDC is the clear winner.  I only prefer LDC because LDC's
architecture makes it easier for cross-compilation (with GCC/GDC you
need to jump through a lot more hoops to get a working cross compiler).
GDC is also tied to the GCC release cycle, and tends to be several
language versions behind LDC.  But both compilers have excellent
optimizers, but they are definitely different so for some things GDC
will beat LDC, for other things LDC will beat GDC. It may depend on the
specific optimization flags you use as well.

But these sorts of statements are just generalizations. The best way to
find out for sure is to disassemble the executable and see for yourself
what the assembly looks like. :-)


T

-- 
Public parking: euphemism for paid parking. -- Flora


Re: gdc or ldc for faster programs?

2022-01-25 Thread Daniel N via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 20:04:04 UTC, Adam D Ruppe wrote:

On Tuesday, 25 January 2022 at 19:52:17 UTC, Ali Çehreli wrote:

ldc: ~0.95 seconds
gdc: ~0.79 seconds
dmd: ~1.77 seconds




Maybe you can try --ffast-math on ldc.


Re: gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 11:52, Ali Çehreli wrote:

> a program I wrote about spelling-out parts of a number

Here is the program as a single module:

module spellout.spellout;

// This program was written as a code kata to spell out
// certain parts of integers as in "1 million 2 thousand
// 42". Note that this way of spelling-out numbers is not
// grammatically correct in English.

// Returns a string that contains the partly spelled-out version
// of the parameter.
//
// You must copy the returned string when needed as this function
// uses the same internal buffer for all invocations of the same
// template instance.
auto spellOut(T)(in T number_) {
  import std.array : Appender;
  import std.string : strip;
  import std.traits : Unqual;
  import std.meta : AliasSeq;

  static Appender!(char[]) result;
  result.clear;

  // We treat these specially because the algorithm below does
  // 'number = -number' and calls the same implementation
  // function. The trouble is, for example, -int.min is still a
  // negative number.
  alias problematics = AliasSeq!(
byte, "negative 128",
short, "negative 32 thousand 768",
int, "negative 2 billion 147 million 483 thousand 648",
long, "negative 9 quintillion 223 quadrillion 372 trillion" ~
  " 36 billion 854 million 775 thousand 808");

  static assert((problematics.length % 2) == 0);

  static foreach (i, P; problematics) {
static if (i % 2) {
  // This is a string; skip

} else {
  // This is a problematic type
  static if (is (T == P)) {
// Our T happens to be this problematic type
if (number_ == T.min) {
  // and we are dealing with a problematic value
  result ~= problematics[i + 1];
  return result.data;
}
  }
}
  }

  auto number = cast(Unqual!T)number_; // Thanks 'in'! :p

  if (number == 0) {
result ~= "zero";

  } else {
if (number < 0) {
  result ~= "negative";
  static if (T.sizeof < int.sizeof) {
// Being careful with implicit conversions. (See the dmd
// command line switch -preview=intpromote)
number = cast(T)(-cast(int)number);

  } else {
number = -number;
  }
}

spellOutImpl(number, result);
  }

  return result.data.strip;
}

unittest {
  assert(1_001_500.spellOut == "1 million 1 thousand 500");
  assert((-1_001_500).spellOut ==
 "negative 1 million 1 thousand 500");
  assert(1_002_500.spellOut == "1 million 2 thousand 500");
}

import std.format : format;
import std.range : isOutputRange;

void spellOutImpl(T, O)(T number, ref O output)
if (isOutputRange!(O, char))
in (number > 0, format!"Invalid number: %s"(number)) {
  import std.range : retro;
  import std.format : formattedWrite;

  foreach (divider; dividers!T.retro) {
const quotient = number / divider.value;

if (quotient) {
  output.formattedWrite!" %s %s"(quotient, divider.word);
}

number %= divider.value;
  }
}

struct Divider(T) {
  T value;// 1_000, 1_000_000, etc.
  string word;// "thousand", etc
}

// Returns the words related with the provided size of an
// integral type. The parameter is number of bytes
// e.g. int.sizeof
auto words(size_t typeSize) {
  // This need not be recursive at all but it was fun using
  // recursion.
  final switch (typeSize) {
  case 1: return [ "" ];
  case 2: return words(1) ~ [ "thousand" ];
  case 4: return words(2) ~ [ "million", "billion" ];
  case 8: return words(4) ~ [ "trillion", "quadrillion", "quintillion" ];
  }
}

unittest {
  // These are relevant words for 'int' and 'uint' values:
  assert(words(4) == [ "", "thousand", "million", "billion" ]);
}

// Returns a Divider!T array associated with T
auto dividers(T)() {
  import std.range : array, enumerate;
  import std.algorithm : map;

  static const(Divider!T[]) result =
words(T.sizeof)
.enumerate!T
.map!(t => Divider!T(cast(T)(10^^(t.index * 3)), t.value))
.array;

  return result;
}

unittest {
  // Test a few entries
  assert(dividers!int[1] == Divider!int(1_000, "thousand"));
  assert(dividers!ulong[3] == Divider!ulong(1_000_000_000, "billion"));
}

void main() {
  version (test) {
return;
  }

  import std.meta : AliasSeq;
  import std.stdio : writefln;
  import std.random : Random, uniform;
  import std.conv : to;

  static foreach (T; AliasSeq!(byte, ubyte, short, ushort,
   int, uint, long, ulong)) {{
  // A few numbers for each type
  report(T.min);
  report((T.max / 4).to!T);  // Overcome int promotion for
 // shorter types because I want
 // to test with the exact type
 // e.g. for byte.
  report(T.max);
}}

  enum count = 2_000_000;
  writefln!"Testing with %,s random numbers"(spellOut(count));

  // Use the same seed to be fair between compilations
  enum seed = 0;
  auto rnd = Random(seed);

  ulong totalLength;
  foreach (i; 0 .

Re: gdc or ldc for faster programs?

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 08:04:04PM +, Adam D Ruppe via Digitalmars-d-learn 
wrote:
> On Tuesday, 25 January 2022 at 19:52:17 UTC, Ali Çehreli wrote:
> > ldc: ~0.95 seconds
> > gdc: ~0.79 seconds
> > dmd: ~1.77 seconds
> 
> Not surprising at all: gdc is excellent and underrated in the
> community.

The GCC optimizer is actually pretty darned good, comparable to LDC's. I
only prefer LDC because of easier cross-compilation and more up-to-date
language version (due to GDC being tied to GCC's release cycle). But I
wouldn't hesitate to use gdc if I didn't need to cross-compile or use
features from the latest language version.

DMD's optimizer is miles behind LDC/GDC, sad to say. About the only
thing that keeps me using dmd is its lightning-fast compilation times,
ideal for iterative development. For anything performance related, DMD
isn't even on my radar.


T

-- 
Doubtless it is a good thing to have an open mind, but a truly open mind should 
be open at both ends, like the food-pipe, with the capacity for excretion as 
well as absorption. -- Northrop Frye


Re: gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 12:01, Johan wrote:


Have you tried `--enable-cross-module-inlining` with LDC?


Tried now. Makes no difference that I can sense, likely because there is 
only one module anyway. :) (But I guess it works over Phobos modules too.)


Ali


Re: gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 12:59, Daniel N wrote:


Maybe you can try --ffast-math on ldc.


Did not make a difference.

Ali



Re: gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 12:42, H. S. Teoh wrote:

>> For a test run for 2 million numbers:
>>
>> ldc: ~0.95 seconds
>> gdc: ~0.79 seconds
>> dmd: ~1.77 seconds
>
> For measurements under 1 second, I'm skeptical of the accuracy, because
> there could be all kinds of background noise, CPU interrupts and stuff
> that could be skewing the numbers.  What about do a best-of-3-runs with
> 20 million numbers (expected <20 seconds per run) and see how the
> numbers look?

Makes sense. The results are similar to the 2 million run.

> But these sorts of statements are just generalizations. The best way to
> find out for sure is to disassemble the executable and see for yourself
> what the assembly looks like. :-)

I posted the program to have more eyes on the assembly. ;)

Ali



Re: passing a variadic parameter to randomSample

2022-01-25 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 11:50:08 UTC, vit wrote:




thanks. problem solved (providing all parameters are of the same 
type).


// ---

module test;
import std;

auto RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(unpredictableSeed);
return only(r).randomSample(1, rnd).front;
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
writeln( RandomChoice(5, 8, 2) );
writeln( RandomChoice(100.05, 110.8, 109.54) );

//writeln( RandomChoice("typeA", 5, 100.14) ); // nope. they 
all need to be of the same type.
writeln( RandomChoice("typeA", 5.to!string, 100.14.to!string) 
);

}

//--


Re: passing a variadic parameter to randomSample

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 13:55, forkit wrote:

> auto RandomChoice(R...)(R r)

Watch out though: The compiler will compile a different function per set 
of values. For example, there will be separate RandomChoice instances 
for ("hello") vs. ("world").


D has a simple variadic parameter syntax as well:

auto RandomChoice(R)(R[] r...)

> {
>  auto rnd = MinstdRand0(unpredictableSeed);
>  return only(r).randomSample(1, rnd).front;

Which makes that simpler as well because being a slice, r is already a 
range. And there is choice():


return r.choice(rnd);

Something is very important though: The 'r' slice is short-lived; it 
does not live in dynamic memory. RandomChoice() should not save it for 
later use nor return it. (The compiler may have protection against that; 
I am not sure.)


Ali



Re: gdc or ldc for faster programs?

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 01:30:59PM -0800, Ali Çehreli via Digitalmars-d-learn 
wrote:
[...]
> I posted the program to have more eyes on the assembly. ;)
[...]

I tested the code locally, and observed, just like Ali did, that the LDC
version is unambiguously slower than the gdc version by a small margin.

So I decided to compare the disassembly.  Due to the large number of
templates in the main spellOut/spellOutImpl functions, I didn't have the
time to look at all of them; I just arbitrarily picked the !(int)
instantiation. And I'm seeing something truly fascinating:

- The GDC version has at its core a single idivl instruction for the /
  and %= operators (I surmise that the optimizer realized that both
  could share the same instruction because it yields both results).  The
  function is short and compact.

- The LDC version, however, seems to go out of its way to avoid the
  idivl instruction, having instead a whole bunch of shr instructions
  and imul instructions involving magic constants -- the kind of stuff
  you see in bit-twiddling hacks when people try to ultra-optimize their
  code.  There also appears to be some loop unrolling, and the function
  is markedly longer than the GDC version because of this.

This is very interesting because idivl is known to be one of the slower
instructions, but gdc nevertheless considered it not worthwhile to
replace it, whereas ldc seems obsessed about avoid idivl at all costs.

I didn't check the other instantiations, but it would appear that in
this case the simpler route of just using idivl won over the complexity
of trying to replace it with shr+mul.


T

-- 
Guns don't kill people. Bullets do.


Re: passing a variadic parameter to randomSample

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 02:07:43PM -0800, Ali Çehreli via Digitalmars-d-learn 
wrote:
[...]
> auto RandomChoice(R)(R[] r...)
> 
> > {
> >  auto rnd = MinstdRand0(unpredictableSeed);
> >  return only(r).randomSample(1, rnd).front;
> 
> Which makes that simpler as well because being a slice, r is already a
> range. And there is choice():
> 
> return r.choice(rnd);
> 
> Something is very important though: The 'r' slice is short-lived; it does
> not live in dynamic memory. RandomChoice() should not save it for later use
> nor return it. (The compiler may have protection against that; I am not
> sure.)

I think with -dip1000 the compiler should refuse to compile the code if
you try to save a slice of r past the function body.


T

-- 
Philosophy: how to make a career out of daydreaming.


Re: passing a variadic parameter to randomSample

2022-01-25 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 22:07:43 UTC, Ali Çehreli wrote:




thanks. makes it even shorter and simpler :-)

// --

module test;
@safe:

import std;

auto RandomChoice(R...)(R r)
{
auto rnd = MinstdRand0(unpredictableSeed);
return only(r).choice(rnd);
}

void main()
{
writeln( RandomChoice("typeA", "typeB", "typeC") );
writeln( RandomChoice(5, 8, 2) );
writeln( RandomChoice(1.3, 5.09, 8, 2) );
writeln( RandomChoice(100.05, 110.8, 109.54) );

//writeln( RandomChoice("typeA", 5, 100.14) );
// nope. some issue with mixing strings with numeric types

writeln( RandomChoice("typeA", 5.to!string, 100.14.to!string) 
);

// NOTE: This registers with -profile=gc
}

// --




Re: gdc or ldc for faster programs?

2022-01-25 Thread Elronnd via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 22:33:37 UTC, H. S. Teoh wrote:
interesting because idivl is known to be one of the slower 
instructions, but gdc nevertheless considered it not worthwhile 
to replace it, whereas ldc seems obsessed about avoid idivl at 
all costs.


Interesting indeed.  Two remarks:

1. Actual performance cost of div depends a lot on hardware.  
IIRC on my old intel laptop it's like 40-60 cycles; on my newer 
amd chip it's more like 20; on my mac it's ~10.  GCC may be 
assuming newer hardware than llvm.  Could be worth popping on a 
-march=native -mtune=native.  Also could depend on how many ports 
can do divs; i.e. how many of them you can have running at a time.


2. LLVM is more aggressive wrt certain optimizations than gcc, by 
default.  Though I don't know how relevant that is at -O3.


Re: passing a variadic parameter to randomSample

2022-01-25 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 22:35:29 UTC, forkit wrote:




I should point out (to anyone looking at that code I posted), 
that it's easier, and makes more sense, to just write:


writeln( ["typeA", "typeB", "typeC"].choice );

... but my main focus here, was learning about variadic template 
functions.




Re: gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 14:33, H. S. Teoh wrote:

> This is very interesting

Fascinating code generation and investigation! :)

Ali



Re: gdc or ldc for faster programs?

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 10:41:35PM +, Elronnd via Digitalmars-d-learn wrote:
> On Tuesday, 25 January 2022 at 22:33:37 UTC, H. S. Teoh wrote:
> > interesting because idivl is known to be one of the slower
> > instructions, but gdc nevertheless considered it not worthwhile to
> > replace it, whereas ldc seems obsessed about avoid idivl at all
> > costs.
> 
> Interesting indeed.  Two remarks:
> 
> 1. Actual performance cost of div depends a lot on hardware.  IIRC on
> my old intel laptop it's like 40-60 cycles; on my newer amd chip it's
> more like 20; on my mac it's ~10.  GCC may be assuming newer hardware
> than llvm.  Could be worth popping on a -march=native -mtune=native.
> Also could depend on how many ports can do divs; i.e. how many of them
> you can have running at a time.

I tried `ldc2 -mcpu=native` but that did not significantly change the
performance.


> 2. LLVM is more aggressive wrt certain optimizations than gcc, by
> default.  Though I don't know how relevant that is at -O3.

Yeah, I've noted in the past that LDC seems to be pretty aggressive with
inlining / loop unrolling, whereas GDC has a thing for vectorization and
SIMD/XMM usage.  The exact outcomes are a toss-up, though. Sometimes LDC
wins, sometimes GDC wins.  Depends on what exactly the code is doing.


T

-- 
"Outlook not so good." That magic 8-ball knows everything! I'll ask about 
Exchange Server next. -- (Stolen from the net)


Re: passing a variadic parameter to randomSample

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 10:48:26PM +, forkit via Digitalmars-d-learn wrote:
[...]
> ... but my main focus here, was learning about variadic template
> functions.

D has several flavors of variadics:

1) C-style variadics (not type-safe, not recommended):

int func(int firstArgc, ...)

2) D-style type-safe variadics (non-templated):

int func(int[] args...)

   All arguments must be of the same type, and the function receives
   them as an array of that type, so .length can be used to ensure you
   don't overrun the array.

3) Variadic template functions:

int func(Args...)(Args args)

   Arguments can be of any type, the type can be obtained with Args[i].
   (Not to be confused with lowercase args[i], which gives you the
   argument value itself.)  The most flexible of the lot, but may also
   lead to template bloat if used excessively (one instantiation is
   generated for every different combination of argument types).

There's also the lazy variant of (2) with delegates, but I've never used
them before.


T

-- 
An elephant: A mouse built to government specifications. -- Robert Heinlein


Re: gdc or ldc for faster programs?

2022-01-25 Thread forkit via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 20:01:18 UTC, Johan wrote:


Tough to say. Of course DMD is not a serious contender, but I 
believe the difference between GDC and LDC is very small and 
really in the details, i.e. you'll have to look at assembly to 
find out the delta.

Have you tried `--enable-cross-module-inlining` with LDC?

-Johan


dmd is the best though, in terms of compilation speed without 
optimisation.


As I write/test A LOT of code, that time saved is very much 
appreciated ;-)


I hope it remains that way.


Re: gdc or ldc for faster programs?

2022-01-25 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jan 25, 2022 at 11:01:57PM +, forkit via Digitalmars-d-learn wrote:
> On Tuesday, 25 January 2022 at 20:01:18 UTC, Johan wrote:
> > 
> > Tough to say. Of course DMD is not a serious contender, but I
> > believe the difference between GDC and LDC is very small and really
> > in the details, i.e. you'll have to look at assembly to find out the
> > delta.  Have you tried `--enable-cross-module-inlining` with LDC?
[...]
> dmd is the best though, in terms of compilation speed without
> optimisation.
> 
> As I write/test A LOT of code, that time saved is very much
> appreciated ;-)
[...]

My general approach is: use dmd for iterating the code - compile - test
cycle, and use LDC for release/production builds.


T

-- 
Chance favours the prepared mind. -- Louis Pasteur


Re: gdc or ldc for faster programs?

2022-01-25 Thread Johan via Digitalmars-d-learn

On Tuesday, 25 January 2022 at 19:52:17 UTC, Ali Çehreli wrote:


I am using compilers installed by Manjaro Linux's package 
system:


ldc: LDC - the LLVM D compiler (1.28.0):
  based on DMD v2.098.0 and LLVM 13.0.0

gdc: dc (GCC) 11.1.0

dmd: DMD64 D Compiler v2.098.1


What phobos version is gdc using?

-Johan



Re: gdc or ldc for faster programs?

2022-01-25 Thread Ali Çehreli via Digitalmars-d-learn

On 1/25/22 16:15, Johan wrote:
> On Tuesday, 25 January 2022 at 19:52:17 UTC, Ali Çehreli wrote:
>>
>> I am using compilers installed by Manjaro Linux's package system:
>>
>> ldc: LDC - the LLVM D compiler (1.28.0):
>>   based on DMD v2.098.0 and LLVM 13.0.0
>>
>> gdc: dc (GCC) 11.1.0
>>
>> dmd: DMD64 D Compiler v2.098.1
>
> What phobos version is gdc using?

Oh! Good question. Unfortunately, I don't think Phobos modules contain 
that information. The following line outputs 2076L:


pragma(msg, __VERSION__);

So, I guess I've been comparing apples to oranges but in this case an 
older gdc is doing pretty well.


Ali