in MPI/Intercommunicator.cs [407:483]
public void AllgatherFlattened<T>(T[] inValues, int[] counts, ref T[] outValues)
{
if (counts.Length != RemoteSize)
throw new ArgumentException("counts should be the size of the remote group", "counts");
int totalCounts = 0;
for (int i = 0; i < counts.Length; i++) checked
{
totalCounts += counts[i];
}
if (outValues.Length != totalCounts)
outValues = new T[totalCounts];
MPI_Datatype datatype = FastDatatypeCache<T>.datatype;
if (datatype == Unsafe.MPI_DATATYPE_NULL)
{
using (UnmanagedMemoryStream inStream = new UnmanagedMemoryStream())
{
// Serialize the data to a stream
for (int source = 0; source < inValues.Length; ++source)
Serialize(inStream, inValues[source]);
// Get the lengths
int[] recvLengths = null;
int totalRecvLengths = 0;
int[] recvDispls = new int[RemoteSize];
Allgather(Convert.ToInt32(inStream.Length), ref recvLengths);
recvDispls[0] = 0;
totalRecvLengths = recvLengths[0];
for (int i = 1; i < RemoteSize; i++) checked
{
recvDispls[i] = recvDispls[i - 1] + recvLengths[i - 1];
totalRecvLengths += recvLengths[i];
}
using (UnmanagedMemoryStream outStream = new UnmanagedMemoryStream(totalRecvLengths))
{
int errorCode;
unsafe
{
errorCode = Unsafe.MPI_Allgatherv(inStream.Buffer, Convert.ToInt32(inStream.Length), Unsafe.MPI_BYTE,
outStream.Buffer, recvLengths, recvDispls, Unsafe.MPI_BYTE, comm);
}
if (errorCode != Unsafe.MPI_SUCCESS)
throw Environment.TranslateErrorIntoException(errorCode);
// De-serialize the data
for (int source = 0; source < totalCounts; ++source)
outValues[source] = Deserialize<T>(outStream);
}
}
}
else
{
int size = 0;
int[] displs = new int[counts.Length];
displs[0] = 0;
for (int i = 1; i < counts.Length; i++) checked
{
displs[i] = displs[i - 1] + counts[i - 1];
size += counts[i];
}
if (outValues == null || outValues.Length != size)
outValues = new T[size];
// Pin the array while we are gathering into it.
GCHandle inHandle = GCHandle.Alloc(inValues, GCHandleType.Pinned);
GCHandle outHandle = GCHandle.Alloc(outValues, GCHandleType.Pinned);
int errorCode = Unsafe.MPI_Allgatherv(inHandle.AddrOfPinnedObject(), inValues.Length, datatype,
outHandle.AddrOfPinnedObject(), counts, displs, datatype, comm);
inHandle.Free();
outHandle.Free();
if (errorCode != Unsafe.MPI_SUCCESS)
throw Environment.TranslateErrorIntoException(errorCode);
}
}