From: Dan Bonachea (bonachea_at_cs_dot_berkeley_dot_edu)
Date: Thu Feb 03 2005 - 23:55:38 PST
At 02:48 PM 2/2/2005, Andrew A. Johnson wrote:
>I have a quick UPC question involving shared arrays
>and dynamic memory allocation. In the examples, to
>create a sharred array of size "N", I can do:
>
> shared [N/THREADS] int array[N];
>
>For example, if N is 9 and THREADS is 3 (i.e. 3 processors),
>this would give me a 1D array with the layout
>
> array[0] -> affinity to 0
> array[1] -> affinity to 0
> array[2] -> affinity to 0
> array[3] -> affinity to 1
> array[4] -> affinity to 1
> array[5] -> affinity to 1
> array[6] -> affinity to 2
> array[7] -> affinity to 2
> array[8] -> affinity to 2
>
>so it is basically a 1D array, split evenly
>into chunks of THREADS processors.
>
>Ok, in most application codes (and the big
>new code I'm contemplating use with UPC), N
>is never known at compile time, and is a
>user-input variable for the size of the data set
>(i.e. the total length of this 1D array I want).
>
>My question is, How do I get this same data layout
>when "N" is a variable only known at run time?
>
>I've been trying to use pointers and the upc
>dynamic memory allocation functions, but having
>trouble getting it to lay-out the data this way.
>
>I'm using the UPC compiler on the Cray X1,
>if that helps...
>
>Thanks, Andrew
>
>--
>Andrew A. Johnson, Ph.D.
>Army HPC Research Center / NetworkCS, Inc.
>612.337.3415 ajohn_at_ahpcrc_dot_org
>
Hi Andrew - I'm copying your question to the upc-libs list, because we've had
some relevant discussions there.
You can allocate the data with this layout using a call such as:
int my_block_elems = N/THREADS; // assuming THREADS divides N evenly
int num_blocks = N/my_block_elems;
shared [1] int *array = upc_all_alloc(num_blocks, my_block_elems*sizeof(int));
This will allocate the heap data blocks as you wish, however the real trouble
is declaring a pointer which will conveniently access them using a non-compile
time constant blocksize. The pointer above has blocksize 1, so (for
THREADS==3) this gives:
array[0] -> affinity to 0
array[1] -> affinity to 1
array[2] -> affinity to 2
array[3] -> affinity to 0
array[4] -> affinity to 1
array[5] -> affinity to 2
array[6] -> affinity to 0
array[7] -> affinity to 1
array[8] -> affinity to 2
UPC currently requires all pointer blocksizes to have a compile-time constant
size, so there's no way convenient way to get the same effect for a
non-constant block size. However, given the declaration above, you can get a
pointer to the start of the ith block like this:
int i;
shared [] int *ith_block = (shared [] int *)&(array[i*my_block_elems]);
and then access the elements of the block as ith_block[0], ith_block[1], etc
There has been some discussion of macros, libraries or even language support
to make this translation more convenient, but nothing standardized has yet
emerged.
Dan