예제 #1
0
        /// <summary>
        /// parallel evaluator; For arguments which are not stored on this process,
        /// other processes are asked.
        /// </summary>
        /// <param name="Keys">input; indices at which the permutation should be evaluated;</param>
        /// <param name="Result">
        /// output; the i-th entry is the value of the permutation for index
        /// <paramref name="Keys"/>[i];
        /// </param>
        public void EvaluatePermutation <T1, T2>(T1 Keys, T2 Result)
            where T1 : IList <long>
            where T2 : IList <long> //
        {
            using (new FuncTrace()) {
                if (Keys.Count != Result.Count)
                {
                    throw new ArgumentException("Keys and Result array must have the same number of elements");
                }

                int cnt = Keys.Count;
                int myrank;
                int size;
                MPI.Wrappers.csMPI.Raw.Comm_Size(this.m_Comm, out size);
                MPI.Wrappers.csMPI.Raw.Comm_Rank(this.m_Comm, out myrank);
                ilPSP.MPICollectiveWatchDog.Watch(this.m_Comm);


                // create objects for questions to other processors
                // ================================================

                List <int>[] Questions  = new List <int> [size];
                List <int>[] iQuestions = new List <int> [size];
                for (int p = 0; p < size; p++)
                {
                    Questions[p]  = new List <int>();
                    iQuestions[p] = new List <int>();
                }

                // local evaluation of the permutation mapping
                // ===========================================
                for (int i = 0; i < cnt; i++)
                {
                    long idx = Keys[i];
                    if (idx < 0 || idx >= TotalLength)
                    {
                        throw new ArgumentException("argument out of range; (argument values start at 0)");
                    }

                    long idxLocal = idx - i0Offset;
                    if (idxLocal >= 0 && idxLocal < LocalLength)
                    {
                        // local evaluation

                        Result[i] = m_Values[idxLocal]; // that's all, folks
                    }
                    else
                    {
                        // another processor has to be asked

                        int targProcess = m_Partition.FindProcess(idx);
                        int idxLoc      = (int)(idx - m_Partition.GetI0Offest(targProcess)); // m_i0Offset[targProcess]);
                        Questions[targProcess].Add(idxLoc);
                        iQuestions[targProcess].Add(i);
                    }
                }

                // --------------------
                // Ask other processors
                // --------------------

                // setup question messenger
                // ========================

                Many2ManyMessenger <int> m2mAsk = new Many2ManyMessenger <int>(m_Comm);
                for (int p = 0; p < size; p++)
                {
                    if (Questions[p].Count > 0)
                    {
                        m2mAsk.SetCommPath(p, Questions[p].Count);
                    }
                }

                m2mAsk.CommitCommPaths();

                // transmit data
                // =============

                m2mAsk.StartTransmission(1);

                for (int p = 0; p < size; p++)
                {
                    if (Questions[p].Count > 0)
                    {
                        m2mAsk.SendBuffers(p).CopyFrom(Questions[p].ToArray(), 0);
                        Questions[p] = null;
                        m2mAsk.TransmittData(p);
                    }
                }

                // wait until communication is finished
                // ====================================

                m2mAsk.FinishBlocking();

                // --------------------------
                // answer to other processors
                // --------------------------


                // setup answer messenger
                // ======================

                Many2ManyMessenger <long> m2mAnswer = new Many2ManyMessenger <long>(m_Comm);
                for (int p = 0; p < size; p++)
                {
                    if (m2mAsk.ReceiveBuffers(p) != null)
                    {
                        m2mAnswer.SetCommPath(p, m2mAsk.ReceiveBuffers(p).Count);
                    }
                }
                m2mAnswer.CommitCommPaths();

                // transmit data
                // =============

                m2mAnswer.StartTransmission(1);

                for (int p = 0; p < size; p++)
                {
                    Many2ManyMessenger <int> .Buffer  q = m2mAsk.ReceiveBuffers(p);
                    Many2ManyMessenger <long> .Buffer r = m2mAnswer.SendBuffers(p);

                    if (q != null)
                    {
                        int _cnt = q.Count;

                        for (int i = 0; i < _cnt; i++)
                        {
                            r[i] = m_Values[q[i]];
                        }

                        m2mAnswer.TransmittData(p);
                    }
                }
                m2mAsk.Dispose();


                // wait until communication is finished
                // ====================================

                m2mAnswer.FinishBlocking();

                // ------------------------------------------
                // evaluate the answers from other processors
                // ------------------------------------------

                for (int p = 0; p < size; p++)
                {
                    Many2ManyMessenger <long> .Buffer r = m2mAnswer.ReceiveBuffers(p);

                    if (r != null)
                    {
                        // test
                        if (r.Count != iQuestions[p].Count)
                        {
                            throw new ApplicationException("internal error: mismatch between number of questions/answers");
                        }

                        int        c     = iQuestions[p].Count;
                        List <int> iQeus = iQuestions[p];

                        for (int i = 0; i < c; i++)
                        {
                            Result[iQeus[i]] = r[i];
                        }
                    }
                }
                m2mAnswer.Dispose();
            }
        }
예제 #2
0
        /// <summary>
        /// performs a parallel inversion of this permutation
        /// </summary>
        /// <returns></returns>
        public Permutation Invert()
        {
            using (new FuncTrace()) {
                Permutation inv         = new Permutation(this);
                int         localLength = m_Partition.LocalLength; //m_LocalLengths[m_Master.MyRank];
                int         size;
                MPI.Wrappers.csMPI.Raw.Comm_Size(m_Comm, out size);


                inv.m_Values = new long[localLength];
                long myi0Offset = m_Partition.i0; //m_i0Offset[m_Master.MyRank];

                Many2ManyMessenger <PermutationEntry> m2m = new Many2ManyMessenger <PermutationEntry>(m_Comm);
                int[] NoOfItemsToSent = new int[size];


                // calc i0's for each process
                // ==========================

                long[] i0 = new long[size + 1];
                for (int i = 1; i <= size; i++)
                {
                    i0[i] = i0[i - 1] + m_Partition.GetLocalLength(i - 1);// m_LocalLengths[i - 1];
                }
                // do local inversion and collect items
                // ====================================
                List <PermutationEntry>[] itemsToSend = new List <PermutationEntry> [size];
                for (int p = 0; p < size; p++)
                {
                    itemsToSend[p] = new List <PermutationEntry>();
                }

                for (int i = 0; i < localLength; i++)
                {
                    // decide wether inversion of entry i is local or has to be transmitted ...
                    if (m_Values[i] >= myi0Offset && m_Values[i] < (myi0Offset + localLength))
                    {
                        // local
                        inv.m_Values[this.m_Values[i] - myi0Offset] = i + myi0Offset;
                    }
                    else
                    {
                        // transmit

                        // find target processor
                        int targProc = m_Partition.FindProcess(m_Values[i]);

                        NoOfItemsToSent[targProc]++;

                        // collect item
                        PermutationEntry pe;
                        pe.Index   = myi0Offset + i;
                        pe.PermVal = m_Values[i];
                        itemsToSend[targProc].Add(pe);
                    }
                }


                // setup messenger
                // ===============

                for (int i = 0; i < size; i++)
                {
                    if (NoOfItemsToSent[i] > 0)
                    {
                        m2m.SetCommPath(i, NoOfItemsToSent[i]);
                    }
                }
                m2m.CommitCommPaths();

                // transmit data
                // =============

                //csMPI.Raw.Barrier(csMPI.Raw.MPI_COMM_WORLD);
                //Console.WriteLine("one");
                //csMPI.Raw.Barrier(csMPI.Raw.MPI_COMM_WORLD);
                //Console.WriteLine("two");
                //csMPI.Raw.Barrier(csMPI.Raw.MPI_COMM_WORLD);
                //Console.WriteLine("three");

                m2m.StartTransmission(1);

                for (int p = 0; p < size; p++)
                {
                    if (NoOfItemsToSent[p] <= 0)
                    {
                        continue;
                    }

                    //Many2ManyMessenger.Buffer<PermEntry> sndbuf = new Many2ManyMessenger.Buffer<PermEntry>(m2m, false, p);
                    PermutationEntry[] items = itemsToSend[p].ToArray();
                    m2m.SendBuffers(p).CopyFrom(items, 0);

                    m2m.TransmittData(p);
                }

                m2m.FinishBlocking();

                // invert received items
                // =====================


                for (int p = 0; p < size; p++)
                {
                    Many2ManyMessenger <PermutationEntry> .Buffer rcvbuf = m2m.ReceiveBuffers(p);
                    if (rcvbuf == null)
                    {
                        continue; // no data from process no. p
                    }
                    int cnt = rcvbuf.Count;

                    PermutationEntry[] items = new PermutationEntry[cnt];
                    rcvbuf.CopyTo(items, 0);


                    for (int i = 0; i < cnt; i++)
                    {
                        inv.m_Values[items[i].PermVal - myi0Offset] = items[i].Index;
                    }
                }


                // finalize
                // ========
                m2m.Dispose();
                return(inv);
            }
        }