Can anyone help with the general format for flattening a 3D array using MPI? I think I can get the array 1 dimensional just by using (i+xlength*j+xlength*ylength*k), but then I have trouble using equations that reference particular cells of the array.
I tried chunking the code into chunks based on how many processors I had, but then when I needed a value that another processor had, I had a hard time. Is there a way to make this easier (and more efficient) using ghost cells or pointer juggling?
You have two options at least. The simpler one is to declare a preprocessor macro that hides the complexity of the index calculation, e.g.:
This is clumsy since the macro will only work with arrays of fixed leading dimensions, e.g. whatever x
ylength
xzlength
.Much better way to do it is to use so-called dope vectors. Dope vectors are basically indices into the big array. You allocate one big flat chunk of size
xlength * ylength * zlength
to hold the actual data and then create an index vector (actually a tree in the 3D case). In your case the index has two levels:xlength
pointers to thexlength
arrays of pointers, each containingylength
pointers to the beginning of a block ofzlength
elements in memory.Let's call the top level pointer array
A
. ThenA[i]
is a pointer to a pointer array that describes thei
-th slab of data.A[i][j]
is thej
-th element of thei
-th pointer array, which points todata[i][j][0]
(ifdata
was a 3D array). Construction of the dope vector works similar to this:Dope vectors are as easy to use as normal arrays with some special considerations. For example,
A[i][j][k]
will give you access to the desired element ofdata
. One caveat of dope vectors is that the top level consist of pointers to other pointer tables and not of pointers to the data itself, henceA
cannot be used as shortcut for&A[0][0][0]
, norA[i]
used as shortcut for&A[i][0][0]
. StillA[i][j]
is equivalent to&A[i][j][0]
. Another caveat is that this form of array indexing is slower than normal 3D array indexing since it involves pointer chasing.Some people tend to allocate a single storage block for both data and dope vectors. They simply place the index at the beginning of the allocated block and the actual data goes after that. The advantage of this method is that disposing the array is as simple as deleting the whole memory block, while disposing dope vectors, created with the code from the previous section, requires multiple invocations of the
free
operator.