Skynet 1M Fiber microbenchmark in D
Biotronic
simen.kjaras at gmail.com
Wed Oct 18 11:52:08 UTC 2017
On Wednesday, 18 October 2017 at 11:34:57 UTC, Nordlöw wrote:
> Another thing...how should the synchronization between the
> fibers figure out when the total number of fibers have reached
> one million?...via an atomic counter fed by reference to the
> constructor...or are there better ways? Because I do need an
> atomic reference counter here, right?
This is how I did it:
import core.thread : Fiber;
class MyFiber : Fiber {
int _depth;
ulong _index;
ulong _value;
this(int depth, ulong index) {
super(&run);
_depth = depth;
_index = index;
}
void run() {
if (_depth == 6) { // 10^6 == 1 million, so stop here.
_value = _index;
return;
}
_value = 0;
foreach (i; 0..10) { // Line 23
auto e = new MyFiber(_depth+1, _index * 10 + i);
e.call();
_value += e._value;
}
}
}
unittest {
import std.stdio : writeln;
import std.datetime.stopwatch : StopWatch, AutoStart;
auto sw = StopWatch(AutoStart.yes);
auto a = new MyFiber(0, 0);
a.call();
sw.stop();
assert(a._value == 499999500000);
writeln(a._value, " after ", sw.peek);
}
> And how do I parallelize this over multiple worker threads?
> AFAICT fibers are by default all spawned in the same main
> thread, right?
True. Well, they're not really spawned on any thread - they're
allocated on the heap, have their own stack, and are run on
whichever thread happens to invoke their call() method.
I experimented a little bit with parallelism, and the easiest
definitely is to replace line 23 with this:
foreach (i; taskPool.parallel(10.iota, 1)) {
It seems to make very little difference in terms of run time,
though. I tried using a mix of these approaches - parallel at low
depth, basically just to fill up the cores, and serial closer to
the leaves. The difference is still negligible, so I assume the
losses are elsewhere.
--
Biotronic
More information about the Digitalmars-d-learn
mailing list