public void AllgatherFlattened()

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);
            }
        }