Hi Kasia,
Looking at ptolemy/domains/pn/kernel/PNDirector.java, I believe that the
algorithm works
on a per-receiver basis, so it should block only when there is no data
on all the channels of
a multiport. Edward might have some input here, but that is my
understanding.
See also the PN chapter in
"Heterogeneous Concurrent Modeling and Design in Java (Volume 3: Ptolemy
II Domains)" at
http://www.eecs.berkeley.edu/Pubs/TechRpts/2008/EECS-2008-37.html
There are some tests that involve multiports with width greater than 1 in
ptolemy/domains/pn/test/auto/WidthInferenceTest*.xml
I've attached a model that has a Const and a Ramp going to a Commutator.
The Const has its firingCountLimit set to 1.
The Ramp has its firingCountLimit set to 50 because if firingCountLimit
is set to NONE,
then the PN Director will throw
ptolemy.kernel.util.IllegalActionException: Queue size 131072 exceeds
the maximum capacity in port .PNMultiport.Commutator.input. Perhaps you
have an unbounded queue?
in .PNMultiport.PN Director
at
ptolemy.domains.pn.kernel.PNDirector._incrementLowestWriteCapacityPort(PNDirector.java:482)
at
ptolemy.domains.pn.kernel.PNDirector._resolveInternalDeadlock(PNDirector.java:549)
at
ptolemy.actor.process.CompositeProcessDirector._resolveDeadlock(CompositeProcessDirector.java:719)
at ptolemy.actor.process.ProcessDirector.fire(ProcessDirector.java:259)
at ptolemy.actor.CompositeActor.fire(CompositeActor.java:458)
at ptolemy.actor.Manager.iterate(Manager.java:742)
at ptolemy.actor.Manager.execute(Manager.java:351)
at ptolemy.actor.Manager.run(Manager.java:1111)
at ptolemy.actor.Manager$PtolemyRunThread.run(Manager.java:1641)
I modified the development version of PNDirector to indicate which port
is causing the problem
and it looks like what happens when firingCountLimit is NONE is that the
Ramp produces
data and the Commutator fails to read from the Ramp because there is no
token on the
channel connected to the Const port.
Commutator's fire() method indicates what happens when data is not
available:
/** Read <i>blockSize</i> tokens from each input channel and send them
* to the output port. If an input channel does not have enough
* tokens, suspend firing
* and return. In this case, the actor makes a record of the
* input channel that it last attempted to read so that it can
* start reading at that channel in the next iteration. The
* order in which the tokens are produced is the order of the
* channels in the input port.
*
* @exception IllegalActionException If there is no director.
*/
public void fire() throws IllegalActionException {
super.fire();
_tentativeInputPosition = _currentInputPosition;
int width = input.getWidth();
int blockSizeValue = ((IntToken) blockSize.getToken()).intValue();
for (int i = 0; i < width; i++) {
if (!input.hasToken(_tentativeInputPosition, blockSizeValue)) {
break;
}
Token[] inputs = input.get(_tentativeInputPosition++,
blockSizeValue);
output.send(0, inputs, blockSizeValue);
if (_tentativeInputPosition >= width) {
_tentativeInputPosition = 0;
}
}
}
A better answer to your question might be: The Ptolemy II PNDirector
works on a per-channel
basis, so a multiport blocks on a per-channel basis, but it depends on
how the actor
is written. Most actors expect data on each channel and read
sequentially. Some actors,
such as NondeterministicMerge read from channels that have data and skip
channels
that do not have data.
See PNMultiportNondeterministicMerge.xml for a model that has the Const with
a firingCountLimit of 1 and the Ramp with a firingCountLimit of 50.
Note that PN cannot handle a relation with multiple sources connected to
the relation.
PNDirector says:
/** Override the base class to reset the capacities of all the
receivers.
* @exception IllegalActionException If the superclass throws it.
*/
public void preinitialize() throws IllegalActionException {
super.preinitialize();
// Check that no relation has multiple sources of data
connected to it.
// FIXME: This only detects the error at this level of the
hierarchy.
// Probably need to recursively descend into composite actors.
CompositeEntity container = (CompositeEntity) getContainer();
Iterator relations = container.relationList().iterator();
while (relations.hasNext()) {
IORelation relation = (IORelation) relations.next();
if (relation.linkedSourcePortList().size() > 1) {
throw new IllegalActionException(relation,
"Relation has multiple sources of data,"
+ " which is not allowed in PN."
+ " If you want nondeterministic merge,"
+ " use the NondeterministicMerge actor.");
}
}
...
_Christopher
On 9/15/11 7:50 AM, Katarzyna Bylec wrote:
Hello,
I'm working on some problem from PN domain and while designing the
solution I'd like to make it clear what's the blocking algorithm
concerning multiports.
I more detail - I have a multiport input. Does the containing actor
write blocks when there's no data on the channel it tries to read from
or can it move to another channel in this port and blocks only when
there's no data in all channels?
Regards,
Kasia
--
Christopher Brooks, PMP University of California
CHESS Executive Director US Mail: 337 Cory Hall
Programmer/Analyst CHESS/Ptolemy/Trust Berkeley, CA 94720-1774
ph: 510.643.9841 (Office: 545Q Cory)
home: (F-Tu) 707.665.0131 cell: 707.332.0670
<?xml version="1.0" standalone="no"?>
<!DOCTYPE entity PUBLIC "-//UC Berkeley//DTD MoML 1//EN"
"http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd">
<entity name="PNMultiport" class="ptolemy.actor.TypedCompositeActor">
<property name="_createdBy" class="ptolemy.kernel.attributes.VersionAttribute" value="8.1.devel">
</property>
<property name="PN Director" class="ptolemy.domains.pn.kernel.PNDirector">
<property name="_location" class="ptolemy.kernel.util.Location" value="[80.0, 65.0]">
</property>
</property>
<property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={0, 30, 1438, 519}, maximized=false}">
</property>
<property name="_vergilSize" class="ptolemy.actor.gui.SizeAttribute" value="[1225, 409]">
</property>
<property name="_vergilZoomFactor" class="ptolemy.data.expr.ExpertParameter" value="1.0">
</property>
<property name="_vergilCenter" class="ptolemy.data.expr.ExpertParameter" value="{612.5, 204.5}">
</property>
<property name="Annotation" class="ptolemy.vergil.kernel.attributes.TextAttribute">
<property name="text" class="ptolemy.kernel.util.StringAttribute" value="The Ramp Actor has its firingCountLimit set to 50 so as to avoid an exception in PNDirector.">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[20.0, 255.0]">
</property>
</property>
<entity name="Const" class="ptolemy.actor.lib.Const">
<property name="firingCountLimit" class="ptolemy.data.expr.Parameter" value="1">
</property>
<property name="value" class="ptolemy.data.expr.Parameter" value="{"a1", "a2", "a3", "a4"}">
</property>
<doc>Create a constant sequence.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="60">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[125.0, 120.0]">
</property>
</entity>
<entity name="ArrayToSequence" class="ptolemy.domains.sdf.lib.ArrayToSequence">
<property name="enforceArrayLength" class="ptolemy.data.expr.Parameter" value="false">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[260.0625, 120.0]">
</property>
</entity>
<entity name="SequenceToArray" class="ptolemy.domains.sdf.lib.SequenceToArray">
<property name="arrayLength" class="ptolemy.actor.parameters.PortParameter" value="4">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="{625.0, 115.0}">
</property>
</entity>
<entity name="Commutator" class="ptolemy.actor.lib.Commutator">
<property name="_location" class="ptolemy.kernel.util.Location" value="[440.0, 190.0]">
</property>
</entity>
<entity name="Distributor" class="ptolemy.actor.lib.Distributor">
<property name="blockSize" class="ptolemy.data.expr.Parameter" value="4">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[525.0, 190.0]">
</property>
</entity>
<entity name="ArrayToSequence2" class="ptolemy.domains.sdf.lib.ArrayToSequence">
<property name="enforceArrayLength" class="ptolemy.data.expr.Parameter" value="false">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[260.0, 180.0]">
</property>
</entity>
<entity name="SequenceToArray2" class="ptolemy.domains.sdf.lib.SequenceToArray">
<property name="arrayLength" class="ptolemy.actor.parameters.PortParameter" value="4">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[635.0, 175.0]">
</property>
</entity>
<entity name="Ramp" class="ptolemy.actor.lib.Ramp">
<property name="firingCountLimit" class="ptolemy.data.expr.Parameter" value="NONE">
</property>
<property name="init" class="ptolemy.data.expr.Parameter" value="{1,2,3,4}">
</property>
<property name="step" class="ptolemy.actor.parameters.PortParameter" value="{1,10,100,1000}">
</property>
<doc>Create a sequence of tokens with increasing value</doc>
<property name="_location" class="ptolemy.kernel.util.Location" value="[85.0, 185.0]">
</property>
</entity>
<entity name="Display" class="ptolemy.actor.lib.gui.Display">
<property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={598, 421, 484, 208}, maximized=false}">
</property>
<property name="_paneSize" class="ptolemy.actor.gui.SizeAttribute">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[800.0, 100.0]">
</property>
</entity>
<entity name="Display2" class="ptolemy.actor.lib.gui.Display">
<property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={1116, 214, 484, 208}, maximized=false}">
</property>
<property name="_paneSize" class="ptolemy.actor.gui.SizeAttribute">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[803.75, 171.796875]">
</property>
</entity>
<relation name="relation" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation2" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation7" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation8" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation11" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation12" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation4" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation3" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation5" class="ptolemy.actor.TypedIORelation">
</relation>
<link port="Const.output" relation="relation"/>
<link port="ArrayToSequence.input" relation="relation"/>
<link port="ArrayToSequence.output" relation="relation7"/>
<link port="SequenceToArray.input" relation="relation11"/>
<link port="SequenceToArray.output" relation="relation3"/>
<link port="Commutator.input" relation="relation7"/>
<link port="Commutator.input" relation="relation8"/>
<link port="Commutator.output" relation="relation2"/>
<link port="Distributor.input" relation="relation2"/>
<link port="Distributor.output" relation="relation11"/>
<link port="Distributor.output" relation="relation12"/>
<link port="ArrayToSequence2.input" relation="relation4"/>
<link port="ArrayToSequence2.output" relation="relation8"/>
<link port="SequenceToArray2.input" relation="relation12"/>
<link port="SequenceToArray2.output" relation="relation5"/>
<link port="Ramp.output" relation="relation4"/>
<link port="Display.input" relation="relation3"/>
<link port="Display2.input" relation="relation5"/>
</entity>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE entity PUBLIC "-//UC Berkeley//DTD MoML 1//EN"
"http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd">
<entity name="PNMultiportNondeterministicMerge" class="ptolemy.actor.TypedCompositeActor">
<property name="_createdBy" class="ptolemy.kernel.attributes.VersionAttribute" value="8.1.devel">
</property>
<property name="PN Director" class="ptolemy.domains.pn.kernel.PNDirector">
<property name="_location" class="ptolemy.kernel.util.Location" value="[80.0, 65.0]">
</property>
</property>
<property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={0, 30, 1438, 519}, maximized=false}">
</property>
<property name="_vergilSize" class="ptolemy.actor.gui.SizeAttribute" value="[1225, 409]">
</property>
<property name="_vergilZoomFactor" class="ptolemy.data.expr.ExpertParameter" value="1.0">
</property>
<property name="_vergilCenter" class="ptolemy.data.expr.ExpertParameter" value="{612.5, 204.5}">
</property>
<property name="Annotation" class="ptolemy.vergil.kernel.attributes.TextAttribute">
<property name="text" class="ptolemy.kernel.util.StringAttribute" value="The Ramp Actor has its firingCountLimit set to 50 so as to avoid an exception in PNDirector.">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[20.0, 255.0]">
</property>
</property>
<entity name="Const" class="ptolemy.actor.lib.Const">
<property name="firingCountLimit" class="ptolemy.data.expr.Parameter" value="1">
</property>
<property name="value" class="ptolemy.data.expr.Parameter" value="{"a1", "a2", "a3", "a4"}">
</property>
<doc>Create a constant sequence.</doc>
<property name="_icon" class="ptolemy.vergil.icon.BoxedValueIcon">
<property name="attributeName" class="ptolemy.kernel.util.StringAttribute" value="value">
</property>
<property name="displayWidth" class="ptolemy.data.expr.Parameter" value="60">
</property>
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[125.0, 120.0]">
</property>
</entity>
<entity name="ArrayToSequence" class="ptolemy.domains.sdf.lib.ArrayToSequence">
<property name="enforceArrayLength" class="ptolemy.data.expr.Parameter" value="false">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[260.0625, 120.0]">
</property>
</entity>
<entity name="ArrayToSequence2" class="ptolemy.domains.sdf.lib.ArrayToSequence">
<property name="enforceArrayLength" class="ptolemy.data.expr.Parameter" value="false">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[260.0, 180.0]">
</property>
</entity>
<entity name="Display" class="ptolemy.actor.lib.gui.Display">
<property name="_windowProperties" class="ptolemy.actor.gui.WindowPropertiesAttribute" value="{bounds={598, 421, 484, 208}, maximized=false}">
</property>
<property name="_paneSize" class="ptolemy.actor.gui.SizeAttribute" value="[484, 164]">
</property>
<property name="_location" class="ptolemy.kernel.util.Location" value="[725.0, 145.0]">
</property>
</entity>
<entity name="Ramp" class="ptolemy.actor.lib.Ramp">
<property name="firingCountLimit" class="ptolemy.data.expr.Parameter" value="20">
</property>
<property name="init" class="ptolemy.data.expr.Parameter" value="{1,2,3,4}">
</property>
<property name="step" class="ptolemy.actor.parameters.PortParameter" value="{1,10,100,1000}">
</property>
<doc>Create a sequence of tokens with increasing value</doc>
<property name="_location" class="ptolemy.kernel.util.Location" value="[85.0, 185.0]">
</property>
</entity>
<entity name="NondeterministicMerge" class="ptolemy.domains.pn.kernel.NondeterministicMerge">
<property name="_location" class="ptolemy.kernel.util.Location" value="[490.0, 150.0]">
</property>
</entity>
<relation name="relation" class="ptolemy.actor.TypedIORelation">
<property name="width" class="ptolemy.data.expr.Parameter" value="-1">
</property>
</relation>
<relation name="relation4" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation6" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation7" class="ptolemy.actor.TypedIORelation">
</relation>
<relation name="relation2" class="ptolemy.actor.TypedIORelation">
</relation>
<link port="Const.output" relation="relation"/>
<link port="ArrayToSequence.input" relation="relation"/>
<link port="ArrayToSequence.output" relation="relation6"/>
<link port="ArrayToSequence2.input" relation="relation4"/>
<link port="ArrayToSequence2.output" relation="relation7"/>
<link port="Display.input" relation="relation2"/>
<link port="Ramp.output" relation="relation4"/>
<link port="NondeterministicMerge.input" relation="relation6"/>
<link port="NondeterministicMerge.input" relation="relation7"/>
<link port="NondeterministicMerge.output" relation="relation2"/>
</entity>
_______________________________________________
Kepler-users mailing list
Kepler-users@kepler-project.org
http://lists.nceas.ucsb.edu/kepler/mailman/listinfo/kepler-users