www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - parallel

reply Handyman <handyman handyworld.tv> writes:
import std.stdio;
import core.thread;
import std.datetime;          // for stopwatch
import std.parallelism;

void say(string s) {          // write and flush
    writeln(s);
    stdout.flush();
}

struct Dish {
    string name;
    void prepare() {
       say("Start with the " ~ name ~ ".");
       Thread.sleep(1.seconds); // kunstmatig tijd verbruiken
       say("Finished the " ~ name ~ ".");
    }
}

void main() {
    auto dishes = [ Dish("soup"), Dish("sauce"), Dish("fries"), 
Dish("fish"), Dish("ice") ];
    auto sw = StopWatch(AutoStart.yes);
    foreach (dish; parallel(dishes, 1)) dish.prepare();
    sw.stop;
    writefln("Diner is ready.  Cooking took %.3f seconds.", 
cast(float) sw.peek.msecs / 1000);
}

gives:

Start with the soup.
Start with the sauce.
Start with the fries.
Start with the fish.
Finished the sauce.
Finished the fries.
Start with the ice.
Finished the soup.
Finished the fish.
Finished the ice.
Diner is ready.  Cooking took 1.999 seconds.

Seems that 4 cores go all out on first 4 dishes, then 1 core 
deals with the last dish.  With 4 cores I expect diner is ready 
after 5/4 = 1.25 secs though.  What did I do wrong?
Nov 05 2015
next sibling parent reply anonymous <anonymous example.com> writes:
On 05.11.2015 21:30, Handyman wrote:
 Seems that 4 cores go all out on first 4 dishes, then 1 core deals with
 the last dish.  With 4 cores I expect diner is ready after 5/4 = 1.25
 secs though.  What did I do wrong?
You describe the situation correctly. The unit of work is a dish. That is, the work for a single dish is not split between cores. So one of your four cores has to make two dishes. That takes two seconds.
Nov 05 2015
parent reply Handyman <handyman handyworld.tv> writes:
On Thursday, 5 November 2015 at 20:40:00 UTC, anonymous wrote:
 So one of your four cores has to make two dishes. That takes 
 two seconds.
So make fine-grained? foreach (i; 0..50) Thread.sleep(20.msecs); But then my program still says: '2 secs'. Please enlighten me.
Nov 05 2015
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/05/2015 12:43 PM, Handyman wrote:
 On Thursday, 5 November 2015 at 20:40:00 UTC, anonymous wrote:
 So one of your four cores has to make two dishes. That takes two seconds.
So make fine-grained? foreach (i; 0..50) Thread.sleep(20.msecs); But then my program still says: '2 secs'. Please enlighten me.
That's still 1 second per task. The function prepare() cannot be executed by more than one core. Ali
Nov 05 2015
parent reply Handyman <handyman handyworld.tv> writes:
On Thursday, 5 November 2015 at 20:45:25 UTC, Ali Çehreli wrote:
 That's still 1 second per task. The function prepare() cannot 
 be executed by more than one core.
Thanks. OK. So 'prepare' is atomic? Then let's turn it around: how can I make the cores prepare a meal of 5 dishes in 1.25 secs? Should I rewrite, or split, 'prepare'?
Nov 05 2015
parent reply anonymous <anonymous example.com> writes:
On 05.11.2015 21:52, Handyman wrote:
 On Thursday, 5 November 2015 at 20:45:25 UTC, Ali Çehreli wrote:
 That's still 1 second per task. The function prepare() cannot be
 executed by more than one core.
Thanks. OK. So 'prepare' is atomic? Then let's turn it around: how can I make the cores prepare a meal of 5 dishes in 1.25 secs? Should I rewrite, or split, 'prepare'?
You'd have to split `prepare` further into parallelizable parts. In a real world scenario that may or may not be possible. When the goal is just sleeping we can do it, of course. Just do another `parallel` loop in `prepare`: import std.range: iota; foreach (i; parallel(iota(50))) Thread.sleep(20.msecs); This won't get you down to exactly 1.25 seconds, because the start/finish print outs still take some time, and because of parallelization overhead.
Nov 05 2015
parent Handyman <handyman handyworld.tv> writes:
On Thursday, 5 November 2015 at 21:10:16 UTC, anonymous wrote:
 parallel(iota(50)))
Wow. I have dealt with ranges and 'iota' (and with parallel), but I admit I have to think hard about this example. Thanks a bunch all for your patience.
Nov 05 2015
prev sibling parent reply anonymous <anonymous example.com> writes:
On 05.11.2015 21:43, Handyman wrote:
 foreach (i; 0..50)
     Thread.sleep(20.msecs);

 But then my program still says: '2 secs'.   Please enlighten me.
Let's look at the line that does the `parallel` call: foreach (dish; parallel(dishes, 1)) dish.prepare(); This means that `dishes` is processed in parallel. Multiple threads are started to execute `prepare()` on multiple elements of `dishes` at the same time. Each of those `dish.prepare()` calls is done on only one thread, though. There is not attempt to split the `prepare` action up and run parts of it in parallel.
Nov 05 2015
parent reply Handyman <handyman handyworld.tv> writes:
On Thursday, 5 November 2015 at 20:54:37 UTC, anonymous wrote:
 There is not attempt to split the `prepare` action up and run 
 parts of it in parallel.
So 1.25 secs is impossible?
Nov 05 2015
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/05/2015 12:58 PM, Handyman wrote:
 On Thursday, 5 November 2015 at 20:54:37 UTC, anonymous wrote:
 There is not attempt to split the `prepare` action up and run parts of
 it in parallel.
So 1.25 secs is impossible?
For the given example, yes, impossible. However, as mentioned elsewhere in this thread, if prepare() is parallelizable itself, then it would be possible. Ali
Nov 05 2015
prev sibling parent Alex Parrill <initrd.gz gmail.com> writes:
On Thursday, 5 November 2015 at 20:30:05 UTC, Handyman wrote:
 Seems that 4 cores go all out on first 4 dishes, then 1 core 
 deals with the last dish.  With 4 cores I expect diner is ready 
 after 5/4 = 1.25 secs though.  What did I do wrong?
The first four dishes get scheduled, all of them sleep for 1 second in parallel, then complete at roughly the same time. One second has passed. Now there's one dish left. It gets scheduled, sleeps for 1 second, and finishes (the other threads remain idle). Two seconds have passed.
Nov 05 2015