curently I call it like :
X procA
Y procA
Z porcA
procA takes a long time to execute.
Since X,Y and Z are independant, I want them to execute them in
parallel on X, Y and Z.
I want a generic API like do_parallel ( procA {X,Y,Z} ) or similar.
Kindly suggest how I can achieve this.
Thanks
> I have 2 procs procA and ProcB. These procs run on devices X,Y and Z.
>
> curently I call it like :
>
> X procA
> Y procA
> Z porcA
>
> procA takes a long time to execute.
> Since X,Y and Z are independant, I want them to execute them in
> parallel on X, Y and Z.
>
> I want a generic API like do_parallel ( procA {X,Y,Z} ) or similar.
Ashwin,
please describe your problem in a way there is a chance of understanding
it. Does the Tcl program run on each of the devices? Or on a central
computer talking to the devices?
I'll assume that the program runs on one computer and talks to the
devices X, Y and Z attached to it.
Do the devices talk to the computer while procA is running?
You might start three instances of the program, each talking to one
device and let your OS do the scheduling for you (that's what OSes are
for, after all). What would be the drawbacks of such an approach *in
your specific case*?
Then, of course, if running several instances of the program is out (for
what reasons?), you might resort to asynchronous I/O (look up the
documentation for fileevent). But I am making too many assumptions, so I
might be totally wrong on what your needs are.
Regards
-- tomás
Hi Ashwin Tech,
you can use threads or processes. In general you can use files, pipes or
sockets to communicate between processes and threads. If you use threads
then you can use tcl variables.
A possible thread based solution might be the following snippet.
Greetings Göran
--------------------------------------------------------------------------
proc procA device {
# procA - do something with device
# this is a demo function: it waits between 1 an 10 seconds
# and returns the device and the waiting time
set delay [expr {1000 * int (10*rand ()+1)}]
after $delay
return "$device: $delay"
}
proc do_parallel {procname devlist} {
# do_parallel - generic procedure that involve the proc "procname"
# with every argument in devlist in a separate thread
package require Thread
foreach dev $devlist {
set ::tid($dev) [thread::create { thread::wait } ]
thread::send $::tid($dev) \
[list proc $procname [info args $procname] \
[info body $procname] ]
thread::send -async $::tid($dev) [list $procname $dev]
::result($dev)
trace add variable ::result($dev) write printResults
}
}
proc printResults {name1 name2 op} {
# printResults - simple trace function that prints the results
if {$name2 == ""} {
set varname $name1
} {
set varname [format %s(%s) $name1 $name2]
}
puts `[set $varname]`
}
do_parallel procA [list X Y Z]
vwait forever
Since interpreters aren't shared across threads (let alone processes)
you have to do a little work. If it's easy to replicate the code
(e.g., because you can just [source] it from a file) then your best
bet is to just use a thread pool or something like that:
package require Thread
set operands [list X Y Z]
set workerSource "worker.tcl"
# Construct the thread pool
set pool [tpool::create -maxworkers [llength $operands] \
-initcmd [list source $workerSource]]
# Start the workers
foreach operand $operands {
lappend jobs [tpool::post -nowait $pool [list procA $operand]
}
# Wait for everything to finish
while {[llength $jobs]} {
tpool::wait $pool $jobs jobs
# Assume we don't need to pick up the results; if we did,
# we'd do so here for the *finished* jobs with ids returned
# by [tpool::wait]...
}
# Clean up
tpool::release $pool
There's documentation for the thread pool code at:
http://tcl.cvs.sourceforge.net/viewvc/tcl/thread/doc/html/tpool.html
Donal.