Next: , Previous: , Up: Tips and Tricks   [Contents][Index]


7.1 Using out-of-bound task IDs to simplify code

See Task descriptions, mentions a language feature that can substantially simplify coNCePTuaL programs: Operations involving out-of-bound task IDs are silently ignored. The beauty of this feature is that it reduces the need for special cases at network boundaries. Consider, for example, a simple pipeline pattern in which each task in turn sends a message to the subsequent task:

ALL TASKS t SEND A 64 DOUBLEWORD MESSAGE TO TASK t+1.

Because implicit receives are posted before the corresponding sends (see Sending), all tasks except task 0 start by posting a blocking receive. (No task is sending to task 0.) Task 0 is therefore free to send a message to task 1 . Receipt of that message unblocks task 1, who then sends a message to task 2, thereby unblocking task 3, and so forth. Without needing an explicit special case in the program, task ‘num_tasks-1’ receives a message from task ‘num_tasks-2’ but does not attempt to send a message to nonexistent task ‘num_tasks’, thanks to the rule that communication with nonexistent tasks turns into a no-op (i.e., is elided from the program).

As a more complex variation of the same program, consider a wavefront communication pattern that progresses from the upper-left corner of a mesh to the lower-right corner. Such a pattern can be expressed in just four lines of coNCePTuaL (receive left, receive up, send right, send down) by relying on the property that communication with a nonexistent task is simply not executed:

TASK MESH_NEIGHBOR(src, xsize, +1, ysize,  0) RECEIVES A
  64 DOUBLEWORD MESSAGE FROM ALL TASKS src THEN
TASK MESH_NEIGHBOR(src, xsize,  0, ysize, +1) RECEIVES A
  64 DOUBLEWORD MESSAGE FROM ALL TASKS src THEN
ALL TASKS src SEND A 64 DOUBLEWORD MESSAGE TO
  UNSUSPECTING TASK MESH_NEIGHBOR(src, xsize, +1, ysize,  0) THEN
ALL TASKS src SEND A 64 DOUBLEWORD MESSAGE TO
  UNSUSPECTING TASK MESH_NEIGHBOR(src, xsize,  0, ysize, +1).

To understand the preceding program recall that MESH_NEIGHBOR returns ‘-1’ for nonexistent neighbors. Because ‘-1’ is outside of the range [0, num_tasks) communication with a nonexistent neighbor is ignored. To help the reader understand the preceding program, we present a trace of the events it posts as it runs with a 2 by 2 arrangement of tasks:

[TRACE] phys: 0 | virt: 0 | action: SEND | event: 1 / 2 | lines: 3 - 3
[TRACE] phys: 1 | virt: 1 | action: RECV | event: 1 / 2 | lines: 1 - 1
[TRACE] phys: 2 | virt: 2 | action: RECV | event: 1 / 2 | lines: 2 - 2
[TRACE] phys: 3 | virt: 3 | action: RECV | event: 1 / 2 | lines: 1 - 1

[TRACE] phys: 0 | virt: 0 | action: SEND | event: 2 / 2 | lines: 4 - 4
[TRACE] phys: 1 | virt: 1 | action: SEND | event: 2 / 2 | lines: 4 - 4

[TRACE] phys: 2 | virt: 2 | action: SEND | event: 2 / 2 | lines: 3 - 3

[TRACE] phys: 3 | virt: 3 | action: RECV | event: 2 / 2 | lines: 2 - 2

The c_trace backend (see The c_trace backend) was used to produce that trace. To increase clarity, we manually added blank lines to group concurrent events (i.e., there is no significance to the order of the TRACE lines within each group). The important thing to notice is that there are exactly four receives and exactly four sends:

Because communication with nonexistent tasks is elided at program initialization time there is no run-time cost for such operations—as evidenced by the c_trace output presented above. Furthermore, there is no reliance on the backend to drop messages from nonexistent senders or to nonexistent receivers; it is perfectly safe to utilize no-op’ed communcation in any coNCePTuaL program and when using any backend.


Next: , Previous: , Up: Tips and Tricks   [Contents][Index]

Scott Pakin, pakin@lanl.gov