TOPC_raw_XXX
There are instances when tasks are most naturally generated deep
inside nested loops. Often, this occurs in parallelizing existing
sequential applications.
In such circumstances, it may be difficult to
re-write the code to create a function GenerateTaskInput()
, since
that would require turning the loops inside out. (If you don't know what this
refers to, then you probably don't need "raw_master_slave".)
On a first reading, you may wish to first look at the example for either a `for' loop or `while' loop, depending on the type of loop that you are parallelizing. Then return to the formal descriptions of the `TOP-C' raw functions. This chapter assumes familiarity with the basic concepts of section Overview of `TOP-C/C++' and section Writing `TOP-C' Applications.
TOPC_raw_submit_task_input(input)
serving
the role of GenerateTaskInput()
. The slave blocks inside
TOPC_raw_begin_master_slave()
and executes do_task() and
update_shared_data() until the master executes
TOPC_raw_end_master_slave()
. At that time, the slave
unblocks. The slave does nothing inside
TOPC_raw_end_master_slave()
.
TOPC_raw_begin_master_slave()
and TOPC_raw_end_master_slave()
; Typical usage is:
TOPC_raw_submit_task_input(TOPC_MSG(&input_data,
sizeof(input_data)) );
The argument, input, corresponds to what would be returned by
GenerateTaskInput()
in the routine TOPC_master_slave()
.
input will be processed by DoTask()
and its siblings,
just as in TOPC_master_slave()
).
There can be multiple occurrences of
TOPC_raw_submit_task_input()
.
TOPC_raw_begin_master_slave()
and
TOPC_raw_end_master_slave()
;
If no tasks are outstanding, returns false immediately. Otherwise, it
blocks until a task does return. It calls aplication
callback, CheckTaskResult()
, and then returns true.
Assume that we are parallelizing a code fragment of the following form.
The variables i
and j
will be the input to
DoTask()
, and any data structures indexed by i
and
j
(for example array
in array[i][j]
) will be
part of the shared data.
for ( i = 0; i < 10; i++ ) { for ( j = 0; j < 10; j++ ) { do_task: ... update: array[i][j] = ...; } }
Assume that the labels do_task
and update
above
correspond to the callback functions DoTask()
and
UpdateSharedData()
. Then the code is parallelized below.
typedef struct {int i_val; int j_val;} input_t; void *DoTask(input_t *buf) { int i = (*buf).i_val, j = (*buf).j_val; ... } main(int argc, char **argv) { TOPC_init( &argc, &argv ); TOPC_raw_begin_master_slave(DoTask, CheckTaskResult, UpdateSharedData); { for ( i = 0; i < 10; i++ ) { { for ( j = 0; j < 10; j++ ) { input_t input; input.i_val = i; input.j_val = j; TOPC_raw_submit_task_input( TOPC_MSG(&input, sizeof(input)) ); } } TOPC_raw_end_master_slave(); TOPC_finalize(); }
Assume that we are parallelizing a code fragment of the following form
and input
is a pointer.
while ( (input = next_input()) != NULL ) { do_task: ... update: ... }
Assume that the labels do_task
and update
above
correspond to the callback functions DoTask()
and
UpdateSharedData()
. Then the code is parallelized below,
where input_size
must be specified by the application before it
is used.
TOPC_init( &argc, &argv ); TOPC_raw_begin_master_slave(DoTask, CheckTaskResult, UpdateSharedData); { while ( (input = next_input()) != NULL || TOPC_raw_wait_for_task_result() ) { TOPC_raw_submit_task_input( TOPC_MSG(input, input_size) ); } } TOPC_raw_end_master_slave(); TOPC_finalize();
Note that the code inside the raw begin/end block is executed only by the master. Hence, any shared data between master and slave must be declared outside of the raw begin/end block. See section Local Shared Data, for a relevant example.
If the buffer, input
, contains pointers to other data, then you
will need to marshal the data before calling TOPC_MSG()
.
See section Marshalling Indirect Pointers into `TOP-C' Task Buffers.
Go to the first, previous, next, last section, table of contents.