/// <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; }
private bool RunRule_MatchDeterministicReceives() { bool didRuleGetFired = false; // Rule: R_SR - match between sends and deterministic receives for (int recvIdx = 0; recvIdx < _unmatchedReceives.Count; recvIdx++) { AsyncReceiveInstruction recvInstr = _unmatchedReceives[recvIdx]; // Skip any non-deterministic receives (i.e. wildcard receives) if (recvInstr.IsWildcardReceive) { continue; } int recverRank = recvInstr.ReceiverRank; int senderRank = recvInstr.SenderRank.Value; // Make sure that the recvInstr does not have an eligible receive // that was issued before it. (e.g. a wildcard receive before it // issued from the same MpiProcess) // This check is only important if this recvInstr is not a wildcard receive. bool recvInstrHasUnmatchedPredecessor = _unmatchedReceives .Take(recvIdx) // Look at all recvInstr before the current one .Any(unmatchedRecv => unmatchedRecv.ReceiverRank == recverRank && unmatchedRecv.IsWildcardReceive); // Handle the deterministic receives first if (!recvInstrHasUnmatchedPredecessor) { // before we look at the process and use it's lock, lets see if // we can find it in the ready list first. // If it's in the list, then we know it's been added to the // process' queues due to the logic in the async methods. int sendIdx = _unmatchedSends[senderRank] .FindIndex(instr => instr.ReceiverRank == recverRank); if (sendIdx != -1) { // Then we have a match // Rules: R_SR didRuleGetFired = true; ProcessRule_Match_SendRecv(recvIdx, recvInstr, senderRank, sendIdx); // Since we removed an element from the list we are iterating // thru recvIdx--; } } } return(didRuleGetFired); }
/// <summary> /// Receives a message from the source process. /// See MPI_Irecv in the MPI2 API. /// </summary> /// <param name="srcRank">The source of the message. Null specifies a "wildcard receive.</param> /// <returns> /// A handle on the receive instruction that can be used with a function call /// to <see cref="Wait(ReceiveHandle)" />. /// </returns> public ReceiveHandle ReceiveAsync(int?srcRank) { if (srcRank.HasValue) { ValidateRankArgument("srcRank", srcRank.Value); } AssertProcessCanAccessMpiApi(); Runtime.DetectCollectiveAbort(); var instr = new AsyncReceiveInstruction(Process, Process.GetNextInstructionID(), srcRank); Process.AddInstructionToHistory(instr); AddInstructionToPendingQueue(instr); Runtime.NotifyStateChanged(); return(new ReceiveHandle(instr)); }
internal ReceiveHandle(AsyncReceiveInstruction instr) : base(instr) { }