[Stackless] Scheduling Examples, Problems, Solutions, and Questions
Andrew Francis
andrewfr_ice at yahoo.com
Tue Dec 13 21:24:06 CET 2005
Hello Colleagues:
Perhaps these should go in a Wiki .....
I have been using channels to implement an order
dependency graph. I have run into problems and I have
found solutions. However I would like to know more
about what is happening.
The following code tries to impose a logical order on
some tasklets.
I expect the following execution trace
(A | B) C (D | E) F
| - means processes can execute in parallel.
It is okay to see B finish before A. However it is
wrong to see C finish before B and A finish.
Note, there are no cycles....
In this model, dependencies are implemened through
channels.
Say activity A and activity B share a channel "AtoB."
If channel "AtoB" is a target channel of B, this means
B cannot continue until it receives output. If channel
"AtoB" is a source of A, then A should send input
before finishing.
Here is a programme:
import stackless
class TestActivity(object):
# sources - hashTable of input channels
# targets - hashTable of output channels
def __init__(self, name, sources, targets):
self.sources = sources
self.targets = targets
self.name = name
def execute(self):
print self.name, " about to Join"
for target in self.targets:
print self.name, "joining ", target
self.targets[target].receive()
print self.name, "--joined-- ", target
print self.name, "finished joining"
print self.name, "*** finished Executing ***"
print self.name, "about to update dependents"
for source in self.sources:
print self.name, "updating ", source
self.sources[source].send(True)
print self.name, "finishing"
class StacklessTests(object):
def TestOne(self):
channelAtoC = stackless.channel()
channelBtoC = stackless.channel()
channelCtoD = stackless.channel()
channelCtoE = stackless.channel()
channelDtoF = stackless.channel()
channelEtoF = stackless.channel()
a = TestActivity("A", {"AtoC":channelAtoC},{})
b = TestActivity("B", {"BtoC":channelBtoC},{})
c = TestActivity("C", {"CtoD":channelCtoD,
"CtoE":channelCtoE}, \
{"AtoC":channelAtoC,
"BtoC":channelBtoC})
d = TestActivity("D", {"DtoF":channelDtoF},
{"CtoD":channelCtoD})
e = TestActivity("E", {"EtoF":channelEtoF},
{"CtoE":channelCtoE})
f = TestActivity("F", {},
{"EtoF":channelEtoF,"DtoF":channelDtoF})
stackless.tasklet(f.execute)()
stackless.tasklet(e.execute)()
stackless.tasklet(d.execute)()
stackless.tasklet(b.execute)()
stackless.tasklet(c.execute)()
stackless.tasklet(a.execute)()
print "--WAITING--"
stackless.run()
print "--FINISHED WAITING--"
test = StacklessTests()
test.TestOne()
This is the result as I expected. Note I print
"finished" after they finished receiving input and
before activities updating their dependents. This is
okay.
--WAITING--
F about to Join
F joining EtoF
E about to Join
E joining CtoE
D about to Join
D joining CtoD
B about to Join
B finished joining
B *** finished Executing ***
B about to update dependents
B updating BtoC
C about to Join
C joining AtoC
A about to Join
A finished joining
A *** finished Executing ***
A about to update dependents
A updating AtoC
C --joined-- AtoC
C joining BtoC
C --joined-- BtoC
C finished joining
C *** finished Executing ***
C about to update dependents
C updating CtoD
D --joined-- CtoD
D finished joining
D *** finished Executing ***
D about to update dependents
D updating DtoF
A finishing
B finishing
C updating CtoE
E --joined-- CtoE
E finished joining
E *** finished Executing ***
E about to update dependents
E updating EtoF
F --joined-- EtoF
F joining DtoF
F --joined-- DtoF
F finished joining
F *** finished Executing ***
F about to update dependents
F finishing
C finishing
E finishing
D finishing
--FINISHED WAITING--
Now, in the second test, I complicate things by adding
an
additional channel between B and E
b = TestActivity("B",
{"BtoC":channelBtoC,"BtoE":channelBtoE},\
{})
e = TestActivity("E",
{"EtoF":channelEtoF},{"CtoE":channelCtoE,\
"BtoE":channelBtoE})
The trace should remain the same. However I get the
following:
--WAITING--
F about to Join
F joining EtoF
E about to Join
E joining CtoE
D about to Join
D joining CtoD
B about to Join
B finished joining
B *** finished Executing ***
B about to update dependents
B updating BtoE
C about to Join
C joining AtoC
A about to Join
A finished joining
A *** finished Executing ***
A about to update dependents
A updating AtoC
C --joined-- AtoC
C joining BtoC
A finishing
--FINISHED WAITING--
~
This is wrong. I don't understand why the programme
ends while
tasklets still should be running.
I think what is happening is when Activity B updates
BtoC,
B is scheduled to the end. When C reads "AtoC", it is
rescheduled to the end of the list. However E should
be in a position to re-activate B and C.
I would like to know what exactly is happening.
~
Now what is interesting is when I change the stackless
channel to Asgeir Ingvarsson's uthread Queue, the
problem disappears. I get the proper trace. Asgeir's
uthread module is a great source of stackless
knowledge.
--WAITING--
F about to Join
F joining EtoF
E about to Join
E joining CtoE
D about to Join
D joining CtoD
B about to Join
B finished joining
B *** finished Executing ***
B about to update dependents
B updating BtoE
B updating BtoC
B finishing
C about to Join
C joining AtoC
A about to Join
A finished joining
A *** finished Executing ***
A about to update dependents
A updating AtoC
C --joined-- AtoC
C joining BtoC
C --joined-- BtoC
C finished joining
C *** finished Executing ***
C about to update dependents
C updating CtoD
D --joined-- CtoD
D finished joining
D *** finished Executing ***
D about to update dependents
D updating DtoF
D finishing
A finishing
C updating CtoE
E --joined-- CtoE
E joining BtoE
E --joined-- BtoE
E finished joining
E *** finished Executing ***
E about to update dependents
E updating EtoF
F --joined-- EtoF
F joining DtoF
F --joined-- DtoF
F finished joining
F *** finished Executing ***
F about to update dependents
F finishing
C finishing
E finishing
--FINISHED WAITING--
I am not quite sure why Asgeir's code solves problem.
More
specifically why the pump() method acts allows to the
Queue
to seemingly not block.
Cheers,
Andrew
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless
More information about the Stackless
mailing list