public AsyncSendInstruction(MpiProcess owner, int id, int destRank, string payload, bool eager) : base(owner, id, InstructionType.AsyncSend) { ReceiverRank = destRank; Payload = payload; IsEager = eager; }
/// <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); } }
protected Instruction(MpiProcess owner, int id, InstructionType type) { Owner = owner; ID = id; Type = type; //HasWaitInstruction = false; }
/// <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; }
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); }
/// <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(); } }
/// <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; }
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(); } }
internal MiniMPIProcessAPI(MiniMPIRuntime runtime, MpiProcess process) { Runtime = runtime; Process = process; }
internal MiniMPIStringProcessAPI(MiniMPIStringRuntime runtime, MpiProcess process) : base(runtime, process) { this.Runtime = (MiniMPIStringRuntime)base.Runtime; }
public AsyncReceiveInstruction(MpiProcess owner, int id, int?senderRank) : base(owner, id, InstructionType.AsyncReceive) { SenderRank = senderRank; }
public FinalizeBarrierInstruction(MpiProcess owner, int id, EventWaitHandle waitHandle) : base(owner, id, InstructionType.FinalizeBarrier) { WaitHandle = waitHandle; }
public WaitInstruction(MpiProcess owner, int id, Handle handle) : base(owner, id, InstructionType.Wait) { WaitingOnInstruction = handle.Instruction; WaitHandle = handle.WaitHandle; }