From a114b0c8eefc197adaa559b1cb99a4c46cae45ee Mon Sep 17 00:00:00 2001 From: Sergei Bozhko <sbozhko@mpi-sws.org> Date: Tue, 17 Sep 2019 15:22:32 +0200 Subject: [PATCH] Add service of set of jobs --- .../analysis/basic_facts/service_of_jobs.v | 324 ++++++++++++++++++ restructuring/model/service_of_jobs.v | 113 ++++++ 2 files changed, 437 insertions(+) create mode 100644 restructuring/analysis/basic_facts/service_of_jobs.v create mode 100644 restructuring/model/service_of_jobs.v diff --git a/restructuring/analysis/basic_facts/service_of_jobs.v b/restructuring/analysis/basic_facts/service_of_jobs.v new file mode 100644 index 000000000..3924225e0 --- /dev/null +++ b/restructuring/analysis/basic_facts/service_of_jobs.v @@ -0,0 +1,324 @@ +From rt.util Require Import tactics sum. +From rt.restructuring.behavior Require Import schedule. +From rt.restructuring.model Require Export service_of_jobs. +From rt.restructuring.model Require Import task schedule.priority_based.priorities processor.ideal. +From rt.restructuring.analysis Require Import workload. +From rt.restructuring.analysis.basic_facts Require Import arrivals completion ideal_schedule. + +From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop. + +(** * Lemmas about Service Received by Sets of Jobs *) +(** In this file, we establish basic facts about the service received by _sets_ of jobs. *) + +(* To begin with, we provide some basic properties of service + of a set of jobs in case of a generic scheduling model. *) +Section GenericModelLemmas. + + (* Consider any type of tasks ... *) + Context {Task : TaskType}. + + (* ... and any type of jobs associated with these tasks. *) + Context {Job : JobType}. + Context `{JobTask Job Task}. + Context `{JobArrival Job}. + Context `{JobCost Job}. + + (* Consider any kind of processor state model, ... *) + Context {PState : Type}. + Context `{ProcessorState Job PState}. + + (* ... any job arrival sequence with consistent arrivals, .... *) + Variable arr_seq : arrival_sequence Job. + Hypothesis H_arrival_times_are_consistent : consistent_arrival_times arr_seq. + + (* ... and any schedule of this arrival sequence ...*) + Variable sched : schedule PState. + + (* ... where jobs do not execute before their arrival or after completion. *) + Hypothesis H_jobs_must_arrive_to_execute : jobs_must_arrive_to_execute sched. + Hypothesis H_completed_jobs_dont_execute : completed_jobs_dont_execute sched. + + (* Let P be any predicate over jobs. *) + Variable P : Job -> bool. + + (* Let's define some local names for clarity. *) + Let arrivals_between := arrivals_between arr_seq. + + (* In this section, we prove that the service received by any set of jobs + is upper-bounded by the corresponding workload. *) + Section ServiceBoundedByWorkload. + + (* Let jobs denote any (finite) set of jobs. *) + Variable jobs : seq Job. + + (* Assume that the processor model is a unit service moodel. I.e., + no job ever receives more than one unit of service at any time. *) + Hypothesis H_unit_service : unit_service_proc_model. + + (* Then, we prove that the service received by those jobs is no larger than their workload. *) + Lemma service_of_jobs_le_workload: + forall t1 t2, + service_of_jobs sched P jobs t1 t2 <= workload_of_jobs P jobs. + Proof. + intros t1 t2. + apply leq_sum; intros j _. + by apply cumulative_service_le_job_cost. + Qed. + + End ServiceBoundedByWorkload. + + (* In this section we prove a few facts about splitting + the total service of a set of jobs. *) + Section ServiceCat. + + (* We show that the total service of jobs released in a time interval [t1,t2) + during [t1,t2) is equal to the sum of: + (1) the total service of jobs released in time interval [t1, t) during time [t1, t) + (2) the total service of jobs released in time interval [t1, t) during time [t, t2) + and (3) the total service of jobs released in time interval [t, t2) during time [t, t2). *) + Lemma service_of_jobs_cat_scheduling_interval : + forall t1 t2 t, + t1 <= t <= t2 -> + service_of_jobs sched P (arrivals_between t1 t2) t1 t2 + = service_of_jobs sched P (arrivals_between t1 t) t1 t + + service_of_jobs sched P (arrivals_between t1 t) t t2 + + service_of_jobs sched P (arrivals_between t t2) t t2. + Proof. + move => t1 t2 t /andP [GEt LEt]. + rewrite /arrivals_between (arrivals_between_cat _ _ t) //. + rewrite {1}/service_of_jobs big_cat //=. + rewrite exchange_big //= (@big_cat_nat _ _ _ t) //=; + rewrite [in X in X + _ + _]exchange_big //= [in X in _ + X + _]exchange_big //=. + apply/eqP; rewrite -!addnA eqn_add2l eqn_add2l. + rewrite exchange_big //= (@big_cat_nat _ _ _ t) //= [in X in _ + X]exchange_big //=. + rewrite -[service_of_jobs _ _ _ _ _]add0n /service_of_jobs eqn_add2r. + rewrite big_nat_cond big1 //. + move => x /andP [/andP [GEi LTi] _]. + rewrite big_seq_cond big1 //. + move => j /andP [ARR Ps]. + apply service_before_job_arrival_zero with H0; auto. + eapply in_arrivals_implies_arrived_between in ARR; eauto 2. + by move: ARR => /andP [N1 N2]; apply leq_trans with t. + Qed. + + (* We show that the total service of jobs released in a time interval [t1,t2) + during [t,t2) is equal to the sum of: + (1) the total service of jobs released in a time interval [t1,t) during [t,t2) + and (2) the total service of jobs released in a time interval [t,t2) during [t,t2). *) + Lemma service_of_jobs_cat_arrival_interval : + forall t1 t2 t, + t1 <= t <= t2 -> + service_of_jobs sched P (arrivals_between t1 t2) t t2 = + service_of_jobs sched P (arrivals_between t1 t) t t2 + + service_of_jobs sched P (arrivals_between t t2) t t2. + Proof. + move => t1 t2 t /andP [GEt LEt]. + apply/eqP;rewrite eq_sym; apply/eqP. + rewrite /arrivals_between [in X in _ = X](arrivals_between_cat _ _ t) //. + by rewrite {3}/service_of_jobs -big_cat //=. + Qed. + + End ServiceCat. + +End GenericModelLemmas. + +(* In this section, we prove some properties about service + of sets of jobs for ideal uniprocessor model. *) +Section IdealModelLemmas. + + (* Consider any type of tasks ... *) + Context {Task : TaskType}. + + (* ... and any type of jobs associated with these tasks. *) + Context {Job : JobType}. + Context `{JobTask Job Task}. + Context `{JobArrival Job}. + Context `{JobCost Job}. + + (* Consider any arrival sequence with consistent arrivals. *) + Variable arr_seq : arrival_sequence Job. + Hypothesis H_arrival_times_are_consistent : consistent_arrival_times arr_seq. + + (* Next, consider any ideal uniprocessor schedule of this arrival sequence ... *) + Variable sched : schedule (ideal.processor_state Job). + + (* ... where jobs do not execute before their arrival or after completion. *) + Hypothesis H_jobs_must_arrive_to_execute : jobs_must_arrive_to_execute sched. + Hypothesis H_completed_jobs_dont_execute : completed_jobs_dont_execute sched. + + (* Let P be any predicate over jobs. *) + Variable P : Job -> bool. + + (* Let's define some local names for clarity. *) + Let arrivals_between := arrivals_between arr_seq. + Let completed_by := completed_by sched. + + (* In this section, we prove that the service received by any set of jobs + is upper-bounded by the corresponding interval length. *) + Section ServiceOfJobsIsBoundedByLength. + + (* Let jobs denote any (finite) set of jobs. *) + Variable jobs : seq Job. + + (* Assume that the sequence of jobs is a set. *) + Hypothesis H_no_duplicate_jobs : uniq jobs. + + (* We prove that the overall service of jobs at a single time instant is at most 1. *) + Lemma service_of_jobs_le_1: + forall t, \sum_(j <- jobs | P j) service_at sched j t <= 1. + Proof. + intros t. + case SCHED: (sched t) => [j | ]; simpl. + { case ARR: (j \in jobs). + { rewrite (big_rem j) //=; simpl. + rewrite /service_at /scheduled_at SCHED; simpl. + rewrite -[1]addn0 leq_add //. + - by rewrite eq_refl; case (P j). + - rewrite leqn0 big1_seq; first by done. + move => j' /andP [_ ARRj']. + apply/eqP; rewrite eqb0. + apply/negP; intros CONTR; move: CONTR => /eqP CONTR. + inversion CONTR; subst j'; clear CONTR. + rewrite rem_filter in ARRj'; last by done. + move: ARRj'; rewrite mem_filter; move => /andP [/negP CONTR _]. + by apply: CONTR. + } + { apply leq_trans with 0; last by done. + rewrite leqn0 big1_seq; first by done. + move => j' /andP [_ ARRj']. + apply/eqP; rewrite eqb0. + rewrite /scheduled_at SCHED. + apply/negP; intros CONTR; move: CONTR => /eqP CONTR. + inversion CONTR; clear CONTR. + by subst j'; rewrite ARR in ARRj'. + } + } + { apply leq_trans with 0; last by done. + rewrite leqn0 big1_seq; first by done. + move => j' /andP [_ ARRj']. + by rewrite /service_at /scheduled_at SCHED. + } + Qed. + + (* Then, we prove that the service received by those jobs is no larger than their workload. *) + Corollary service_of_jobs_le_length_of_interval: + forall (t : instant) (Δ : duration), + service_of_jobs sched P jobs t (t + Δ) <= Δ. + Proof. + intros. + have EQ: \sum_(t <= x < t + Δ) 1 = Δ. + { by rewrite big_const_nat iter_addn mul1n addn0 -{2}[t]addn0 subnDl subn0. } + rewrite -{2}EQ; clear EQ. + rewrite /service_of_jobs exchange_big //=. + rewrite leq_sum //. + move => t' _. + by apply service_of_jobs_le_1. + Qed. + + End ServiceOfJobsIsBoundedByLength. + + (* In this section, we introduce a connection between the cumulative + service, cumulative workload, and completion of jobs. *) + Section WorkloadServiceAndCompletion. + + (* Consider an arbitrary time interval [t1, t2). *) + Variables t1 t2 : instant. + + (* Let jobs be a set of all jobs arrived during [t1, t2). *) + Let jobs := arrivals_between t1 t2. + + (* Next, we consider some time instant [t_compl]. *) + Variable t_compl : instant. + + (* And state the proposition that all jobs are completed by time + t_compl. Next we show that this proposition is equivalent to + the fact that [workload of jobs = service of jobs]. *) + Let all_jobs_completed_by t_compl := + forall j, j \in jobs -> P j -> completed_by j t_compl. + + (* First, we prove that if the workload of [jobs] is equal to the service + of [jobs], then any job in [jobs] is completed by time t_compl. *) + Lemma workload_eq_service_impl_all_jobs_have_completed: + workload_of_jobs P jobs = + service_of_jobs sched P jobs t1 t_compl -> + all_jobs_completed_by t_compl. + Proof. + unfold jobs; intros EQ j ARR Pj; move: (ARR) => ARR2. + apply in_arrivals_implies_arrived_between in ARR; last by done. + move: ARR => /andP [T1 T2]. + have F1: forall a b, (a < b) || (a >= b). + { by intros; destruct (a < b) eqn:EQU; apply/orP; + [by left |right]; apply negbT in EQU; rewrite leqNgt. } + move: (F1 t_compl t1) => /orP [LT | GT]. + { rewrite /service_of_jobs /service_during in EQ. + rewrite exchange_big big_geq //= in EQ; last by rewrite ltnW. + rewrite /workload_of_jobs in EQ. + rewrite (big_rem j) ?Pj //= in EQ. + move: EQ => /eqP; rewrite addn_eq0; move => /andP [CZ _]. + unfold completed_by, schedule.completed_by. + by move: CZ => /eqP CZ; rewrite CZ. + } + { unfold workload_of_jobs, service_of_jobs in EQ; unfold completed_by, schedule.completed_by. + rewrite /service -(service_during_cat _ _ _ t1); last by apply/andP; split. + rewrite cumulative_service_before_job_arrival_zero // add0n. + rewrite <- sum_majorant_eqn with (F1 := fun j => service_during sched j t1 t_compl) + (xs := arrivals_between t1 t2) (P := P); try done. + intros; apply cumulative_service_le_job_cost; auto using ideal_proc_model_provides_unit_service. + } + Qed. + + (* And vice versa, the fact that any job in [jobs] is completed by time t_compl + implies that the workload of [jobs] is equal to the service of [jobs]. *) + Lemma all_jobs_have_completed_impl_workload_eq_service: + all_jobs_completed_by t_compl -> + workload_of_jobs P jobs = + service_of_jobs sched P jobs t1 t_compl. + Proof. + unfold jobs; intros COMPL. + have F: forall j t, t <= t1 -> j \in arrivals_between t1 t2 -> service_during sched j 0 t = 0. + { intros j t LE ARR. + eapply in_arrivals_implies_arrived_between in ARR; eauto 2; move: ARR => /andP [GE LT]. + eapply cumulative_service_before_job_arrival_zero; eauto 2. + by apply leq_trans with t1. } + destruct (t_compl <= t1) eqn:EQ. + { unfold service_of_jobs. unfold service_during. + rewrite exchange_big //=. + rewrite big_geq; last by done. + rewrite /workload_of_jobs big1_seq //. + move => j /andP [Pj ARR]. + specialize (COMPL _ ARR Pj). + rewrite <- F with (j := j) (t := t_compl); try done. + apply/eqP; rewrite eqn_leq; apply/andP; split. + - by apply COMPL. + - by apply service_at_most_cost; auto using ideal_proc_model_provides_unit_service. + } + apply/eqP; rewrite eqn_leq; apply/andP; split; first last. + { by apply service_of_jobs_le_workload; auto using ideal_proc_model_provides_unit_service. } + { unfold workload_of_jobs, service_of_jobs. + rewrite big_seq_cond [X in _ <= X]big_seq_cond. + rewrite leq_sum //. + move => j /andP [ARR Pj]. + specialize (COMPL _ ARR Pj). + rewrite -[service_during _ _ _ _ ]add0n. + rewrite -(F j t1); try done. + rewrite -(big_cat_nat) //=; last first. + move: EQ =>/negP /negP; rewrite -ltnNge; move => EQ. + by apply ltnW. + } + Qed. + + (* Using the lemmas above, we prove equivalence. *) + Corollary all_jobs_have_completed_equiv_workload_eq_service: + all_jobs_completed_by t_compl <-> + workload_of_jobs P jobs = + service_of_jobs sched P jobs t1 t_compl. + Proof. + split. + - by apply all_jobs_have_completed_impl_workload_eq_service. + - by apply workload_eq_service_impl_all_jobs_have_completed. + Qed. + + End WorkloadServiceAndCompletion. + +End IdealModelLemmas. + diff --git a/restructuring/model/service_of_jobs.v b/restructuring/model/service_of_jobs.v new file mode 100644 index 000000000..7aab4cdad --- /dev/null +++ b/restructuring/model/service_of_jobs.v @@ -0,0 +1,113 @@ +From rt.util Require Import tactics sum. +From rt.restructuring.behavior Require Import schedule. +From rt.restructuring.model Require Import task schedule.priority_based.priorities processor.ideal. +From rt.restructuring.analysis Require Import workload. +From rt.restructuring.analysis.basic_facts Require Import arrivals completion ideal_schedule. + +From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop. + +(** * Service Received by Sets of Jobs *) +(** In this file, we define the notion of service received by a set of jobs. *) +Section ServiceOfJobs. + + (* Consider any type of tasks ... *) + Context {Task : TaskType}. + + (* ... and any type of jobs associated with these tasks. *) + Context {Job : JobType}. + Context `{JobTask Job Task}. + Context `{JobArrival Job}. + Context `{JobCost Job}. + + (* Consider any kind of processor state model, ... *) + Context {PState : Type}. + Context `{ProcessorState Job PState}. + + (* ... any job arrival sequence, ... *) + Variable arr_seq : arrival_sequence Job. + + (* ... and any given schedule. *) + Variable sched : schedule PState. + + (* First, we define the service received by a generic set of jobs. *) + Section ServiceOfSetOfJobs. + + (* Let P be any predicate over jobs, ...*) + Variable P : Job -> bool. + + (* ... and let jobs denote any (finite) set of jobs. *) + Variable jobs : seq Job. + + (* Then we define the cumulative service received at + time t by the jobs that satisfy this predicate ... *) + Definition service_of_jobs_at (t : instant) := + \sum_(j <- jobs | P j) service_at sched j t. + + (* ... and the cumulative service received during time + interval [t1, t2) by the jobs that satisfy the predicate. *) + Definition service_of_jobs (t1 t2 : instant) := + \sum_(j <- jobs | P j) service_during sched j t1 t2. + + End ServiceOfSetOfJobs. + + (* Next, we define the service received by tasks with + higher-or-equal priority under a given FP policy. *) + Section PerTaskPriority. + + (* Consider any FP policy. *) + Variable higher_eq_priority : FP_policy Task. + + (* Let jobs denote any (finite) set of jobs. *) + Variable jobs : seq Job. + + (* Let tsk be the task to be analyzed. *) + Variable tsk : Task. + + (* Based on the definition of jobs of higher or equal priority (with respect to tsk), ... *) + Let of_higher_or_equal_priority j := higher_eq_priority (job_task j) tsk. + + (* ...we define the service received during [t1, t2) by jobs of higher or equal priority. *) + Definition service_of_higher_or_equal_priority_tasks (t1 t2 : instant) := + service_of_jobs of_higher_or_equal_priority jobs t1 t2. + + End PerTaskPriority. + + (* Next, we define the service received by jobs with + higher-or-equal priority under JLFP policies. *) + Section PerJobPriority. + + (* Consider any JLDP policy. *) + Variable higher_eq_priority : JLFP_policy Job. + + (* Let jobs denote any (finite) set of jobs. *) + Variable jobs : seq Job. + + (* Let j be the job to be analyzed. *) + Variable j : Job. + + (* Based on the definition of jobs of higher or equal priority, ... *) + Let of_higher_or_equal_priority j_hp := higher_eq_priority j_hp j. + + (* ...we define the service received during [t1, t2) by jobs of higher or equal priority. *) + Definition service_of_higher_or_equal_priority_jobs (t1 t2 : instant) := + service_of_jobs of_higher_or_equal_priority jobs t1 t2. + + End PerJobPriority. + + (* In this section, we define the notion of workload for sets of jobs. *) + Section ServiceOfTask. + + (* Let tsk be the task to be analyzed... *) + Variable tsk : Task. + + (* ... and let jobs denote any (finite) set of jobs. *) + Variable jobs : seq Job. + + (* We define the cumulative task service received by + the jobs from the task within time interval [t1, t2). *) + Definition task_service_of_jobs_in t1 t2 := + service_of_jobs (job_of_task tsk) jobs t1 t2. + + End ServiceOfTask. + +End ServiceOfJobs. -- GitLab