in MPI/Communicator.cs [1532:1599]
internal void GatherFlattened_impl<T>(bool isRoot, int size, T[] inValues, int[] counts, int root, ref T[] outValues)
{
MPI_Datatype datatype = FastDatatypeCache<T>.datatype;
if (!isRoot)
{
if (datatype == Unsafe.MPI_DATATYPE_NULL)
{
T[][] tempOut = null;
Gather_impl<T[]>(isRoot, size, inValues, root, ref tempOut);
}
else
{
// Pin the array while we are gathering out of it.
GCHandle inHandle = GCHandle.Alloc(inValues, GCHandleType.Pinned);
int errorCode = Unsafe.MPI_Gatherv(inHandle.AddrOfPinnedObject(), inValues.Length, datatype, new IntPtr(), null, null, datatype, root, comm);
inHandle.Free();
if (errorCode != Unsafe.MPI_SUCCESS)
throw Environment.TranslateErrorIntoException(errorCode);
}
}
else
{
if (counts.Length != Size)
throw new ArgumentException($"counts.Length ({counts.Length}) != Communicator.Size ({Size})");
int totalRecvSize = 0;
// we must use checked addition in case the total count exceeds 2 billion.
for (int i = 0; i < counts.Length; i++) checked
{
totalRecvSize += counts[i];
}
if (outValues == null || outValues.Length < totalRecvSize)
outValues = new T[totalRecvSize];
if (datatype == Unsafe.MPI_DATATYPE_NULL)
{
T[][] tempOut = new T[counts.Length][];
Gather_impl<T[]>(isRoot, size, inValues, root, ref tempOut);
int cumulativeCount = 0;
for (int source = 0; source < counts.Length; ++source) checked
{
tempOut[source].CopyTo(outValues, cumulativeCount);
cumulativeCount += counts[source];
}
}
else
{
int[] displs = new int[counts.Length];
displs[0] = 0;
for (int i = 1; i < counts.Length; i++)
displs[i] = checked(displs[i - 1] + counts[i - 1]);
// 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_Gatherv(inHandle.AddrOfPinnedObject(), inValues.Length, datatype,
outHandle.AddrOfPinnedObject(), counts, displs, datatype, root, comm);
inHandle.Free();
outHandle.Free();
if (errorCode != Unsafe.MPI_SUCCESS)
throw Environment.TranslateErrorIntoException(errorCode);
}
}
}