#!F-adobe-helvetica-medium-r-normal--18*
#!N 
#!CNavyBlue #!N  #!Rexmodp A Parallel Version of the Add Module 
#!N #!EC #!N #!N The Add module created in the example 
in  #!Laddmodx,dxall1028 h Add Module Example--Add a Number to Every Data Value  #!EL  would work correctly on partitioned data because the code 
generated by the Module Builder automatically provides recursive traversal. However, it 
would not run in parallel on a parallel-architecture machine. To create 
an "addparallel" module, copy the following files to the directory you 
want to work in: #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N  #!F-adobe-times-bold-r-normal--18*   /opt/local/dx/samples/program_guide/Makefile_ 
#!EF  #!F-adobe-times-bold-i-normal--18*   workstation #!EF #!N  #!F-adobe-times-bold-r-normal--18*   /opt/local/dx/samples/program_guide/add_parallel.c #!EF #!N  #!F-adobe-times-bold-r-normal--18*   /opt/local/dx/samples/program_guide/addpar.mdf 
#!EF #!EF #!N #!N #!EC Now rename the makefile to  #!F-adobe-times-bold-r-normal--18*   
Makefile #!EF and enter make add_par. #!N #!N To run this 
module in Data Explorer (from the directory to which the files 
were copied), enter: #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N dx -edit -mdf 
./addpar.mdf -exec ./dxexec #!EF #!N #!N #!EC #!N #!N This command 
starts Data Explorer (the  #!F-adobe-times-bold-r-normal--18*   addpar.mdf #!EF file tells the graphical 
user interface about AddParallel and its inputs and outputs). #!N #!N 
You can now run any visual program that uses the AddParallel 
module. One such program is  #!F-adobe-times-bold-r-normal--18*   /opt/local/dx/samples/program_guide/add_parallel.net #!EF . #!N #!N 
The AddParallel module: #!N #!I0 #!N  #!F-adobe-times-medium-r-normal--18*   #!N #!N #!I30 #!N 
o Encapsulates the Field-level processing in the subroutine  #!F-adobe-times-bold-r-normal--18*   task #!EF 
in this example. #!N #!I30 #!N o Calls  #!F-adobe-times-bold-r-normal--18*   DXCreateTaskGroup #!EF 
just before recursively traversing the Object in  #!F-adobe-times-bold-r-normal--18*   m_AddParallel #!EF . 
#!N #!I30 #!N o Adds the tasks for processing the Fields 
during recursive traversal by calling  #!F-adobe-times-bold-r-normal--18*   DXAddTask #!EF . #!N #!I30 
#!N o Calls  #!F-adobe-times-bold-r-normal--18*   DXExecuteTaskGroup #!EF just after recursive traversal. At 
this point, the tasks that are defined will be scheduled on 
multiple processors. If any of the tasks returns an error, that 
error will be returned from  #!F-adobe-times-bold-r-normal--18*   DXExecuteTaskGroup #!EF . #!N #!I0 
#!N #!EF #!N #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 01 #include <dx/dx.h> 
#!N 02 #!N 03 static Error DoAdd(Object o, float x); #!N 
04 #!N 05 m_AddParallel(Object *in, Object *out) #!N 06 { #!N 
07 Object o = NULL; #!N 08 float x; #!EF #!N 
#!N #!EC #!N #!N Copy the structure of  #!F-adobe-times-bold-r-normal--18*   in[0] #!EF 
. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 09 if (!in[0]) #!N 10 
DXErrorGoto(ERROR_BAD_PARAMETER, "missing object"); #!N 11 o = DXCopy(in[0], COPY_STRUCTURE); #!N 12 
if (!o) #!N 13 goto error; #!EF #!N #!N #!EC #!N 
#!N Extract floating-point parameter from  #!F-adobe-times-bold-r-normal--18*   in[1] #!EF (default 0). #!CForestGreen 
#!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 14 if (!in[1]) #!N 15 x = 
0; #!N 16 else if (!DXExtractFloat(in[1], &x)) #!N 17 DXErrorGoto(ERROR_BAD_PARAMETER, "bad 
addend"); #!EF #!N #!N #!EC #!N #!N Create the task Group, 
call  #!F-adobe-times-bold-r-normal--18*   DoAdd() #!EF for recursive traversal, and then execute the 
task Group. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 18 DXCreateTaskGroup(); #!N #!N 
19 if (!DoAdd(o, x)) { #!N 20 DXAbortTaskGroup() #!N 21 goto 
error; #!N 22 } #!N 23 if (!DXExecuteTaskGroup()) #!N 24 goto 
error; #!N #!EF #!N #!N #!EC #!N #!N A successful return 
or return on error. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 25 out[0] 
= o; #!N 26 return OK; #!N 27 #!N 28 error: 
#!N 29 DXDelete(o); #!N 30 return ERROR; #!N 31 } #!N 
32 #!N 33 #!EF #!N #!N #!EC #!N #!N The argument 
block for passing parameters to the task routine: #!CForestGreen #!N #!N 
 #!F-adobe-courier-bold-r-normal--18*   #!N 34 struct arg { #!N 35 Field field; #!N 
36 float x; #!N 37 } #!EF #!N #!N #!EC #!N 
#!N The following task routine does the actual work of processing 
a Field.  #!F-adobe-times-bold-r-normal--18*   DXAddTask #!EF instructs the executive to call this 
routine once for each Field. The executive will pass to  #!F-adobe-times-bold-r-normal--18*   
task #!EF the argument block pointer that was specified when  #!F-adobe-times-bold-r-normal--18*   
DXAddTask #!EF itself was called. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 01 
#!N 02 static Error #!N 03 task(Pointer p) #!N 04 { 
#!N 05 struct arg *arg = (struct arg *)p; #!N 06 
Field field; #!N 07 float x, *from, *to; #!N 08 int 
i, n; #!N 09 Array a; #!EF #!N #!N #!EC #!N 
#!N Extract the arguments. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 10 field 
= arg->field; #!N 11 x = arg->x; #!EF #!N #!N #!EC 
#!N #!N Extract, typecheck, and get the data from the "data" 
component. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 12 a = (Array) DXGetComponentValue(field, 
"data"); #!N 13 if (!a) #!N 14 DXErrorReturn(ERROR_MISSING_DATA, "field has no 
data"); #!N 15 if (!DXTypeCheck(a, TYPE_FLOAT, CATEGORY_REAL, 0)) #!N 16 DXErrorReturn(ERROR_BAD_TYPE, 
"data is not floating point"); #!N 17 from = (float *) 
DXGetArrayData(a); #!EF #!N #!N #!EC #!N #!N Create a new Array, 
allocate space to it, and put it in the Field. #!CForestGreen 
#!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 18 DXGetArrayInfo(a, &n, NULL, NULL, NULL, NULL); 
#!N 19 a = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0); #!N 20 if (!DXAddArrayData(a, 
0, n, NULL)) #!N 21 return ERROR; #!N 22 to = 
(float *) DXGetArrayData(a); #!N 23 DXSetComponentValue(field, "data", (Object)a); #!EF #!N #!N 
#!EC #!N #!N The following loop adds  #!F-adobe-times-bold-r-normal--18*   x #!EF to 
obtain the result. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 24 for (i=0; 
i<n; i++) #!N 25 to[i] = from[i] + x; #!EF #!N 
#!N #!EC #!N #!N Clean up the Field. #!CForestGreen #!N #!N 
 #!F-adobe-courier-bold-r-normal--18*   #!N 26 DXChangedComponentValues(field, "data"); #!N 27 DXEndField(field); #!N 28 #!N 
29 return OK; #!N 30 } #!EF #!N #!N #!EC #!N 
#!N The recursive traversal routine follows. Note that at this point 
(and for each Field) it does not process the Field but 
calls  #!F-adobe-times-bold-r-normal--18*   DXAddTask #!EF , specifying the routine that will be 
called in parallel to do the actual work. #!N #!N The 
Data Explorer programming interface is designed so that, in general, the 
programmer does need to use explicit locks. For information about local 
and global memory allocation, see  #!Lstoral,dxall1096 h Memory Allocation  #!EL  . #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   
#!N 01 static #!N 02 Error #!N 03 DoAdd(Object o, float 
x) #!N 04 { #!N 05 struct arg arg; #!N 06 
int i, n; #!N 07 Object oo; #!EF #!N #!N #!EC 
#!N Determine the class of the object. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   
#!N 08 switch (DXGetObjectClass(o)) { #!N 09 #!N 10 case CLASS_FIELD: 
#!EF #!N #!N #!EC #!N #!N Add the task for this 
Field. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 11 arg.field = (Field)o; #!N 
12 arg.x = x; #!N 13 if (!DXAddTask(task, &arg, sizeof arg, 
0.0)) #!N 14 return ERROR; #!N 15 break; #!N 16 #!N 
17 case CLASS_GROUP: #!EF #!N #!N #!EC #!N #!N Traverse Groups 
recursively. #!CForestGreen #!N #!N  #!F-adobe-courier-bold-r-normal--18*   #!N 18 for (i=0; oo=DXGetEnumeratedMember((Group)o, i, 
NULL); i++) #!N 19 if (!DoAdd(oo, x)) #!N 20 return ERROR; 
#!N 21 break; #!N 22 } #!N 23 #!N 24 return 
OK; #!N 25 } #!EF #!N #!N #!EC #!N #!N #!N 
 #!F-adobe-times-medium-i-normal--18*   Next Topic #!EF #!N #!N  #!Lexmodp1,dxall1044 h A Parallel Version of the AverageCell Module  #!EL  #!N  #!F-adobe-times-medium-i-normal--18*   #!N 
