.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