in MPI/Intracommunicator.cs [637:698]
public void AlltoallFlattened<T>(T[] inValues, int[] sendCounts, int[] recvCounts, ref T[] outValues)
{
if (sendCounts.Length != Size)
throw new ArgumentException($"sendCounts.Length ({sendCounts.Length}) != Communicator.Size ({Size})");
if (recvCounts.Length != Size)
throw new ArgumentException($"recvCounts.Length ({recvCounts.Length}) != Communicator.Size ({Size})");
if (Size == 1)
{
outValues = inValues;
return;
}
SpanTimer.Enter("AlltoallFlattened");
int totalCounts = 0;
for (int i = 0; i < recvCounts.Length; i++) checked
{
totalCounts += recvCounts[i];
}
// Make sure the outgoing array is the right size
if (outValues == null || outValues.Length < totalCounts)
outValues = new T[totalCounts];
MPI_Datatype datatype = FastDatatypeCache<T>.datatype;
if (datatype == Unsafe.MPI_DATATYPE_NULL)
{
// There is no associated MPI datatype for this type, so we will
// need to serialize the value for transmission.
if (SplitLargeObjects)
Serialization.AlltoallFlattened(this, inValues, sendCounts, recvCounts, outValues);
else
AlltoallFlattened_serialized(inValues, sendCounts, recvCounts, outValues);
}
else
{
int[] sendDispls = new int[sendCounts.Length];
int[] recvDispls = new int[recvCounts.Length];
sendDispls[0] = 0;
recvDispls[0] = 0;
for (int i = 1; i < sendDispls.Length; i++) checked
{
sendDispls[i] = sendDispls[i - 1] + sendCounts[i - 1];
recvDispls[i] = recvDispls[i - 1] + recvCounts[i - 1];
}
int lastIndex = sendCounts.Length - 1;
int totalSendCount = checked(sendDispls[lastIndex] + sendCounts[lastIndex]);
if (totalSendCount > inValues.Length)
{
throw new ArgumentException($"Sum of sendCounts ({totalSendCount}) > inValues.Length ({inValues.Length})");
}
GCHandle inHandle = GCHandle.Alloc(inValues, GCHandleType.Pinned);
GCHandle outHandle = GCHandle.Alloc(outValues, GCHandleType.Pinned);
int errorCode = Unsafe.MPI_Alltoallv(inHandle.AddrOfPinnedObject(), sendCounts, sendDispls, datatype,
outHandle.AddrOfPinnedObject(), recvCounts, recvDispls, datatype, comm);
inHandle.Free();
outHandle.Free();
if (errorCode != Unsafe.MPI_SUCCESS)
throw Environment.TranslateErrorIntoException(errorCode);
}
SpanTimer.Leave("AlltoallFlattened");
}