1 %\subsection{Chare Arrays}
4 Chare arrays
\index{chare array
}\index{chare arrays
}\index{arrays
} are
5 arbitrarily-sized, possibly-sparse collections of chares that are distributed
6 across the processors. The entire array has a globally unique identifier of
7 type
\kw{CkArrayID
}, and each element has a unique index of type
8 \kw{CkArrayIndex
}. A
\kw{CkArrayIndex
} can be a single integer (i.e. a one-dimensional array),
9 several integers (i.e. a multi-dimensional array), or an arbitrary string of
10 bytes (e.g. a binary tree index).
12 Array elements can be dynamically created and destroyed on any PE,
13 migrated between PEs, and messages for the elements will still arrive
14 properly. Array elements can be migrated at any time, allowing arrays to be
15 efficiently load balanced. A chare array (or a subset of array elements) can
16 receive a broadcast/multicast or contribute to a reduction.
18 An example program can be found here:
\examplerefdir{array
}.
20 \section{Declaring a One-dimensional Array
}
22 You can declare a one-dimensional (
1D)
\index{array
}\index{chare array
}chare
28 entry A(
\uw{parameters1
});
29 entry void someEntry(
\uw{parameters2
});
33 Array elements extend the system class
\kw{CBase
}\_\uw{ClassName
}, inheriting
37 \item \kw{thisProxy
}: the proxy to the entire chare array that can be indexed
38 to obtain a proxy to a specific array element (e.g. for a
1D chare array
39 \kw{thisProxy
[10]}; for a
2D chare array
\kw{thisProxy(
10,
20)
})
40 \item \kw{thisArrayID
}: the array's globally unique identifier
41 \item \kw{thisIndex
}: the element's array index (an array element can obtain a
42 proxy to itself like this
\kw{thisProxy
[thisIndex
]})
45 \zap{As well as chares are allowed to inherit directly from class
\kw{Chare
},
46 array elements are allowed to inherit from
\kw{ArrayElement1D
} if
1D array,
47 \kw{ArrayElement2D
} if
2D array, and so on up to
6D.
}
50 class A : public CBase
\_A \
{
54 void someEntry(
\uw{parameters2
});
58 Note that
\uw{A
} must have a
\emph{migration constructor
}, which is typically
65 //... constructor code ...
68 A::someEntry(
\uw{parameters2
})
70 // ... code for someEntry ...
74 See the section~
\ref{arraymigratable
} on migratable array elements for more
75 information on the migration constructor that takes
\kw{CkMigrateMessage *
} as
78 \section{Declaring Multi-dimensional Arrays
}
80 \charmpp{} supports multi-dimensional or user-defined indices. These array types
85 array
[1D
] ArrayA \
{ entry ArrayA(); entry void e(
\uw{parameters
});\
}
86 array
[2D
] ArrayB \
{ entry ArrayB(); entry void e(
\uw{parameters
});\
}
87 array
[3D
] ArrayC \
{ entry ArrayC(); entry void e(
\uw{parameters
});\
}
88 array
[4D
] ArrayD \
{ entry ArrayD(); entry void e(
\uw{parameters
});\
}
89 array
[5D
] ArrayE \
{ entry ArrayE(); entry void e(
\uw{parameters
});\
}
90 array
[6D
] ArrayF \
{ entry ArrayF(); entry void e(
\uw{parameters
});\
}
91 array
[Foo
] ArrayG \
{ entry ArrayG(); entry void e(
\uw{parameters
});\
}
92 array
[Bar<
3>
] ArrayH \
{ entry ArrayH(); entry void e(
\uw{parameters
});\
}
95 The declaration of ArrayG expects an array index of type
\kw{CkArrayIndex
}\uw{Foo
},
96 which must be defined before including the
\texttt{.decl.h
} file (see
97 section~
\ref{user-defined array index type
} on user-defined array indices for
102 class ArrayA : public CBase
\_ArrayA \
{ public: ArrayA()\
{\
} ...\
};
103 class ArrayB : public CBase
\_ArrayB \
{ public: ArrayB()\
{\
} ...\
};
104 class ArrayC : public CBase
\_ArrayC \
{ public: ArrayC()\
{\
} ...\
};
105 class ArrayD : public CBase
\_ArrayD \
{ public: ArrayD()\
{\
} ...\
};
106 class ArrayE : public CBase
\_ArrayE \
{ public: ArrayE()\
{\
} ...\
};
107 class ArrayF : public CBase
\_ArrayF \
{ public: ArrayF()\
{\
} ...\
};
108 class ArrayG : public CBase
\_ArrayG \
{ public: ArrayG()\
{\
} ...\
};
109 class ArrayH : public CBase
\_ArrayH \
{ public: ArrayH()\
{\
} ...\
};
112 The fields in
\kw{thisIndex
} are different depending on the dimensionality of
116 \item 1D array:
\kw{thisIndex
}
117 \item 2D array ($x$,$y$):
\kw{thisIndex.x
},
\kw{thisIndex.y
}
118 \item 3D array ($x$,$y$,$z$):
\kw{thisIndex.x
},
\kw{thisIndex.y
},
120 \item 4D array ($w$,$x$,$y$,$z$):
\kw{thisIndex.w
},
\kw{thisIndex.x
},
121 \kw{thisIndex.y
},
\kw{thisIndex.z
}
122 \item 5D array ($v$,$w$,$x$,$y$,$z$):
\kw{thisIndex.v
},
\kw{thisIndex.w
},
123 \kw{thisIndex.x
},
\kw{thisIndex.y
},
\kw{thisIndex.z
}
124 \item 6D array ($x_1$,$y_1$,$z_1$,$x_2$,$y_2$,$z_2$):
\kw{thisIndex.x1
},
125 \kw{thisIndex.y1
},
\kw{thisIndex.z1
},
\kw{thisIndex.x2
},
\kw{thisIndex.y2
},
127 \item Foo array:
\kw{thisIndex
}
128 \item Bar<
3> array:
\kw{thisIndex
}
131 \section{Creating an Array
}
132 \label{basic array creation
}
134 An array is created using the
\kw{CProxy
\_Array::ckNew
} routine, which must
135 be called from PE
0. To create an array from any PE, asynchronous array creation
136 using a callback can be used. See section~
\ref{asynchronous_array_creation
} for
137 asynchronous array creation.
\kw{CProxy
\_Array::ckNew
} returns a proxy object,
138 which can be kept, copied, or sent in messages. The following creates a
139 1D
\index{array
}array containing elements indexed (
0,
1,
\ldots,
\uw{dimX
}-
1):
142 CProxy_ArrayA a1 = CProxy_ArrayA::ckNew(
\uw{params
}, dimX);
145 Likewise, a dense multidimensional array can be created by passing the extents
146 at creation time to
\kw{ckNew
}.
149 CProxy_ArrayB a2 = CProxy_ArrayB::ckNew(
\uw{params
}, dimX, dimY);
150 CProxy_ArrayC a3 = CProxy_ArrayC::ckNew(
\uw{params
}, dimX, dimY, dimZ);
151 CProxy_ArrayD a4 = CProxy_ArrayC::ckNew(
\uw{params
}, dimW, dimX, dimY, dimZ);
152 CProxy_ArrayE a5 = CProxy_ArrayC::ckNew(
\uw{params
}, dimV, dimW, dimX, dimY, dimZ);
153 CProxy_ArrayF a6 = CProxy_ArrayC::ckNew(
\uw{params
}, dimX1, dimY1, dimZ1, dimX2, dimY2, dimZ2);
156 For user-defined arrays, this functionality cannot be used. The
157 array elements must be inserted individually as described in
158 section~
\ref{dynamic_insertion
}.
160 During creation, the constructor is invoked on each array element. For more
161 options when creating the array, see section~
\ref{advanced array create
}.
163 \section{Entry Method Invocation
}
165 To obtain a proxy to a specific element in chare array, the chare array proxy
166 (e.g.
\kw{thisProxy
}) must be indexed by the appropriate index call depending
167 on the dimensionality of the array:
170 \item 1D array, to obtain a proxy to element $i$:
\kw{thisProxy
[$i$
]} or
172 \item 2D array, to obtain a proxy to element $(i,j)$:
\kw{thisProxy($i$,$j$)
}
173 \item 3D array, to obtain a proxy to element $(i,j,k)$:
\kw{thisProxy($i$,$j$,$k$)
}
174 \item 4D array, to obtain a proxy to element $(i,j,k,l)$:
175 \kw{thisProxy($i$,$j$,$k$,$l$)
}
176 \item 5D array, to obtain a proxy to element $(i,j,k,l,m)$:
177 \kw{thisProxy($i$,$j$,$k$,$l$,$m$)
}
178 \item 6D array, to obtain a proxy to element $(i,j,k,l,m,n)$:
179 \kw{thisProxy($i$,$j$,$k$,$l$,$m$,$n$)
}
180 \item User-defined array, to obtain a proxy to element $i$:
\kw{thisProxy
[$i$
]}
181 or
\kw{thisProxy($i$)
}
184 To send a
\index{Array message
} message to an array element, index the proxy
185 and call the method name:
188 a1
[i
].doSomething(
\uw{parameters
});
189 a3(x,y,z).doAnother(
\uw{parameters
});
190 aF
[CkArrayIndexFoo(...)
].doAgain(
\uw{parameters
});
193 You may invoke methods on array elements that have not yet been created. The
194 \charmpp{} runtime system will buffer the message until the element is
196 %\footnote{However, the element must eventually be created (i.e. within
197 %a 3-minute buffering period).}
198 \footnote{However, the element must eventually be created.
}
200 Messages are not guaranteed to be delivered in order. For instance, if a method
201 is invoked on method
\kw{A
} and then method
\kw{B
}; it is possible that
\kw{B
}
202 is executed before
\kw{A
}.
209 Messages sent to migrating elements will be delivered after the migrating
210 element arrives on the destination PE. It is an error to send a message
211 to a deleted array element.
213 \section{Broadcasts on Chare Arrays
}
215 To
\index{array broadcast
} broadcast a message to all the current elements of
216 an array, simply omit the index (invoke an entry method on the chare array
220 a1.doIt(
\uw{parameters
}); //<- invokes doIt on each array element
223 The broadcast message will be delivered to every existing array element exactly
224 once. Broadcasts work properly even with ongoing migrations, insertions, and
227 \section{Reductions on Chare Arrays
}
230 A
\index{array reduction
}reduction applies a single operation (e.g. add,
231 max, min, ...) to data items scattered across many processors and
232 collects the result in one place.
\charmpp{} supports reductions
233 over the members of an array or group.
235 The data to be reduced comes from a call to the member
\kw{contribute
}
238 void contribute(int nBytes, const void *data, CkReduction::reducerType type);
241 This call contributes
\kw{nBytes
} bytes starting at
\kw{data
} to the
242 reduction
\kw{type
} (see Section~
\ref{builtin_reduction
}). Unlike sending a
243 message, you may use
\kw{data
} after the call to
\kw{contribute
}. All
244 members of the chare array or group must call
\kw{contribute
},
245 and all of them must use the same reduction type.
248 For example, if we want to sum each array/group member's single integer myInt,
252 // Inside any member method
253 int myInt=get_myInt();
254 contribute(sizeof(int),\&myInt,CkReduction::sum_int);
257 The built-in reduction types (see below) can also handle arrays of
258 numbers. For example, if each element of a chare array has a pair of
259 doubles
\uw{forces
}[2], the corresponding elements of which are to be added across
260 all elements, from each element call:
263 double forces
[2]=get_my_forces();
264 contribute(
2*sizeof(double),forces,CkReduction::sum_double);
267 Note that since C++ arrays (like
\uw{forces
}[2]) are already pointers, we
268 don't use \&
\uw{forces
}.
270 A slightly simpler interface is available for
\verb+std::vector<T>+,
271 since the class determines the size and count of the underlying type:
275 vector<double> forces(
2);
276 get_my_forces(forces);
277 contribute(forces, CkReduction::sum_double, cb);
280 Either of these will result in a
{\tt double
} array of
2 elements, the first of which
281 contains the sum of all
\uw{forces
}[0] values, with the second element
282 holding the sum of all
\uw{forces
}[1] values of the chare array elements.
284 Typically the client entry method of a reduction takes a single argument of
285 type CkReductionMsg (see Section~
\ref{reductionClients
}). However, by giving an entry method the
286 \kw{reductiontarget
} attribute in the
{\tt .ci
} file, you can instead use entry methods that take
287 arguments of the same type as specified by the
{\em contribute
} call.
288 When creating a callback to the
289 reduction target, the entry method index is generated by
290 {\tt CkReductionTarget(ChareClass, method
\_name)
}
291 instead of
{\tt CkIndex
\_ChareClass::method
\_name(...)
}.
293 the code for a typed reduction that yields an
{\tt int
}, would look like this:
296 // In the .ci file...
297 entry
[reductiontarget
] void done(int result);
300 // Create a callback that invokes the typed reduction client
301 // driverProxy is a proxy to the chare object on which
302 // the reduction target method
{\em done
} is called upon completion
304 CkCallback cb(CkReductionTarget(Driver, done), driverProxy);
306 // Contribution to the reduction...
307 contribute(sizeof(int), &intData, CkReduction::sum_int, cb);
309 // Definition of the reduction client...
310 void Driver::done(int result)
312 CkPrintf("Reduction value: \%d", result);
316 This will also work for arrays of data
317 elements(
{\tt entry
[reductiontarget
] void done(int n, int result
[n
])
}),
318 and for any user-defined type with a PUP method
319 (see ~
\ref{sec:pup
}). If you know that the reduction will yield a particular
320 number of elements, say
3 {\tt int
}s, you can also specify a reduction target which
321 takes
3 {\tt int
}s and it will be invoked correctly.
323 Reductions do not have to specify commutative-associative operations on data;
324 they can also be used to signal the fact that all array/group members
325 have reached a certain synchronization point. In this case, a simpler version
326 of contribute may be used:
328 %Sometimes it is not important the data to be reduced, but only the fact that all
329 %elements have reached a synchronization point. In this case a simpler version of
330 %contribute can be used:
336 In all cases, the result of the reduction operation is passed to the
{\em reduction
337 client
}. Many different kinds of reduction clients can be used, as
338 explained in Section~
\ref{reductionClients
}.
340 Please refer to
\examplerefdir{reductions/typed
\_reduction} for a working example of
341 reductions in Charm++.
343 Note that the reduction will complete properly even if chare array elements are
{\em migrated
}
344 or
{\em deleted
} during the reduction. Additionally, when you create a new chare array element,
345 it is expected to contribute to the next reduction not already in progress on that
348 \subsection{Built-in Reduction Types
}
349 \label{builtin_reduction
}
351 \charmpp{} includes several built-in reduction types, used to combine
352 individual contributions. Any of them may be passed as an argument of type
353 \kw{CkReduction::reducerType
} to
\kw{contribute
}.
355 The first four operations (
{\tt sum
},
{\tt product
},
{\tt max
}, and
{\tt min
}) work on
{\tt char
},
356 {\tt short
},
{\tt int
},
{\tt long
},
{\tt long long
},
{\tt float
}, or
{\tt double
} data as indicated
357 by the suffix. The logical reductions (
{\tt and
},
{\tt or
}) only work on bool and integer data.
358 All the built-in reductions work on either single numbers (pass a pointer) or arrays-- just
359 pass the correct number of bytes to
\kw{contribute
}.
363 \item \kw{CkReduction::nop
} : no operation performed.
366 \item \kw{CkReduction::sum
\_char},
370 \kw{sum
\_long\_long},
375 \kw{sum
\_ulong\_long},
378 the result will be the sum of the given numbers.
380 \item \kw{CkReduction::product
\_char},
384 \kw{product
\_long\_long},
386 \kw{product
\_ushort},
389 \kw{product
\_ulong\_long},
391 \kw{product
\_double} : the result will be the product of the given numbers.
393 \item \kw{CkReduction::max
\_char},
397 \kw{max
\_long\_long},
402 \kw{max
\_ulong\_long},
405 the result will be the largest of the given numbers.
407 \item \kw{CkReduction::min
\_char},
411 \kw{min
\_long\_long},
416 \kw{min
\_ulong\_long},
419 the result will be the smallest of the given numbers.
421 \item \kw{CkReduction::logical
\_and\_bool},
\kw{logical
\_and\_int} : the result will be the logical AND of the given
424 \item \kw{CkReduction::logical
\_or\_bool},
\kw{logical
\_or\_int} : the result will be the logical OR of the given
427 \item \kw{CkReduction::logical
\_xor\_bool},
\kw{logical
\_xor\_int} : the result will be the logical XOR of the given
430 \item \kw{CkReduction::bitvec
\_and\_bool},
\kw{bitvec
\_and\_int} : the result will be the bitvector AND of the given
433 \item \kw{CkReduction::bitvec
\_or\_bool},
\kw{bitvec
\_or\_int} : the result will be the bitvector OR of the given
436 \item \kw{CkReduction::bitvec
\_xor\_bool},
\kw{bitvec
\_xor\_int} : the result will be the bitvector XOR of the given
439 \item \kw{CkReduction::set
} : the result will be a verbatim concatenation of
440 all the contributed data, separated into
\kw{CkReduction::setElement
} records.
441 The data contributed can be of any length, and can vary across array elements
442 or reductions. To extract the data from each element, see the description
445 \item \kw{CkReduction::concat
} : the result will be a byte-by-byte
446 concatenation of all the contributed data. The contributed elements
447 are not delimiter-separated.
449 \item \kw{CkReduction::random
} : the result will be a single randomly
450 selected value of all of the contributed values.
452 \item \kw{CkReduction::statistics
} : returns
453 a
\kw{CkReduction::statisticsElement
} struct, containing summary
454 statistics of the contributed data. Specifically, the struct
455 contains the following fields:
\kw{int count
},
\kw{double
456 mean
}, and
\kw{double m2
}, and the following functions:
\kw {double
457 variance()
} and
\kw{double stddev()
}.
461 \kw{CkReduction::set
} returns a collection of
\kw{CkReduction::setElement
}
462 objects, one per contribution. This class has the definition:
465 class CkReduction::setElement
468 int dataSize; //The length of the `data' array in bytes.
469 char data
[1]; //A place holder that marks the start of the data array.
470 CkReduction::setElement *next(void);
474 Example: Suppose you would like to contribute
3 integers from each array
475 element. In the reduction method you would do the following:
478 void ArrayClass::methodName (CkCallback &cb)
481 result
[0] =
1; // Copy the desired values into the result.
484 // Contribute the result to the reductiontarget cb.
485 contribute(
3*sizeof(int), result, CkReduction::set, cb);
489 Inside the reduction's target method, the contributions can be accessed by using
490 the
\texttt{CkReduction::setElement->next()
} iterator.
493 void SomeClass::reductionTargetMethod (CkReductionMsg *msg)
495 // Get the initial element in the set.
496 CkReduction::setElement *current = (CkReduction::setElement*) msg->getData();
497 while(current != NULL) // Loop over elements in set.
499 // Get the pointer to the packed int's.
500 int *result = (int*) ¤t->data;
501 // Do something with result.
502 current = current->next(); // Iterate.
507 The reduction set order is undefined. You should add a source field to the
508 contributed elements if you need to know which array element gave a particular
509 contribution. Additionally, if the contributed elements are of a complex
510 data type, you will likely have to supply code for
511 %serialize/unserialize operation on your element structure if your
512 %reduction element data is complex.
513 serializing/deserializing them.
514 Consider using the
\kw{PUP
}
515 interface (
\S~
\ref{sec:pup
}) to simplify your object serialization
518 If the outcome of your reduction is dependent on the order in which
519 data elements are processed, or if your data is just too
520 heterogeneous to be handled elegantly by the predefined types and you
521 don't want to undertake multiple reductions, you can use a tuple
522 reduction or define your own custom reduction type.
524 Tuple reductions allow performing multiple different reductions in the
525 same message. The reductions can be on the same or different data, and
526 the reducer type for each reduction can be set independently as well.
527 The contributions that make up a single tuple reduction message are all
528 reduced in the same order as each other. As an example, a chare array
529 element can contribute to a gatherv-like operation using a tuple reduction
530 that consists of two set reductions.
534 CkReduction::tupleElement tupleRedn
[] = \
{
535 CkReduction::tupleElement(sizeof(int), \&thisIndex, CkReduction::set),
536 CkReduction::tupleElement(sizeData, data, CkReduction::set)
538 CkReductionMsg* msg = CkReductionMsg::buildFromTuple(tupleRedn, tupleSize);
539 CkCallback allgathervCB(CkIndex
\_Foo::allgathervResult(
0), thisProxy);
540 msg->setCallback(allgathervCB);
544 The result of this reduction is a single CkReductionMsg that can be processed
545 as multiple reductions:
548 void Foo::allgathervResult (CkReductionMsg* msg)
551 CkReduction::tupleElement* results;
553 msg->toTuple(\&results, \&numReductions);
554 CkReduction::setElement* currSrc = (CkReduction::setElement*)results
[0].data;
555 CkReduction::setElement* currData = (CkReduction::setElement*)results
[1].data;
557 // ... process currSrc and currData
563 See the next section (Section~
\ref{new_type_reduction
}) for details on
564 custom reduction types.
566 \section{Destroying Array Elements
}
568 To destroy an array element -- detach it from the array,
569 call its destructor, and release its memory--invoke its
570 \kw{Array destroy
} method, as:
576 Note that this method can also be invoked remotely i.e. from
577 a process different from the one on which the array element resides.
578 You must ensure that no messages are sent to a deleted element.
579 After destroying an element, you may insert a new element at