Concurrent computing

From Rosetta Code
Revision as of 04:22, 18 February 2011 by Sonia (talk | contribs) (→‎{{header|Go}}: updated to use new WaitGroup feature. also simplified a bit.)
Task
Concurrent computing
You are encouraged to solve this task according to the task description, using any language you may know.

Using either native language concurrency syntax or freely available libraries write a program to display the strings "Enjoy" "Rosetta" "Code", one string per line, in random order. Concurrency syntax must use threads, tasks, co-routines, or whatever concurrency is called in your language.


Ada

<lang ada>with Ada.Text_IO; use Ada.Text_IO; with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;

procedure Concurrent_Hello is

  task type Writer (Message : access String);
  task body Writer is
     Seed : Generator;
  begin
     Reset (Seed); -- This is time-dependent, see Reference Manual A.5.2
     delay Duration (Random (Seed));
     Put_Line (Message.all);
  end Writer;
 
  S1 : aliased String := "Enjoy";
  S2 : aliased String := "Rosetta";
  S3 : aliased String := "Code";
  T1 : Writer (S1'Access);
  T2 : Writer (S2'Access);
  T3 : Writer (S3'Access);

begin

  null;

end Concurrent_Hello;</lang>

Note that random generator object is local to each task. It cannot be accessed concurrently without mutual exclusion. In order to get different initial states of local generators Reset is called.

ALGOL 68

<lang algol68>main:(

 PROC echo = (STRING string)VOID:
     printf(($gl$,string));
 PAR(
   echo("Enjoy"),
   echo("Rosetta"),
   echo("Code")
 )

)</lang>

C

Works with: POSIX
Library: pthread

<lang c>#include <stdio.h>

  1. include <unistd.h>
  2. include <pthread.h>

pthread_mutex_t condm = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int bang = 0;

  1. define WAITBANG() do { \
  pthread_mutex_lock(&condm); \
  while( bang == 0 ) \
  { \
     pthread_cond_wait(&cond, &condm); \
  } \
  pthread_mutex_unlock(&condm); } while(0);\

void *t_enjoy(void *p) {

 WAITBANG();
 printf("Enjoy\n");
 pthread_exit(0);

}

void *t_rosetta(void *p) {

 WAITBANG();
 printf("Rosetta\n");
 pthread_exit(0);

}

void *t_code(void *p) {

 WAITBANG();
 printf("Code\n");
 pthread_exit(0);

}

typedef void *(*threadfunc)(void *); int main() {

  int i;
  pthread_t a[3];
  threadfunc p[3] = {t_enjoy, t_rosetta, t_code};
  
  for(i=0;i<3;i++)
  {
    pthread_create(&a[i], NULL, p[i], NULL);
  }
  sleep(1);
  bang = 1;
  pthread_cond_broadcast(&cond);
  for(i=0;i<3;i++)
  {
    pthread_join(a[i], NULL);
  }

}</lang>

Note: since threads are created one after another, it is likely that the execution of their code follows the order of creation. To make this less evident, I've added the bang idea using condition: the thread really executes their code once the gun bang is heard. Nonetheless, I still obtain the same order of creation (Enjoy, Rosetta, Code), and maybe it is because of the order locks are acquired. The only way to obtain randomness seems to be to add random wait in each thread (or wait for special cpu load condition)

C#

<lang csharp> static Random tRand = new Random();

static void Main(string[] args) { Thread t = new Thread(new ParameterizedThreadStart(WriteText)); t.Start("Enjoy");

t = new Thread(new ParameterizedThreadStart(WriteText)); t.Start("Rosetta");

t = new Thread(new ParameterizedThreadStart(WriteText)); t.Start("Code");

Console.ReadLine(); }

private static void WriteText(object p) { Thread.Sleep(tRand.Next(1000, 4000)); Console.WriteLine(p); } </lang>

An example result:

Enjoy
Code
Rosetta

Clojure

A simple way to obtain concurrency is using the future function, which evaluates its body on a separate thread. <lang clojure> (doseq [text ["Enjoy" "Rosetta" "Code"]]

 (future (println text)))

</lang>

Common Lisp

Concurrency and threads are not part of the Common Lisp standard. However, most implementations provide some interface for concurrency. Bordeaux Threads, used here, provides a compatibility layer for many implementations. (Binding out to *standard-output* before threads are created is needed as each thread gets its own binding for *standard-output*.)

<lang lisp>(defun concurrency-example (&optional (out *standard-output*))

 (let ((lock (bordeaux-threads:make-lock)))
   (flet ((writer (string)
            #'(lambda () 
                (bordeaux-threads:acquire-lock lock t)
                (write-line string out)
                (bordeaux-threads:release-lock lock))))
     (bordeaux-threads:make-thread (writer "Enjoy"))
     (bordeaux-threads:make-thread (writer "Rosetta"))
     (bordeaux-threads:make-thread (writer "Code")))))</lang>

D

Library: Tango

<lang d>import tango.core.Thread; import tango.io.Console; import tango.math.Random;

void main() {

   (new Thread( { Thread.sleep(Random.shared.next(1000) / 1000.0); Cout("Enjoy").newline; } )).start;
   (new Thread( { Thread.sleep(Random.shared.next(1000) / 1000.0); Cout("Rosetta").newline; } )).start;
   (new Thread( { Thread.sleep(Random.shared.next(1000) / 1000.0); Cout("Code").newline; } )).start;

}</lang>

dodo0

<lang dodo0>fun parprint -> text, return (

  fork() -> return, throw
     println(text, return)
  | x
  return()

) | parprint

parprint("Enjoy") -> parprint("Rosetta") -> parprint("Code") ->

exit()</lang>

E

<lang e>def base := timer.now() for string in ["Enjoy", "Rosetta", "Code"] {

   timer <- whenPast(base + entropy.nextInt(1000), fn { println(string) })

}</lang>

Nondeterminism from preemptive concurrency rather than a random number generator:

<lang e>def seedVat := <import:org.erights.e.elang.interp.seedVatAuthor>(<unsafe>) for string in ["Enjoy", "Rosetta", "Code"] {

  seedVat <- (`
      fn string {
          println(string)
          currentVat <- orderlyShutdown("done")
      }
  `) <- get(0) <- (string)

}</lang>

Erlang

hw.erl <lang erlang>-module(hw). -export([start/0]).

start() ->

  [ spawn(fun() ->  say(self(), X) end) || X <- ['Enjoy', 'Rosetta', 'Code'] ],
  wait(2),
  ok.

say(Pid,Str) ->

  io:fwrite("~s~n",[Str]),
  Pid ! done.

wait(N) ->

  receive
      done -> case N of
          0 -> 0;
          _N -> wait(N-1)
      end
  end.</lang>

running it <lang erlang>|erlc hw.erl |erl -run hw start -run init stop -noshell</lang>

F#

We define a parallel version of Seq.iter by using asynchronous workflows: <lang fsharp>module Seq =

   let piter f xs =
       seq { for x in xs -> async { f x } }
       |> Async.Parallel
       |> Async.RunSynchronously
       |> ignore

let main() = Seq.piter

               (System.Console.WriteLine:string->unit)
               ["Enjoy"; "Rosetta"; "Code";]

main()</lang>

With version 4 of the .NET framework and F# PowerPack 2.0 installed, it is possible to use the predefined PSeq.iter instead.

Factor

<lang factor>USE: concurrency.combinators

{ "Enjoy" "Rosetta" "Code" } [ print ] parallel-each</lang>

Forth

Works with: gforth version 0.6.2

Many Forth implementations come with a simple cooperative task scheduler. Typically each task blocks on I/O or explicit use of the pause word. There is also a class of variables called "user" variables which contain task-specific data, such as the current base and stack pointers.

<lang forth>require tasker.fs require random.fs

task ( str len -- )
 64 NewTask 2 swap pass
 ( str len -- )
 10 0 do
   100 random ms
   pause 2dup cr type
 loop 2drop ;
main
 s" Enjoy"   task
 s" Rosetta" task
 s" Code"    task
 begin pause single-tasking? until ;

main</lang>

Fortran

Fortran doesn't have threads but there are several compilers that support OpenMP, e.g. gfortran and Intel. The following code has been tested with thw Intel 11.1 compiler on WinXP.

<lang Fortran>program concurrency

 implicit none
 character(len=*), parameter :: str1 = 'Enjoy'
 character(len=*), parameter :: str2 = 'Rosetta'
 character(len=*), parameter :: str3 = 'Code'
 integer                     :: i
 real                        :: h
 real, parameter             :: one_third = 1.0e0/3
 real, parameter             :: two_thirds = 2.0e0/3
 interface
    integer function omp_get_thread_num
    end function omp_get_thread_num
 end interface
 interface
    integer function omp_get_num_threads
    end function omp_get_num_threads
 end interface
 ! Use OpenMP to create a team of threads
 !$omp parallel do private(i,h)
 do i=1,20
    ! First time through the master thread output the number of threads
    ! in the team
    if (omp_get_thread_num() == 0 .and. i == 1) then
       write(*,'(a,i0,a)') 'Using ',omp_get_num_threads(),' threads'
    end if
    ! Randomize the order
    call random_number(h)
    !$omp critical
    if (h < one_third) then
       write(*,'(a)') str1
    else if (h < two_thirds) then
       write(*,'(a)') str2
    else
       write(*,'(a)') str3
    end if
    !$omp end critical
 end do
 !$omp end parallel do

end program concurrency</lang>

Go

When main() exits, that's it. To ensure completion of the goroutines, it is necessary to wait for them. <lang go>package main

import (

   "log"
   "time"
   "os"
   "rand"
   "sync"

)

func main() {

   words := []string{"Enjoy", "Rosetta", "Code"}
   l := log.New(os.Stdout, "", 0)
   rand.Seed(time.Nanoseconds())
   var q sync.WaitGroup
   q.Add(len(words))
   for _, w := range words {
       go func(w string) {
           time.Sleep(rand.Int63n(1e9))
           l.Println(w)
           q.Done()
       }(w)
   }
   q.Wait()

}</lang>

Groovy

<lang groovy>'Enjoy Rosetta Code'.tokenize().collect { w ->

   Thread.start {
       Thread.sleep(1000 * Math.random() as int)
       println w
   }

}.each { it.join() }</lang>

Haskell

Note how the map treats the list of processes just like any other data.

<lang haskell>import Control.Concurrent

main = mapM_ forkIO [process1, process2, process3] where

 process1 = putStrLn "Enjoy" 
 process2 = putStrLn "Rosetta"
 process3 = putStrLn "Code"</lang>

J

Example:

<lang j> smoutput&>({~?~@#);:'Enjoy Rosetta Code' Rosetta Code Enjoy </lang>

NOTES AND CAUTIONS:

1) While J's syntax and semantics is highly parallel, it is a deterministic sort of parallelism (analogous to the design of modern GPUs) and not the stochastic parallelism which is implied in this task specification (and which is usually obtained by timeslicing threads of control). The randomness implemented here is orthogonal to the parallelism in the display (and you could remove smoutput& without altering the appearence, in this trivial example).

2) The current working beta of J (and the past implementations) do not implement hardware based concurrency. This is partially an economic issue (since all of the current and past language implementations have been distributed for free, with terms which allow free distribution), and partially a hardware maturity issue (historically, most CPU multi-core development has been optimized for stochastic parallelism with minimal cheap support for large scale deterministic parallelism and GPUs have not been capable of supporting the kind of generality needed by J).

This state of affairs is likely to change, eventually (most likely this will be after greater than factor of 2 speedups from hardware parallelism are available for the J users in cases which are common and important enough to support the implementation). But, for now, J's parallelism is entirely conceptual.

Java

Uses CyclicBarrier to force all threads to wait until they're at the same point before executing the println, increasing the odds they'll print in a different order (otherwise, while the they may be executing in parallel, the threads are started sequentially and with such a short run-time, will usually output sequentially as well).

<lang java>import java.util.concurrent.CyclicBarrier;

public class Threads {

 public static class DelayedMessagePrinter implements Runnable
 {
   private CyclicBarrier barrier;
   private String msg;
   
   public DelayedMessagePrinter(CyclicBarrier barrier, String msg)
   {
     this.barrier = barrier;
     this.msg = msg;
   }
   
   public void run()
   {
     try
     {  barrier.await();  }
     catch (Exception e)
     {  }
     System.out.println(msg);
   }
 }
 
 public static void main(String[] args)
 {
   CyclicBarrier barrier = new CyclicBarrier(3);
   new Thread(new DelayedMessagePrinter(barrier, "Enjoy")).start();
   new Thread(new DelayedMessagePrinter(barrier, "Rosetta")).start();
   new Thread(new DelayedMessagePrinter(barrier, "Code")).start();
 }

}</lang>

JavaScript

Works with: Firefox version 2.0

<lang javascript>var textbox = document.getElementsByTagName("textarea")[0]; setTimeout( function(){ textbox.value += "Enjoy\n"; }, Math.random() * 1000 ); setTimeout( function(){ textbox.value += "Rosetta\n"; }, Math.random() * 1000 ); setTimeout( function(){ textbox.value += "Code\n"; }, Math.random() * 1000 );</lang>

Logtalk

<lang logtalk>:- object(concurrency).

   :- initialization(output).
   output :-
       threaded((
           write('Enjoy'),
           write('Rosetta'),
           write('Code')
       )).
- end_object.</lang>

Lua

<lang lua>co = {} co[1] = coroutine.create( function() print "Enjoy" end ) co[2] = coroutine.create( function() print "Rosetta" end ) co[3] = coroutine.create( function() print "Code" end )

math.randomseed( os.time() ) h = {} i = 0 repeat

   j = math.random(3)
   if h[j] == nil then
      coroutine.resume( co[j] )
      h[j] = true
      i = i + 1
   end

until i == 3</lang>

Mathematica

Parallelization requires Mathematica 7 or later <lang Mathematica>ParallelDo[

   Pause[RandomReal[]];
   Print[s],
   {s, {"Enjoy", "Rosetta", "Code"}}

]</lang>

Objeck

<lang objeck> bundle Default {

 class MyThread from Thread {
   New(name : String) {
     Parent(name);
   }
   method : public : Run(param : Base) ~ Nil {
     string := param->As(String);
     string->PrintLine();
   }
 }
 class Concurrent {
   New() {
   }
   function : Main(args : System.String[]) ~ Nil {
     t0 := MyThread->New("t0");
     t1 := MyThread->New("t1");
     t2 := MyThread->New("t2");
     t0->Execute("Enjoy"->As(Base));
     t1->Execute("Rosetta"->As(Base));
     t2->Execute("Code"->As(Base));
   }
 }

} </lang>

OCaml

<lang ocaml>#directory "+threads"

  1. load "unix.cma"
  2. load "threads.cma"

let sleepy_print msg =

   Unix.sleep ( Random.int 4 );
   print_endline msg

let threads = List.map ( Thread.create sleepy_print ) ["Enjoy"; "Rosetta"; "Code"];; let () = List.iter ( Thread.join ) threads;;</lang>

Oz

The randomness comes from the unpredictability of thread scheduling (this is how I understand this exercise).

<lang oz>for Msg in ["Enjoy" "Rosetta" "Code"] do

  thread
     {System.showInfo Msg}
  end

end</lang>

Perl

<lang perl>use threads; use Time::HiRes qw(sleep);

$_->join for map {

   threads->create(sub {
       sleep rand;
       print shift, "\n";
   }, $_)

} qw(Enjoy Rosetta Code);</lang>

Perl 6

Works with: pugs

Hyper-operators are unordered: <lang perl6>my @words = <Enjoy Rosetta Code>; @words».say</lang> Output: <lang>Rosetta Code Enjoy</lang>

PicoLisp

Using background tasks

<lang PicoLisp>(for (N . Str) '("Enjoy" "Rosetta" "Code")

  (task (- N) (rand 1000 4000)              # Random start time 1 .. 4 sec
     Str Str                                # Closure with string value
     (println Str)                          # Task body: Print the string
     (task @) ) )                           # and stop the task</lang>

Using child processes

<lang PicoLisp>(for Str '("Enjoy" "Rosetta" "Code")

  (let N (rand 1000 4000)                   # Randomize
     (unless (fork)                         # Create child process
        (wait N)                            # Wait 1 .. 4 sec
        (println Str)                       # Print string
        (bye) ) ) )                         # Terminate child process</lang>

PureBasic

<lang PureBasic>Global mutex = CreateMutex()

Procedure Printer(*str$)

 LockMutex(mutex)
 PrintN(*str$)
 UnlockMutex(mutex)

EndProcedure

If OpenConsole()

 LockMutex(mutex)
 thread1 = CreateThread(@Printer(), @"Enjoy")
 thread2 = CreateThread(@Printer(), @"Rosetta")
 thread3 = CreateThread(@Printer(), @"Code")
 UnlockMutex(mutex)
 
 WaitThread(thread1)
 WaitThread(thread2)
 WaitThread(thread3)
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
 Input()
 
 CloseConsole()

EndIf

FreeMutex(mutex)</lang>

Python

Works with: Python version 2.5

<lang python>import threading import random

def echo(string):

   print string

threading.Timer(random.random(), echo, ("Enjoy",)).start() threading.Timer(random.random(), echo, ("Rosetta",)).start() threading.Timer(random.random(), echo, ("Code",)).start()</lang>

Or, by using a for loop to start one thread per list entry, where our list is our set of source strings:

<lang python>import threading import random

def echo(string):

   print string

for text in ["Enjoy", "Rosetta", "Code"]:

   threading.Timer(random.random(), echo, (text,)).start()</lang>

Raven

<lang raven>[ 'Enjoy' 'Rosetta' 'Code' ] as $words

thread talker

   $words pop "%s\n"
   repeat dup print
       500 choose ms

talker as a talker as b talker as c</lang>

Rhope

Works with: Rhope version alpha 1

<lang rhope>Main(0,0) |:

   Print["Enjoy"]
   Print["Rosetta"]
   Print["Code"]
|</lang>

In Rhope, expressions with no shared dependencies run in parallel by default.

Ruby

<lang ruby>%w{Enjoy Rosetta Code}.map do |x|

   Thread.new do
       sleep rand
       puts x
   end

end.each do |t|

 t.join

end</lang>

Scala

<lang scala>import scala.actors.Futures List("Enjoy", "Rosetta", "Code").map { x =>

   Futures.future {                           
     Thread.sleep((Math.random * 1000).toInt)   
      println(x)                                 
   }         

}.foreach(_())</lang>

Scheme

<lang scheme>(parallel-execute (lambda () (print "Enjoy"))

                 (lambda () (print "Rosetta"))
                 (lambda () (print "Code")))</lang>

Tcl

Assuming that "random" means that we really want the words to appear in random (rather then "undefined" or "arbitrary") order:

<lang tcl>after [expr int(1000*rand())] {puts "Enjoy"} after [expr int(1000*rand())] {puts "Rosetta"} after [expr int(1000*rand())] {puts "Code"}</lang>

will execute each line after a randomly chosen number (0...1000) of milliseconds.

A step towards "undefined" would be to use after idle, which is Tcl for "do this whenever you get around to it". Thus:

<lang tcl>after idle {puts "Enjoy"} after idle {puts "Rosetta"} after idle {puts "Code"}</lang>

(While no particular order is guaranteed by the Tcl spec, the current implementations will all execute these in the order in which they were added to the idle queue).

It's also possible to use threads for this. Here we do this with the built-in thread-pool support: <lang tcl>package require Thread set pool [tpool::create -initcmd {

   proc delayPrint msg {
       after [expr int(1000*rand())]
       puts $msg
   }

}] tpool::post -detached $pool [list delayPrint "Enjoy"] tpool::post -detached $pool [list delayPrint "Rosetta"] tpool::post -detached $pool [list delayPrint "Code"] tpool::release $pool after 1200 ;# Give threads time to do their work exit</lang>

UnixPipes

<lang bash>(echo "Enjoy" & echo "Rosetta"& echo "Code"&)</lang>

Visual Basic .NET

<lang vbnet>Imports System.Threading

Module Module1

  Public rnd As New Random
  Sub Main()
      Dim t1 As New Thread(AddressOf Foo)
      Dim t2 As New Thread(AddressOf Foo)
      Dim t3 As New Thread(AddressOf Foo)
      t1.Start("Enjoy")
      t2.Start("Rosetta")
      t3.Start("Code")
      t1.Join()
      t2.Join()
      t3.Join()
  End Sub
  Sub Foo(ByVal state As Object)
      Thread.Sleep(rnd.Next(1000))
      Console.WriteLine(state)
  End Sub

End Module</lang>