Thread overview
.array required if FilterResult is fed to parallel [lazy]
Jul 03
kdevel
Jul 03
monkyyy
Jul 04
Sergey
Jul 05
Sergey
July 03
import std;

extern (C) int sleep (int);

void main ()
{
   defaultPoolThreads (8);
   auto itemsstring = "a b c d e f g";
   auto items = itemsstring
      .split // split at ws
      .filter!(s => s != "" && s[0] != '#')
//      .array // uncomment for parallel execution
      ;
   pragma (msg, typeof (items));
   foreach (item; parallel (items)) {
      sleep (1);
      writeln (item);
   }
}

This program prints the letters a to g with a 1 s pause between them.
Is that intended?

July 03

On Thursday, 3 July 2025 at 21:56:03 UTC, kdevel wrote:

>
import std;

extern (C) int sleep (int);

void main ()
{
   defaultPoolThreads (8);
   auto itemsstring = "a b c d e f g";
   auto items = itemsstring
      .split // split at ws
      .filter!(s => s != "" && s[0] != '#')
//      .array // uncomment for parallel execution
      ;
   pragma (msg, typeof (items));
   foreach (item; parallel (items)) {
      sleep (1);
      writeln (item);
   }
}

This program prints the letters a to g with a 1 s pause between them.
Is that intended?

likely, .array isnt aa's range code, ideally there would be a smarter "make a forward range more random access" primitive.

July 04

On Thursday, 3 July 2025 at 21:56:03 UTC, kdevel wrote:

>
import std;

extern (C) int sleep (int);

void main ()
{
   defaultPoolThreads (8);
   auto itemsstring = "a b c d e f g";
   auto items = itemsstring
      .split // split at ws
      .filter!(s => s != "" && s[0] != '#')
//      .array // uncomment for parallel execution
      ;
   pragma (msg, typeof (items));
   foreach (item; parallel (items)) {
      sleep (1);
      writeln (item);
   }
}

This program prints the letters a to g with a 1 s pause between them.
Is that intended?

Apparently, yes.

    ParallelForeach!R parallel(R)(R range)
    {
        static if (hasLength!R)
        {
            // Default work unit size is such that we would use 4x as many
            // slots as are in this thread pool.
            size_t workUnitSize = defaultWorkUnitSize(range.length);
            return parallel(range, workUnitSize);
        }
        else
        {
            // Just use a really, really dumb guess if the user is too lazy to
            // specify.
            return parallel(range, 512);
        }
    }

Because filter has no length, it guesses it can hand the first 512 to one thread. Which is all of it.

In order to get the behavior you want, you have to specify the work unit size:

foreach (item; parallel (items, 1)) { // one unit per thread

Note that I was not aware of this, and I bet most people are not, even seasoned D developers.

-Steve

July 04

On Friday, 4 July 2025 at 00:17:40 UTC, Steven Schveighoffer wrote:

>

Note that I was not aware of this, and I bet most people are not, even seasoned D developers.

-Steve

We’ve used that parameter when participated in “related top n” benchmark!

July 04

On Friday, 4 July 2025 at 04:08:01 UTC, Sergey wrote:

>

On Friday, 4 July 2025 at 00:17:40 UTC, Steven Schveighoffer wrote:

>

Note that I was not aware of this, and I bet most people are not, even seasoned D developers.

We’ve used that parameter when participated in “related top n” benchmark!

I meant the part where a range without length picks a bad number for that value. Is that why we did it? I don’t remember.

-Steve

July 05

On Friday, 4 July 2025 at 12:32:28 UTC, Steven Schveighoffer wrote:

>

I meant the part where a range without length picks a bad number for that value. Is that why we did it? I don’t remember.

-Steve

Yes
We’ve experimented with several options there
But finished with 1
https://github.com/jinyus/related_post_gen/blob/3955e78fdce28cd516a8349551303736e03ec728/d_con/source/app.d#L56

July 05

On Saturday, 5 July 2025 at 14:38:55 UTC, Sergey wrote:

>

On Friday, 4 July 2025 at 12:32:28 UTC, Steven Schveighoffer wrote:

>

I meant the part where a range without length picks a bad number for that value. Is that why we did it? I don’t remember.

Yes
We’ve experimented with several options there
But finished with 1
https://github.com/jinyus/related_post_gen/blob/3955e78fdce28cd516a8349551303736e03ec728/d_con/source/app.d#L56

Yes, but note that posts is an array, with a length. So we did not run into this problem.

And in any case, if it did not have a length, the number of posts is around 5k, so 512 wouldn't have been horrible performance.

The issue here is that one thread gets all the work, and the others are left idle.

-Steve