예제 #1
0
 public AsyncSendInstruction(MpiProcess owner, int id, int destRank, string payload, bool eager)
     : base(owner, id, InstructionType.AsyncSend)
 {
     ReceiverRank = destRank;
     Payload      = payload;
     IsEager      = eager;
 }
예제 #2
0
        /// <summary>Creates the MpiProcesses and starts their threads.</summary>
        /// <typeparam name="TIMpiApi">The type of process API that will be passed to the <paramref name="processWork"/> delegate.</typeparam>
        /// <param name="processWork">The method that will be run by each MpiProcess.</param>
        private void SpawnWorkerProcesses <TIMpiApi>(Action <TIMpiApi> processWork)
            where TIMpiApi : IMiniMPICoreAPI
        {
            //
            ParameterizedThreadStart processThreadStart = obj => {
                MpiProcess p          = (MpiProcess)obj;
                var        processAPI = (TIMpiApi)CreateProcessAPI(p);
                ProcessWorker(p, processAPI, processWork);
            };

            // Creates the amount of MpiProcesses specified in the constructor
            // and has all of them run the same method.
            String processThreadNameFormatString = String.Format("P{{0}} (RuntimeID={0})", this.ID);

            Processes = (from i in Enumerable.Range(0, ProcessCount)
                         let t = new Thread(new ParameterizedThreadStart(processThreadStart))
            {
                // Setting the name helps when viewing the thread in a
                // debugger or in Chess' ConcurrencyExplorer
                Name = String.Format(processThreadNameFormatString, i)
            }
                         select new MpiProcess(i, t))
                        .ToArray();

            // Start all the processes
            foreach (var p in Processes)
            {
                p.Thread.Start(p);
            }
        }
예제 #3
0
 protected Instruction(MpiProcess owner, int id, InstructionType type)
 {
     Owner = owner;
     ID    = id;
     Type  = type;
     //HasWaitInstruction = false;
 }
예제 #4
0
        /// <summary>
        /// This method does the modification of the state for the following
        /// rules: R_SR, R_SR*
        /// </summary>
        /// <param name="recvIdx">The index in the _unmatchedRecieves list.</param>
        /// <param name="recvInstr"></param>
        /// <param name="senderRank"></param>
        /// <param name="sendIdx">The index in the _unmatchedSends list.</param>
        private void ProcessRule_Match_SendRecv(int recvIdx, AsyncReceiveInstruction recvInstr, int senderRank, int sendIdx)
        {
            // Get the send instruction
            MpiProcess senderP = GetProcessByRank(senderRank);

            // Look thru the sender's queue to get the match by looking for the
            // first one sent to the receiver.  This way, we ensure the
            // NonOvertaking requirement
            var sendInstr = senderP.SendQueue.FirstOrDefault(instr => instr.ReceiverRank == recvInstr.ReceiverRank);

            Debug.Assert(sendInstr != null, "If an instruction is in the ready queue, it should also be in the process's queue of instructions too.");

            // Since we got the lock open, lets remove it now
            senderP.SendQueue.Remove(sendInstr);

            // Now remove it from the receiver's queue
            recvInstr.Owner.ReceiveQueue.Remove(recvInstr);

            // Match up on our end
            recvInstr.MatchedSend = sendInstr;
            _unmatchedReceives.RemoveAt(recvIdx);
            _matched.Add(recvInstr);

            sendInstr.MatchedReceive = recvInstr;
            _unmatchedSends[senderRank].RemoveAt(sendIdx);
            _matched.Add(sendInstr);

            // And finally, Simulate the completion of the instructions by copying
            // their data
            recvInstr.Payload     = sendInstr.Payload;
            recvInstr.IsCompleted = true;
            // Even if the SendInstr was eager, just set it completed again
            sendInstr.IsCompleted = true;
        }
예제 #5
0
        internal MpiProcess GetProcessByRank(int rank)
        {
            MpiProcess foundP = Processes.FirstOrDefault(p => p.Rank == rank);

            if (foundP == null)
            {
                throw new ArgumentOutOfRangeException("rank", rank, "No process with the specified rank exists.");
            }
            return(foundP);
        }
예제 #6
0
        /// <summary>Marks this process to abort.</summary>
        internal void UnblockProcessForCollectiveAbort(MpiProcess p)
        {
            // Try to unblock the process if it's blocked
            var blockingInstr = p.BlockingInstruction;

            if (blockingInstr != null)
            {
                blockingInstr.WaitHandle.Set();
            }
        }
예제 #7
0
        /// <summary>
        /// Blocks the process and notifies the runtime that the state has changed just before blocking.
        /// </summary>
        internal void BlockProcessOnInstruction(MpiProcess p, IBlockingInstruction instr)
        {
            Debug.Assert(instr != null);

            // Setup state and notify the runtime we've changed the state of the runtime
            p.BlockingInstruction = instr;
            Interlocked.Increment(ref _blockedProcessesCount);
            _runtimeStateChangedEvent.Set();

            // And block
            BlockOnInstructionWaitHandle(instr);

            // Finished blocking, cleanup state
            Interlocked.Decrement(ref _blockedProcessesCount);
            p.BlockingInstruction = null;
        }
예제 #8
0
        protected void ProcessWorker <TIMpiApi>(MpiProcess process, TIMpiApi processAPI, Action <TIMpiApi> processWork)
            where TIMpiApi : IMiniMPICoreAPI
        {
            // Wait for the runtime to signal that all of the processes have been
            // started before I continue.
            _startProcessesTogether.WaitOne();

            process.State = MpiProcessState.Started;
            try
            {
                processWork(processAPI);

                // Detect if an MpiInitialize was matched with an MpiFinalize
                if (process.State == MpiProcessState.MpiInitialized)
                {
                    throw new InvalidMiniMPIProgramException("MpiFinalized must be called.");
                }
            }
            catch (MiniMPICollectiveAbortException ex)
            {
                // Record the error for the process
                Interlocked.Exchange(ref process.Error, ex);
            }
            catch (Exception ex)
            {
                Runtime.StartCollectiveAbort();

                // Only set this if not set yet
                Interlocked.CompareExchange(ref _firstErroredProcessRank, process.Rank, -1);

                // Record the error for the process
                Interlocked.Exchange(ref process.Error, ex);
            }
            finally
            {
                process.State = MpiProcessState.Finished;

                // Notify the runtime that the process has finished
                Interlocked.Increment(ref _processesFinishedCount);
                Runtime.NotifyStateChanged();
            }
        }
예제 #9
0
 internal MiniMPIProcessAPI(MiniMPIRuntime runtime, MpiProcess process)
 {
     Runtime = runtime;
     Process = process;
 }
예제 #10
0
 internal MiniMPIStringProcessAPI(MiniMPIStringRuntime runtime, MpiProcess process)
     : base(runtime, process)
 {
     this.Runtime = (MiniMPIStringRuntime)base.Runtime;
 }
예제 #11
0
 public AsyncReceiveInstruction(MpiProcess owner, int id, int?senderRank)
     : base(owner, id, InstructionType.AsyncReceive)
 {
     SenderRank = senderRank;
 }
예제 #12
0
 public FinalizeBarrierInstruction(MpiProcess owner, int id, EventWaitHandle waitHandle)
     : base(owner, id, InstructionType.FinalizeBarrier)
 {
     WaitHandle = waitHandle;
 }
예제 #13
0
 public WaitInstruction(MpiProcess owner, int id, Handle handle)
     : base(owner, id, InstructionType.Wait)
 {
     WaitingOnInstruction = handle.Instruction;
     WaitHandle           = handle.WaitHandle;
 }