.array required if FilterResult is fed to parallel [lazy]

Steven Schveighoffer schveiguy at gmail.com
Fri Jul 4 00:17:40 UTC 2025


On Thursday, 3 July 2025 at 21:56:03 UTC, kdevel wrote:
> ```d
> 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](https://github.com/dlang/phobos/blob/96458a1722c74ea03ffd70366c0fff554b1a8f2c/std/parallelism.d#L1658-L1673).

```d
     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:

```d
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


More information about the Digitalmars-d mailing list