public virtual void TestZeroAlloaction() { ResourceCalculator resCalc = new DefaultResourceCalculator(); Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc = Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(1, 1); RLESparseResourceAllocation rleSparseVector = new RLESparseResourceAllocation(resCalc , minAlloc); rleSparseVector.AddInterval(new ReservationInterval(0, long.MaxValue), ReservationRequest .NewInstance(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance(0, 0), (0)) ); Log.Info(rleSparseVector.ToString()); NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (0, 0), rleSparseVector.GetCapacityAtTime(new Random().NextLong())); NUnit.Framework.Assert.IsTrue(rleSparseVector.IsEmpty()); }
private void DecrementAllocation(ReservationAllocation reservation) { System.Diagnostics.Debug.Assert((readWriteLock.IsWriteLockedByCurrentThread())); IDictionary <ReservationInterval, ReservationRequest> allocationRequests = reservation .GetAllocationRequests(); string user = reservation.GetUser(); RLESparseResourceAllocation resAlloc = userResourceAlloc[user]; foreach (KeyValuePair <ReservationInterval, ReservationRequest> r in allocationRequests) { resAlloc.RemoveInterval(r.Key, r.Value); rleSparseVector.RemoveInterval(r.Key, r.Value); } if (resAlloc.IsEmpty()) { Sharpen.Collections.Remove(userResourceAlloc, user); } }
public virtual void TestSteps() { ResourceCalculator resCalc = new DefaultResourceCalculator(); Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc = Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(1, 1); RLESparseResourceAllocation rleSparseVector = new RLESparseResourceAllocation(resCalc , minAlloc); int[] alloc = new int[] { 10, 10, 10, 10, 10, 10 }; int start = 100; ICollection <KeyValuePair <ReservationInterval, ReservationRequest> > inputs = GenerateAllocation (start, alloc, true); foreach (KeyValuePair <ReservationInterval, ReservationRequest> ip in inputs) { rleSparseVector.AddInterval(ip.Key, ip.Value); } Log.Info(rleSparseVector.ToString()); NUnit.Framework.Assert.IsFalse(rleSparseVector.IsEmpty()); NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (0, 0), rleSparseVector.GetCapacityAtTime(99)); NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (0, 0), rleSparseVector.GetCapacityAtTime(start + alloc.Length + 1)); for (int i = 0; i < alloc.Length; i++) { NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (1024 * (alloc[i] + i), (alloc[i] + i)), rleSparseVector.GetCapacityAtTime(start + i)); } NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (0, 0), rleSparseVector.GetCapacityAtTime(start + alloc.Length + 2)); foreach (KeyValuePair <ReservationInterval, ReservationRequest> ip_1 in inputs) { rleSparseVector.RemoveInterval(ip_1.Key, ip_1.Value); } Log.Info(rleSparseVector.ToString()); for (int i_1 = 0; i_1 < alloc.Length; i_1++) { NUnit.Framework.Assert.AreEqual(Org.Apache.Hadoop.Yarn.Api.Records.Resource.NewInstance (0, 0), rleSparseVector.GetCapacityAtTime(start + i_1)); } NUnit.Framework.Assert.IsTrue(rleSparseVector.IsEmpty()); }
private void IncrementAllocation(ReservationAllocation reservation) { System.Diagnostics.Debug.Assert((readWriteLock.IsWriteLockedByCurrentThread())); IDictionary <ReservationInterval, ReservationRequest> allocationRequests = reservation .GetAllocationRequests(); // check if we have encountered the user earlier and if not add an entry string user = reservation.GetUser(); RLESparseResourceAllocation resAlloc = userResourceAlloc[user]; if (resAlloc == null) { resAlloc = new RLESparseResourceAllocation(resCalc, minAlloc); userResourceAlloc[user] = resAlloc; } foreach (KeyValuePair <ReservationInterval, ReservationRequest> r in allocationRequests) { resAlloc.AddInterval(r.Key, r.Value); rleSparseVector.AddInterval(r.Key, r.Value); } }
internal InMemoryPlan(QueueMetrics queueMetrics, SharingPolicy policy, ReservationAgent agent, Org.Apache.Hadoop.Yarn.Api.Records.Resource totalCapacity, long step, ResourceCalculator resCalc, Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc, Org.Apache.Hadoop.Yarn.Api.Records.Resource maxAlloc, string queueName, Planner replanner, bool getMoveOnExpiry, Clock clock ) { this.queueMetrics = queueMetrics; this.policy = policy; this.agent = agent; this.step = step; this.totalCapacity = totalCapacity; this.resCalc = resCalc; this.minAlloc = minAlloc; this.maxAlloc = maxAlloc; this.rleSparseVector = new RLESparseResourceAllocation(resCalc, minAlloc); this.queueName = queueName; this.replanner = replanner; this.getMoveOnExpiry = getMoveOnExpiry; this.clock = clock; }
public virtual Org.Apache.Hadoop.Yarn.Api.Records.Resource GetConsumptionForUser( string user, long t) { readLock.Lock(); try { RLESparseResourceAllocation userResAlloc = userResourceAlloc[user]; if (userResAlloc != null) { return(userResAlloc.GetCapacityAtTime(t)); } else { return(Resources.Clone(ZeroResource)); } } finally { readLock.Unlock(); } }
internal InMemoryReservationAllocation(ReservationId reservationID, ReservationDefinition contract, string user, string planName, long startTime, long endTime, IDictionary <ReservationInterval, ReservationRequest> allocationRequests, ResourceCalculator calculator, Org.Apache.Hadoop.Yarn.Api.Records.Resource minAlloc) { this.contract = contract; this.startTime = startTime; this.endTime = endTime; this.reservationID = reservationID; this.user = user; this.allocationRequests = allocationRequests; this.planName = planName; resourcesOverTime = new RLESparseResourceAllocation(calculator, minAlloc); foreach (KeyValuePair <ReservationInterval, ReservationRequest> r in allocationRequests) { resourcesOverTime.AddInterval(r.Key, r.Value); if (r.Value.GetConcurrency() > 1) { hasGang = true; } } }
/// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.PlanningException /// "/> /// <exception cref="Org.Apache.Hadoop.Yarn.Server.Resourcemanager.Reservation.Exceptions.ContractValidationException /// "/> private bool ComputeAllocation(ReservationId reservationId, string user, Plan plan , ReservationDefinition contract, ReservationAllocation oldReservation) { Log.Info("placing the following ReservationRequest: " + contract); Resource totalCapacity = plan.GetTotalCapacity(); // Here we can addd logic to adjust the ResourceDefinition to account for // system "imperfections" (e.g., scheduling delays for large containers). // Align with plan step conservatively (i.e., ceil arrival, and floor // deadline) long earliestStart = contract.GetArrival(); long step = plan.GetStep(); if (earliestStart % step != 0) { earliestStart = earliestStart + (step - (earliestStart % step)); } long deadline = contract.GetDeadline() - contract.GetDeadline() % plan.GetStep(); // setup temporary variables to handle time-relations between stages and // intermediate answers long curDeadline = deadline; long oldDeadline = -1; IDictionary <ReservationInterval, ReservationRequest> allocations = new Dictionary <ReservationInterval, ReservationRequest>(); RLESparseResourceAllocation tempAssigned = new RLESparseResourceAllocation(plan.GetResourceCalculator (), plan.GetMinimumAllocation()); IList <ReservationRequest> stages = contract.GetReservationRequests().GetReservationResources (); ReservationRequestInterpreter type = contract.GetReservationRequests().GetInterpreter (); // Iterate the stages in backward from deadline for (ListIterator <ReservationRequest> li = stages.ListIterator(stages.Count); li. HasPrevious();) { ReservationRequest currentReservationStage = li.Previous(); // validate the RR respect basic constraints ValidateInput(plan, currentReservationStage, totalCapacity); // run allocation for a single stage IDictionary <ReservationInterval, ReservationRequest> curAlloc = PlaceSingleStage( plan, tempAssigned, currentReservationStage, earliestStart, curDeadline, oldReservation , totalCapacity); if (curAlloc == null) { // if we did not find an allocation for the currentReservationStage // return null, unless the ReservationDefinition we are placing is of // type ANY if (type != ReservationRequestInterpreter.RAny) { throw new PlanningException("The GreedyAgent" + " couldn't find a valid allocation for your request" ); } else { continue; } } else { // if we did find an allocation add it to the set of allocations allocations.PutAll(curAlloc); // if this request is of type ANY we are done searching (greedy) // and can return the current allocation (break-out of the search) if (type == ReservationRequestInterpreter.RAny) { break; } // if the request is of ORDER or ORDER_NO_GAP we constraint the next // round of allocation to precede the current allocation, by setting // curDeadline if (type == ReservationRequestInterpreter.ROrder || type == ReservationRequestInterpreter .ROrderNoGap) { curDeadline = FindEarliestTime(curAlloc.Keys); // for ORDER_NO_GAP verify that the allocation found so far has no // gap, return null otherwise (the greedy procedure failed to find a // no-gap // allocation) if (type == ReservationRequestInterpreter.ROrderNoGap && oldDeadline > 0) { if (oldDeadline - FindLatestTime(curAlloc.Keys) > plan.GetStep()) { throw new PlanningException("The GreedyAgent" + " couldn't find a valid allocation for your request" ); } } // keep the variable oldDeadline pointing to the last deadline we // found oldDeadline = curDeadline; } } } // / If we got here is because we failed to find an allocation for the // ReservationDefinition give-up and report failure to the user if (allocations.IsEmpty()) { throw new PlanningException("The GreedyAgent" + " couldn't find a valid allocation for your request" ); } // create reservation with above allocations if not null/empty ReservationRequest ZeroRes = ReservationRequest.NewInstance(Resource.NewInstance( 0, 0), 0); long firstStartTime = FindEarliestTime(allocations.Keys); // add zero-padding from arrival up to the first non-null allocation // to guarantee that the reservation exists starting at arrival if (firstStartTime > earliestStart) { allocations[new ReservationInterval(earliestStart, firstStartTime)] = ZeroRes; firstStartTime = earliestStart; } // consider to add trailing zeros at the end for simmetry // Actually add/update the reservation in the plan. // This is subject to validation as other agents might be placing // in parallel and there might be sharing policies the agent is not // aware off. ReservationAllocation capReservation = new InMemoryReservationAllocation(reservationId , contract, user, plan.GetQueueName(), firstStartTime, FindLatestTime(allocations .Keys), allocations, plan.GetResourceCalculator(), plan.GetMinimumAllocation()); if (oldReservation != null) { return(plan.UpdateReservation(capReservation)); } else { return(plan.AddReservation(capReservation)); } }
/// <summary> /// This method actually perform the placement of an atomic stage of the /// reservation. /// </summary> /// <remarks> /// This method actually perform the placement of an atomic stage of the /// reservation. The key idea is to traverse the plan backward for a /// "lease-duration" worth of time, and compute what is the maximum multiple of /// our concurrency (gang) parameter we can fit. We do this and move towards /// previous instant in time until the time-window is exhausted or we placed /// all the user request. /// </remarks> private IDictionary <ReservationInterval, ReservationRequest> PlaceSingleStage(Plan plan, RLESparseResourceAllocation tempAssigned, ReservationRequest rr, long earliestStart , long curDeadline, ReservationAllocation oldResAllocation, Org.Apache.Hadoop.Yarn.Api.Records.Resource totalCapacity) { IDictionary <ReservationInterval, ReservationRequest> allocationRequests = new Dictionary <ReservationInterval, ReservationRequest>(); // compute the gang as a resource and get the duration Org.Apache.Hadoop.Yarn.Api.Records.Resource gang = Resources.Multiply(rr.GetCapability (), rr.GetConcurrency()); long dur = rr.GetDuration(); long step = plan.GetStep(); // ceil the duration to the next multiple of the plan step if (dur % step != 0) { dur += (step - (dur % step)); } // we know for sure that this division has no remainder (part of contract // with user, validate before int gangsToPlace = rr.GetNumContainers() / rr.GetConcurrency(); int maxGang = 0; // loop trying to place until we are done, or we are considering // an invalid range of times while (gangsToPlace > 0 && curDeadline - dur >= earliestStart) { // as we run along we remember how many gangs we can fit, and what // was the most constraining moment in time (we will restart just // after that to place the next batch) maxGang = gangsToPlace; long minPoint = curDeadline; int curMaxGang = maxGang; // start placing at deadline (excluded due to [,) interval semantics and // move backward for (long t = curDeadline - plan.GetStep(); t >= curDeadline - dur && maxGang > 0 ; t = t - plan.GetStep()) { // As we run along we will logically remove the previous allocation for // this reservation // if one existed Org.Apache.Hadoop.Yarn.Api.Records.Resource oldResCap = Org.Apache.Hadoop.Yarn.Api.Records.Resource .NewInstance(0, 0); if (oldResAllocation != null) { oldResCap = oldResAllocation.GetResourcesAtTime(t); } // compute net available resources Org.Apache.Hadoop.Yarn.Api.Records.Resource netAvailableRes = Resources.Clone(totalCapacity ); Resources.AddTo(netAvailableRes, oldResCap); Resources.SubtractFrom(netAvailableRes, plan.GetTotalCommittedResources(t)); Resources.SubtractFrom(netAvailableRes, tempAssigned.GetCapacityAtTime(t)); // compute maximum number of gangs we could fit curMaxGang = (int)Math.Floor(Resources.Divide(plan.GetResourceCalculator(), totalCapacity , netAvailableRes, gang)); // pick the minimum between available resources in this instant, and how // many gangs we have to place curMaxGang = Math.Min(gangsToPlace, curMaxGang); // compare with previous max, and set it. also remember *where* we found // the minimum (useful for next attempts) if (curMaxGang <= maxGang) { maxGang = curMaxGang; minPoint = t; } } // if we were able to place any gang, record this, and decrement // gangsToPlace if (maxGang > 0) { gangsToPlace -= maxGang; ReservationInterval reservationInt = new ReservationInterval(curDeadline - dur, curDeadline ); ReservationRequest reservationRes = ReservationRequest.NewInstance(rr.GetCapability (), rr.GetConcurrency() * maxGang, rr.GetConcurrency(), rr.GetDuration()); // remember occupied space (plan is read-only till we find a plausible // allocation for the entire request). This is needed since we might be // placing other ReservationRequest within the same // ReservationDefinition, // and we must avoid double-counting the available resources tempAssigned.AddInterval(reservationInt, reservationRes); allocationRequests[reservationInt] = reservationRes; } // reset our new starting point (curDeadline) to the most constraining // point so far, we will look "left" of that to find more places where // to schedule gangs (for sure nothing on the "right" of this point can // fit a full gang. curDeadline = minPoint; } // if no gangs are left to place we succeed and return the allocation if (gangsToPlace == 0) { return(allocationRequests); } else { // If we are here is becasue we did not manage to satisfy this request. // So we need to remove unwanted side-effect from tempAssigned (needed // for ANY). foreach (KeyValuePair <ReservationInterval, ReservationRequest> tempAllocation in allocationRequests) { tempAssigned.RemoveInterval(tempAllocation.Key, tempAllocation.Value); } // and return null to signal failure in this allocation return(null); } }