Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multithreading in D with for loop

I know that Rust can run loops with lightweight threads. Something like:

use task::spawn;

fn main() {
  for 100.times {
    do spawn {
      io::println("Hello");
    }
  }

How I can do this in D?

like image 523
Suliman Avatar asked Mar 09 '13 09:03

Suliman


2 Answers

Relevant API doc: std.parallelism

Here are a few of ways of accomplishing your example:

Parallel foreach, using a TaskPool's parallel:

foreach (i, val; taskPool.parallel(new int[50])) {
    writeln("Hello:", i);
}

Regular foreach, adding tasks to a task pool using put:

foreach (i; 0 .. 50) {
    auto t = task!writeln("Hello:", i);
    taskPool.put(t);
}

Execute each task in a new thread instead of a TaskPool:

foreach (i; 0 .. 50) {
    auto t = task!writeln("Hello:", i);
    t.executeInNewThread();
}

Rust's runtime has a built-in task scheduler, but with D, this is implemented as a library. That being said, the second is the closest in terms of functionality, and the last is the closest in terms of syntax (but they're OS threads, not lightweight).

In D, lightweight threads are explicitly controlled by the programmer. A TaskPool is analogous to the scheduler in Rust/Go, but it gives more fine-grained control to the programmer. This makes it slightly more verbose, but it also gives you parallel versions of map, reduce, foreach, etc. This makes it easier to represent more complex algorithms efficiently.

Running each example should give you the expected result: out of order writes.

Note:

From the doc:

The worker threads in this pool are daemon threads, meaning that it is not necessary to call TaskPool.stop or TaskPool.finish before terminating the main thread.

The second example doesn't wait until all workers are done, so in testing you may get no results (when main finishes, all remaining tasks are killed). You may need to block by calling finish:

taskPool.finish(true);
like image 58
beatgammit Avatar answered Oct 17 '22 15:10

beatgammit


D has no built-in abstractions for lightweight threads. Instead, you can:

  • use threads (see std.concurrency and std.parallelism)
  • use fibers, and multitask manually by explicitly yielding execution
  • use a library such as Vibe.d, which implements asynchronous I/O using fibers and implicit yielding on blocking operations
like image 30
Vladimir Panteleev Avatar answered Oct 17 '22 16:10

Vladimir Panteleev