Next: Receiving, Previous: Message specifications, Up: Communication statements [Contents][Index]
The
SEND
statement is fundamental to coNCePTuaL. It is
used to send a multiple messages from multiple source tasks to
multiple target tasks. The syntax is formally specified as
follows:
<source_task> is described in Source tasks; <message_spec> and <recv_message_spec> are described in Message specifications; and, <target_tasks> is described in Target tasks.
The
SEND
statement’s simplest form, “
<source_task> SENDS
<message_spec> TO
<target_tasks>”, is fairly straightforward. The
following is a example:
TASK 0 SENDS A 0 BYTE MESSAGE TO TASK 1
The only subtlety in the preceding statement is that it
implicitly causes task 1 to perform a
corresponding receive. This receive can be suppressed by adding the
keyword UNSUSPECTING
before the
<target_tasks>
description:
TASK 0 SENDS A 0 BYTE MESSAGE TO UNSUSPECTING TASK 1
Here are some further examples of valid <send_stmt>s:
ALL TASKS SEND A 64 KILOBYTE MESSAGE TO TASK
0
TASK num_tasks-1 SENDS 5 53 BYTE PAGE ALIGNED MESSAGES TO
ALL OTHER TASKS
TASKS upper SUCH THAT upper>=num_tasks/2
ASYNCHRONOUSLY SEND A 0 BYTE MESSAGE TO TASK upper/2
TASKS nonzero SUCH THAT nonzero>0 SEND nonzero 1E3
BYTE MESSAGES TO UNSUSPECTING TASK 0
There are a number of attributes associated with every message transmission:
A few of those appear in the preceding examples.
When UNSUSPECTING
is omitted,
the implicit
RECEIVE
statement normally inherits all of the
attributes of the corresponding SEND
. However, the second form of
a
<send_stmt>, which contains a
WHO RECEIVES IT
(or WHO RECEIVES THEM
)
clause, enables the receiver’s attributes to be overridden on a
per-attribute basis. For instance, consider the following SEND
statement:
TASK 0 SENDS A 1 MEGABYTE MESSAGE TO TASK 1 WHO RECEIVES IT ASYNCHRONOUSLY
The alternative sequence of statements that does not use
WHO RECEIVES IT
is less straightforward to read
because it splits a single message transmission into two
statements:
TASK 1 ASYNCHRONOUSLY RECEIVES A 1 MEGABYTE MESSAGE FROM
TASK 0
TASK 0 SENDS A 1 MEGABYTE MESSAGE TO UNSUSPECTING TASK
1
Some further examples of WHO RECEIVES IT
follow:
TASKS left SUCH THAT left IS EVEN SEND 5 2 KILOBYTE 64 BYTE ALIGNED MESSAGES TO TASKS left+1 WHO RECEIVE THEM AS UNALIGNED MESSAGES WITH DATA TOUCHING TASK num_tasks-1 ASYNCHRONOUSLY SENDS A 1E5 BYTE MESSAGE WITH VERIFICATION TO TASK 0 WHO RECEIVES IT SYNCHRONOUSLY TASK leaf SUCH THAT KNOMIAL_CHILDREN(leaf,2)=0 SENDS A UNIQUE 1536 BYTE MESSAGE WITH DATA TOUCHING TO TASK KNOMIAL_PARENT(leaf,2) WHO RECEIVES IT ASYNCHRONOUSLY AS A NONUNIQUE QUADWORD ALIGNED MESSAGE WITHOUT DATA TOUCHING INTO BUFFER KNOMIAL_PARENT(leaf,2)
One subtlety of the SEND
statement when used without
UNSUSPECTING
involves the orderings of the sends and
receives. The rule is that receives are posted before sends.
Furthermore,
<restricted_ident>s (see Restricted
identifiers) are evaluated in order from 0
to num_tasks-1. The
implication is that a statement such as ‘TASKS ev SUCH THAT
ev IS EVEN /\ ev<6 SEND A 4 WORD MESSAGE TO TASK ev+2’ is
exactly equivalent to the following ordered sequence of statements
(assuming num_tasks >= 5):
TASK 2 RECEIVES A 4 WORD MESSAGE FROM TASK 0
TASK 4 RECEIVES A 4 WORD MESSAGE FROM TASK 2
TASK 6 RECEIVES A 4 WORD MESSAGE FROM TASK 4
TASK 0 SENDS A 4 WORD MESSAGE TO UNSUSPECTING TASK
2
TASK 2 SENDS A 4 WORD MESSAGE TO UNSUSPECTING TASK
4
TASK 4 SENDS A 4 WORD MESSAGE TO UNSUSPECTING TASK
6
(The
RECEIVE
statement is described in Receiving.)
If the above sequence were executed, tasks 2, 4, and 6 would immediately block on their receives (steps 1–3) . Task 0 would awaken task 2 by sending it a message (step 4). Then, task 2 would be able to continue to step 5 at which point it would send a message to task 4. Task 4 would then finally be able to send a message to task 6 (step 6). Hence, even though the original coNCePTuaL statement encapsulates multiple communication operations, the component communications proceed sequentially because of data dependences and because the operations are blocking.
As another example of send/receive ordering, consider the statement, ‘TASKS x SUCH THAT x IS IN {1,4,5} SEND A 768 BYTE MESSAGE FROM 4 DOUBLEWORDS INTO THE DEFAULT BUFFER TO TASKS y SUCH THAT y IS IN {6,2,3}’. This statement causes nine messages to be sent and received and in the following order: 1 ⇒ 2 , 1 ⇒ 3, 1 ⇒ 6 , 4 ⇒ 2, 4 ⇒ 3 , 4 ⇒ 6, 5 ⇒ 2 , 5 ⇒ 3, 5 ⇒ 6 . The reason that task 6 receives from each sender after tasks 2 and 3 relates to the comment above that <restricted_ident>s are evaluated in order from 0 to num_tasks-1 . One can therefore think of the preceding coNCePTuaL statement as being implemented with the following pseudocode:
for s := 0 to num_tasks-1 do if s is in {1, 4, 5} then for r := 0 to num_tasks-1 do if r is in {6, 2, 3} then r receives from s for s := 0 to num_tasks-1 do if s is in {1, 4, 5} then for r := 0 to num_tasks-1 do if r is in {6, 2, 3} then s sends to r
Next: Receiving, Previous: Message specifications, Up: Communication statements [Contents][Index]