Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- %\documentclass[12pt,a4paper]{article}
- %\documentclass[12pt,a4paper]{report}
- \documentclass[12pt,a4paper]{article}
- \usepackage[margin=1 in]{geometry}
- %\usepackage[a4paper, total={6in, 8in}]{geometry}
- \usepackage{graphicx}
- \usepackage[italian]{babel}
- \usepackage[T1]{fontenc}
- \usepackage[utf8]{inputenc}
- \usepackage{wrapfig}
- \usepackage{algorithm}
- \usepackage{amsmath}
- \usepackage{scrextend}
- \usepackage{float}
- \usepackage{mathtools}
- \usepackage{multicol}
- \usepackage{appendix}
- % CODE %
- \usepackage{listings}
- \usepackage{color}
- \usepackage{array}
- \usepackage{wrapfig}
- \usepackage{multirow}
- \usepackage{tabu}
- \definecolor{codegreen}{rgb}{0,0.6,0}
- \definecolor{codegray}{rgb}{0.5,0.5,0.5}
- \definecolor{codepurple}{rgb}{0.58,0,0.82}
- \definecolor{codeviolet}{rgb}{0.55,0.14,0.66}
- \definecolor{backcolour}{rgb}{0.96,0.96,0.96}
- \lstdefinestyle{mystyle}{
- backgroundcolor=\color{backcolour}, %background codice
- commentstyle=\color{codegreen},
- keywordstyle=\color{codeviolet},
- numberstyle=\tiny\color{codegray},
- stringstyle=\color{codepurple},
- basicstyle=\footnotesize,
- breakatwhitespace=false,
- frame = single,
- breaklines=true,
- captionpos=b,
- keepspaces=true,
- numbers=left,
- numbersep=5pt,
- showspaces=false,
- showstringspaces=false,
- showtabs=false,
- tabsize=2
- }
- \lstset{style=mystyle}
- \interfootnotelinepenalty=10000
- \usepackage{cancel}
- \usepackage{hyperref}
- \hypersetup{
- colorlinks,
- citecolor=black,
- filecolor=black,
- linkcolor=black,
- urlcolor=black
- }
- % END CODE %
- \begin{document}
- \begin{titlepage}
- \centering
- \includegraphics[width=0.4\textwidth]{uni-logo.png}\par\vspace{1cm}
- {\scshape\LARGE Università degli Studi di\\Roma Tor Vergata \par}
- \vspace{1cm}
- {\huge\bfseries Progetto Performance Modeling of Computer Systems and Networks\par}
- \vspace{2cm}
- {\Large\itshape Simone D'Aniello\\Giorgia Marchesi\par}
- \vfill
- \vfill
- {\large \ A.A. 2018-2019}
- \end{titlepage}
- \newpage
- \tableofcontents
- \newpage
- \section{Introduzione}
- %\begin{wrapfigure}{r}{0.3\textwidth}
- % \centering
- % \includegraphics[width=0.25\textwidth]{MCC.png}
- % \caption{Schema mobile Cloud computing}
- % \label{fig:MCC}
- %\end{wrapfigure}
- Il numero di dispositivi mobili sta aumentando in modo esponenziale, innescando nuove sfide per le reti mobili e wireless di tutto il mondo.
- Questa classe di reti è caratterizzata da una bassa capacità di archiviazione, un elevato consumo energetico, una larghezza di banda ridotta e un'elevata latenza.
- Così nasce il \textit{mobile edge computing}, il cui obiettivo principale è potenziare le capacità virtuali di archiviazione, elaborazione ed energetiche fornendo agli utenti dei dispositivi stessi capacità di calcolo elevata, efficienza energetica, capacità di archiviazione e mobilità.
- In questo progetto consideriamo un sistema a due livelli costituito da un \textbf{Cloudlet} - che si trova ad \textit{un hop} di distanza dai dispositivi mobili - e da un \textbf{server Cloud} remoto.
- Le applicazioni in esecuzione sui dispositivi mobili selezionano i tasks da inviare sul server esterno ed inviano una richiesta di \textit{offload} ad un Controller situato nel Cloudlet.
- Gli utenti sono inoltre divisi in due classi, in base alle quali variano sia il rate con cui inviano le richieste di offload sia i tempi di servizio con cui queste ultime vengono servite.
- Quando il Controller riceve una richiesta, dovrà decidere se inviarla al Cloudlet oppure al Cloud in base al livello di occupazione del sistema. Si noti che generalmente le attività ospitate dal server Cloud\footnote{Nel seguito della trattazione indicheremo con “Cloud” il server Cloud remoto} beneficiano di un più alto tasso di esecuzione, ma soffrono per un maggiore ritardo della rete (essendo più distante dai dispositivi). L'obiettivo del Controller è dunque fare le scelte che minimizzino il tempo medio di risposta.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{explanation.png}
- \caption{Modello ad alto livello}
- \label{fig:my_label}
- \end{figure}
- \end{center}
- \newpage
- \section{Modello}
- \subsection{Obiettivi}
- L'obiettivo del progetto è quello di realizzare un \textbf{simulatore next-event} per il sistema descritto in precedenza, determinare se esso è stazionario e sviluppare dei test in accordo al comportamento del sistema.
- Viene quindi richiesta la valutazione dei seguenti elementi
- \begin{itemize}
- \item tempo di risposta
- \item throughput
- \item popolazione media
- \end{itemize}
- ciascuno dei quali a livello di sistema, sottosistema e classe.
- Infine si dovrà ideare un nuovo algoritmo di dispatching dei task che minimizzi il tempo di risposta e confrontare e validare i risultati rispetto al caso precedente. \\
- \subsection{Assunzioni}
- Per la trattazione analitica del problema si è deciso di assumere esponenziali sia i tempi di interarrivo (per i quali non vi è alcuna indicazione esplicita) sia i tempi di servizio del Cloudlet.
- Si noti come, secondo la traccia, quest'ultimo sia caratterizzato da tempi di servizio iper-esponenziali. La scelta effettuata è stata guidata dal fatto di voler rendere il modello più semplice da analizzare senza però stravolgere la trattazione. In fase di simulazione sarà comunque possibile scegliere la distribuzione da testare.
- %In realtà nel Cloudlet i tempi di servizio sono iper-esponenziali, ma la scelta effettuata è stata guidata dal fatto di voler rendere il modello più semplice da analizzare senza però stravolgere la trattazione. In fase di simulazione sarà comunque possibile scegliere la distribuzione da testare.
- \subsection{Modello concettuale}
- Dall'introduzione appare chiara l'architettura \textit{two-layer} del sistema, dove il primo livello è occupato dal Cloudlet ed il secondo dal Cloud.
- Il Cloudlet è suddiviso in \textbf{Controller} - che funge da dispatcher delle richieste che provengono dai dispositivi mobili - e dal \textbf{sistema Cloudlet} che si occupa effettivamente di servire le richieste\footnote{Per comodità, nel seguito della trattazione, chiameremo rispettivamente Controller il primo componente e Cloudlet il secondo}.
- Il Cloud, a differenza del Cloudlet, possiede risorse "illimitate". Va tuttavia considerato il tradeoff tra capacità e latenza di rete dovuta alla maggiore distanza del Cloud dai dispositivi.
- Poichè non vi è alcun riferimento esplicito nè alla presenza di code nei sistemi nè alla distribuzione degli arrivi e dei tempi di servizio, si può modellare il sistema nel seguente modo:
- \begin{labeling}{Cloudlet......}
- \item[\textbf{Cloudlet}:] M/M/N/N queuing model
- \item[\textbf{Cloud}:] M/M/$\infty$ queuing model
- \end{labeling}
- %\begin{itemize}
- %\item M/M/N/N server per il Cloudlet;
- %\item M/M/$\infty$ server per il Cloud;
- %\end{itemize}
- Il Controller decide come assegnare i task - al Cloudlet o al Cloud - secondo il seguente algoritmo\footnote{Viene qui mostrato l'algoritmo base di dispatching. Per algoritmi più avanzati vedere paragrafo \ref{algoritmi_dispatcher}}:\\
- \begin{lstlisting}[language=Python, caption=algoritmo di dispatch]
- while(new task arrives){
- if n1 + n2 = N
- send to Cloud
- else
- accept the task on Cloudlet
- }
- \end{lstlisting}
- Nell'algoritmo, $n_i$ per $i = \{1, 2\}$ è una variabile di stato che indica il numero di task di classe \textit{i} in servizio nel Cloudlet ad un certo istante di tempo.
- Indipendentemente dalla classe di appartenenza, un qualsiasi task in arrivo viene inviato al Controller. Quest'ultimo, in base all'algoritmo di dispatching adottato, deciderà se inviarlo al Cloudlet oppure al Cloud affinché venga eseguito.
- Nel modello non vengono esplicitamente considerati ritardi legati a latenze di rete in quanto già inclusi nei tempi di servizio dei rispettivi sistemi.
- Nella figura \ref{key} si riporta il modello della rete ideato facendo riferimento alle considerazioni fatte finora.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{breakpoint.png}
- \caption{Modello della rete}
- \label{key}
- \end{figure}
- \end{center}
- Riassumendo brevemente i concetti chiave del modello concettuale si ha:\\
- \noindent
- \textbf{Descrizione del sistema}:
- \begin{itemize}
- \item Cloudlet System
- \begin{itemize}
- \item Controller
- \item Cloudlet
- \end{itemize}
- \item Cloud
- \end{itemize}
- \noindent
- \textbf{Variabili di stato}:
- \begin{labeling}{$n_{1_{Cloudlet}}(t)$ }
- \item [$n_{1_{Cloudlet}}(t)$] numero di task in esecuzione nel Cloudlet di classe 1 al tempo t
- \item [$n_{2_{Cloudlet}}(t)$] numero di task in esecuzione nel Cloudlet di classe 2 al tempo t
- \item [$n_{1_{Cloud}}(t)$] numero di task in esecuzione nel Cloud di classe 1 al tempo t
- \item [$n_{2_{Cloud}}(t)$] numero di task in esecuzione nel Cloud di classe 2 al tempo t
- \end{labeling}
- L'evoluzione nel tempo di queste variabili dipende dagli eventi di arrivo e di completamento, in particolare:
- \begin{itemize}
- \item arrivi di classe 1 nel Cloudlet provocano un incremento di 1 della variabile $n_{1_{Cloudlet}}(t)$
- \item arrivi di classe 2 nel Cloudlet provocano un incremento di 1 della variabile $n_{2_{Cloudlet}}(t)$
- \item arrivi di classe 1 nel Cloud provocano un incremento di 1 della variabile $n_{1_{Cloud}}(t)$
- \item arrivi di classe 2 nel Cloud provocano un incremento di 1 della variabile $n_{2_{Cloud}}(t)$
- \item il completamento di un task di classe 1 nel Cloudlet provoca un decremento di 1 della variabile $n_{1_{Cloudlet}}(t)$
- \item il completamento di un task di classe 2 nel Cloudlet provoca un decremento di 1 della variabile $n_{2_{Cloudlet}}(t)$
- \item il completamento di un task di classe 1 nel Cloud provoca un decremento di 1 della variabile $n_{1_{Cloud}}(t)$
- \item il completamento di un task di classe 2 nel Cloud provoca un decremento di 1 della variabile $n_{2_{Cloud}}(t)$
- \end{itemize}
- \newpage
- \subsection{Modello analitico e risultati}
- In questo paragrafo sono ricavati i risultati analitici per il modello della rete proposto, necessari per l'analisi, il confronto e la verifica delle performance del sistema di simulazione.
- Vengono inoltre illustrate le formule matematiche utilizzate per ricavare i parametri di interesse - popolazione, throughput e tempo di risposta - con relativi risultati numerici.
- Al fine di ridurre al minimo imprecisioni e approssimazione, i risultati proposti sono stati ottenuti e verificati tramite script Matlab.
- \subsubsection{Assunzioni}
- Assumiamo sia per Cloud che per Cloudlet tempi di interarrivo esponenziali e denotiamo con $\lambda_1$ e $\lambda_2$ i tassi di arrivo rispettivamente dei task di classe 1 e di classe 2 aventi distribuzione esponenziale. Allo stesso modo assumiamo tempi di servizio esponenziali.
- Per ogni classe di richiesta si riportano nella tabella \ref{tassi_di_servizio} i valori dei tassi di arrivo e di servizio per ciascuna classe, utilizzati sia per l'analisi del modello sia per la simulazione.
- %inserire tabella qui sotto
- \begin{table}[h]
- \center
- \label{tab:tassi}
- \begin{tabular}{|c |c |}
- \hline
- \textbf{Task di classe 1} & \textbf{Task di classe 2} \\
- \hline
- $\lambda_1 = 6 $ $task/s$ & $\lambda_2 = 6.25 $ $task/s$\\
- $\mu_{1\_clet} = 0.45 $ $task/s$ & $\mu_{2\_clet} = 0.27 $ $task/s$\\
- $\mu_{1\_cloud} = 0.25 $ $task/s$ & $\mu_{2\_cloud} = 0.22 $ $task/s$\\
- \hline
- \end{tabular}
- \caption{Tassi di arrivo e di servizio per classe}
- \label{tassi_di_servizio}
- \end{table}
- \subsubsection{Cloudlet: modello e risultati analitici}\label{system}
- Sotto le assunzioni di cui sopra, il Cloudlet può essere modellato come un sistema a pura perdita composto da N serventi e privo di coda di attesa, ovvero come un un sistema M/M/N/N.
- Si tratta di un sistema a pura perdita dal momento che, in assenza del Cloud, se il sistema fosse saturo i task in arrivo verrebbero scartati e quindi andrebbero persi. In questo specifico caso, quando tutti i server del Cloudlet sono occupati, i task in arrivo vengono reindirizzati dal Controller verso il Cloud affinché possano essere eseguiti.
- Definiamo dunque lo stato del sistema tramite una coppia $(j,k)$ dove $j$ e $k$ sono rispettivamente il numero di task di classe 1 e di classe 2 attualmente in servizio nel sistema Cloudlet. Lo spazio degli stati $\Omega$ è finito ed è tale per cui \cite{spectrum}: \\
- \begin{center}
- $\Omega = \{ (j , k) : j + k <= s, j >= 0, k >= 0\}$
- \end{center}
- Si noti che il numero di stati per un tale sistema è pari a $\frac{(s + 1)(s + 2)}{2}$, per cui per $s = N = 20$ serventi il numero di stati del sistema diventa considerevolmente elevato: 231. \'E per questo motivo che si è deciso di semplificare l'analisi del modello limitando a 3 il numero di serventi ed utilizzare i risultati ottenuti per questo valore di N per verificare se il sistema di simulazione sia stato implementato correttamente.
- Il modello di simulazione può essere considerato tanto più corretto quanto i valori restituiti in output sono vicini ai valori analitici derivati.\\
- Tornando allo stato del sistema, si noti come questo segua un processo bidimensionale di nascita-morte per cui il diagramma di transizione degli stati risultante è il seguente:
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{M-M-N-N.png}
- \caption{Catena di Markov per un sistema M/M/s/s con due classi di arrivo}
- \label{fig:my_label}
- \end{figure}
- \end{center}
- Dopo aver mostrato il modello per $s = N$ serventi (con $N$ arbitrario), analizziamolo nel dettaglio per $N=3$ e due classi di arrivo indipendenti.
- La catena di Markov risultante viene raffigurata nella figura \ref{fig:markov3}.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.6\textwidth]{mcreduce.png}
- \caption{Catena di Markov per il sistema M/M/3/3}
- \label{fig:markov3}
- \end{figure}
- \end{center}
- Sia dunque $p_{jk}$ la probabilità di avere in questo sistema $j$ task di classe 1 e $k$ task di classe 2 ad un certo istante di tempo, allora l'insieme delle equazioni di bilanciamento dei flussi per $p_{jk}:(j , k) \in \Omega'$ dove $(\Omega') = \{(j , k) : j+k <=3, j >=0, k >=0 \}$ è dato da: \\
- \begin{center}
- \begin{cases}
- \pi_{00}(\lambda_\1 + \lambda_2) = \pi_{01}\mu_2 + \pi_{10}\mu_1\\
- \pi_{01}(\lambda_1+\lambda_2+\mu_2) = \pi_{00}\lambda_2 + \pi_{11}
- \mu_1 + \pi_{02}(2\mu_2)\\
- \pi_{02}(\lambda_1 + \lambda_2 + 2\mu_2) = \pi_{01}\lambda_2 + \pi_{12}\mu_1 + \pi_{03}(3\mu_2)\\
- \pi_{03}(3\mu_2) = \pi_{02}(\lambda_2)\\
- \pi_{10}(\lambda_1 + \lambda_2 + 2\mu_1) = \pi_{00}\lambda_1 + \pi_{11}\mu_2 + \pi_{20}(2\mu_1)\\
- \pi_{11}(\mu_1 + \mu_2 + \lambda_1 + \lambda_2) = \pi_{01}\lambda_1 + \pi_{10}\lambda_2 + \pi_{12}(2\mu_2) + \pi_{21}(2\mu_1)\\
- \pi_{12}(\mu_1 + 2\mu_2) = \pi_{02}\lambda_1 + \pi_{11}\lambda_2\\
- \pi_{20}(\lambda_1 + \lambda_2 + 2\mu_1) = \pi_{10}\lambda_1 + \pi_{21}\mu_2 + \pi_{30}(3\mu_1)\\
- \pi_{21}(2\mu_1 + \mu_2) = \pi_{11}\lambda_1 + \pi_{20}\lambda_2\\
- \pi_{30}(3\mu_1) = \pi_{20}\lambda_1
- \end{cases}
- \end{center}
- La risoluzione di questo sistema di equazioni consente di determinare la probabilità di blocco (o perdita) del Cloudlet e le singole probabilità di routing.
- La probabilità di perdita è data dalla somma delle probabilità di essere negli stati caratterizzati dal colore rosso (vedere Figura \ref{fig:markov3}) ovvero dipende dagli stati in cui il sistema arriva a saturazione ed inizia a scartare i pacchetti in arrivo. In altre parole è la probabilità che nel sistema ci siano più di 3 job.
- Quindi:
- \begin{center}
- $P_{loss} = p_{30} + p_{03} + p_{21} + p_{12} = 0.92007 $\\~\\
- \end{center}
- Una volta calcolata la probabilità di perdita ed il flusso totale in ingresso all'intero sistema, è possibile determinare il flusso di arrivi effettivo presso Cloudlet. Pertanto:\\
- \begin{center}
- $\lambda_{tot} = \lambda_1 + \lambda_2 = 12,25$ $tasks/s \footnote{Flusso totale entrante nel sistema} $\\~\\
- $\lambda_{clet} = \lambda_{tot} - \lambda_{loss} = \lambda_{tot} - (P_{loss}*\lambda_{tot}) = \lambda_{tot}* (1-P_{loss}) = 0.97906 tasks/s $\\~\\
- \end{center}
- Per quanto riguarda i tempi di risposta (sia globale che per classe) del Cloudlet bisogna osservare che questi, poichè non è presente alcuna coda, non risentono del tempo di attesa in coda e dipendono solo dal tempo di servizio. Quindi abbiamo che:
- \begin{center}
- Siano\\
- $[T_{1\_clet}]$ tempo di risposta dei task di classe 1 nel Cloudlet\\
- $E[T_{2\_clet}] $ tempo di risposta dei task di classe 2 nel Cloudlet\\
- $E[T_{clet}]$ tempo di risposta globale nel Cloudlet\\~\\
- Allora\\~\\
- $E[T_{1\_clet}] = 1/\mu_{1clet}= 2,222222$ s\\~\\
- $E[T_{2\_clet}] = 1/\mu_{2clet} = 3,703704$ s \\~\\
- $E[T_{clet}]= p_1 * E[T_{1\_clet}] + p_2 * E[T_{2\_clet}] = 2,97808 $ s \\
- \end{center}
- dove $p_1$ e $p_2$ sono le probabilità che un task appartenga alla classe 1 ed alla classe 2, in particolare:
- \begin{center}
- $p_{class 1} = \frac{\lambda_1}{\lambda_{tot}} = 0.4898$\\~\\
- $p_{class 2} = \frac{\lambda_2}{\lambda_{tot}} = 0.5102$\\~\\
- \end{center}
- Applicando la legge di Little è ora possibile calcolare la popolazione media (globale e per classe) all'interno del Cloudlet:
- \begin{center}
- Siano\\
- $E[N_{clet}]$ popolazione media nel Cloudlet\\
- $[N_{1\_clet}]$ popolazione media di task di classe 1 nel Cloudlet\\
- $E[N_{2\_clet}] $ popolazione media di task di classe 2 nel Cloudlet\\~\\
- Allora\\~\\
- $E[N]= \lambda_{clet}*E[T] = 2,915702$ tasks\\~\\
- $E[N_{1\_clet}]= \lambda_{1\_clet}*E[T_1] = 1,065637$ tasks\\~\\
- $E[N_{2\_clet}]= \lambda_{2\_clet}*E[T_{2\_clet}] = 1,850065$ tasks
- \end{center}
- dove $\lambda_{1\_clet}$ e $\lambda_{2\_clet} $ sono i task in arrivo di classe 1 e di classe 2 presso il Cloudlet:
- \begin{center}
- $\lambda_{1\_clet} = p_1 * \lambda_{clet} = 0,47954$\\
- $\lambda_{2\_clet} = p_2 * \lambda_{clet} = 0,49952$\\
- \end{center}
- I risultati per la popolazione media sono ricavabili anche tramite le equazioni di bilanciamento dei flussi relativi alla catena di Markov in Figura \ref{fig:markov3}:
- \begin{center}
- $E[N_{clet}]= \sum_{j,k,n = 0}^{3}n*p_{jk} = 0*p_{00} + 1*(p_{01} + p_{10})+ 2*(p_{11} + p_{20} + p_{02}) +\\ + 3*(p_{30} + p_{12} + p_{21} + p_{03})$\\~\\
- $E[N_{1\_clet}]= = \sum_{j,n = 0}^{3}n*p_{jk} = 0*(p_{00} + p_{01}) + 1*(p_{10}+p_{11}) + 2*(p_{20} + p_{21}) + 3*p_{30} $\\~\\
- $E[N_{2\_clet}]=\sum_{k,n = 0}^{3}n*p_{jk} = 0*(p_{00} + p_{10}) + 1*(p_{01}+p_{11}) + 2*(p_{02} + p_{12}) + 3*p_{03}$
- \end{center}
- Il throughput, definito come il numero completamenti per unità di tempo, può essere ricavato applicando la Legge di Little, da cui:
- \begin{center}
- $X_{clet} = \frac{E[N_{clet}]}{E[T_{clet}]} = 0.97906$\\~\\
- $X_{1\_clet} = \frac{E[N_{1\_clet}]}{E[T_{1\_clet}]} = 0.47954$\\~\\
- $X_{2\_clet} = \frac{E[N_{2\_clet}]}{E[T_{2\_clet}]} =0.49952 $\\~\\
- \end{center}
- Si può arrivare allo stesso risultato considerando il fatto che il Cloudlet è stato modellato tramite una Catena di Markov. Questa è tale per cui il processo dopo un certo tempo raggiunge una condizione di equilibrio e il flusso in uscita dallo stato uguaglia il flusso in ingresso. Ovvero è valida l’equazione del bilanciamento globale. Pertanto:
- \begin{center}
- $X_{clet} = \lambda_{clet} = 0.97906$\\~\\
- $X_{1\_clet} = \lambda_{1\_clet} = 0.47954$\\~\\
- $X_{2\_clet} = \lambda_{2\_clet} =0.49952 $\\~\\
- \end{center}
- \subsubsection{Cloud: modello e risultati analitici}
- Il Cloud, a differenza del Cloudlet, presenta risorse illimitate. Pertanto a partire dalle assunzioni fatte\footnote{vedere paragrafo 3.4.1}, è possibile modellarlo come un sistema M/M/$\infty$.
- Un tale sistema è caratterizzato da infiniti serventi in cui ogni arrivo prende servizio immediatamente e quindi non sperimenta attesa. Si parla quindi di un caso limite di un sistema M/M/k con k molto grande.
- Definiamo dunque lo stato del sistema tramite una coppia $(j,k)$ dove $j$ e $k$ sono rispettivamente il numero di task di classe 1 e di classe 2 attualmente in servizio nel sistema. Lo spazio degli stati $\Omega$ è infinito numerabile ed è tale per cui:
- \begin{center}
- $\Omega = \{ (j , k) :j >= 0, k >= 0\}$\\
- \end{center}
- e la catena di Markov risultante è:\\
- %inserire catena per infinite server
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.6\textwidth]{infinite_markov.png}
- \caption{Catena di Markov per un infinite Server}
- \label{fig:my_label}
- \end{figure}
- \end{center}
- Il flusso in arrivo dipende dalla probabilità di perdita del Cloudlet: quando quest'ultimo è saturo, i task vengono inviati al Cloud per poter essere eseguiti. Dunque è possibile determinare il flusso in ingresso nel Cloud come:\\
- \begin{center}
- $\lambda_{cloud} = \lambda_{tot} - \lambda_{clet} = P_{loss} * \lambda_{tot} = 11,27094 tasks/s $\\~\\
- \end{center}
- Da cui si ricavano i tassi di arrivo di classe 1 e di classe 2:\\
- \begin{center}
- $\lambda_{1\_cloud} = p_1* \lambda_{cloud} = 5.51796$ tasks/s \\~\\
- $\lambda_{2\_cloud} = p_2* \lambda_{cloud} = 5.75348 $ tasks/s \\~\\
- \end{center}
- Relativamente ai tempi di risposta e alla popolazione media nel Cloud vale quanto detto per il Cloudlet, si indica con:
- \begin{itemize}
- \item $E[T_{cloud}]$ Tempo di risposta globale nel Cloud
- \item $[T_{1\_cloud}]$ Tempo di risposta dei task di classe 1 nel Cloud
- \item $E[T_{2\_cloud}] $ Tempo di risposta dei task di classe 2 nel Cloud
- \item $E[N_{cloud}]$ popolazione media nel Cloud
- \item $[N_{1\_cloud}]$ popolazione media di task di classe 1 nel Cloud
- \item $E[N_{2\_cloud}] $ popolazione media di task di classe 2 nel Cloud\\~\\
- \end{itemize}
- \newline
- Allora:
- \begin{center}
- $E[T_{1\_cloud}] = \frac{1}{\mu_{1\_cloud}} = 4,00000$ s \\~\\
- $E[T_{2\_cloud}] = \frac{1}{\mu_{2\_cloud}} = 4.54545$ s\\~\\
- $E[T_{cloud}]= p_1 * E[T_{1\_cloud}] + p_2 * E[T_{2\_cloud}] = 4,278292$ s\\~\\
- ***
- \end{center}
- \begin{center}
- $E[N_{1\_cloud}] = \lambda_{1\_cloud}*E[T_{1\_cloud}] = 22,081853$ tasks\\~\\
- $E[N_{2\_cloud}] = \lambda_{2\_cloud}*E[T_{2\_cloud}] = 26,138557$ tasks\\~\\
- $E[N_{cloud}] = \lambda_{cloud}*E[T_{cloud}] = 48,220410$ tasks\\~\\
- \end{center}
- Per quanto riguarda il throughput del Cloud valgono le considerazioni fatte per il Cloudlet, quindi:\\
- \begin{center}
- $X_{cloud} = \lambda_{cloud} = 11.27094$\\~\\
- $X_{1\_cloud} = \lambda_{1\_cloud} = 5.51796$\\~\\
- $X_{2\_cloud} = \lambda_{2\_cloud} = 5.75348 $\\~\\
- \end{center}
- \subsubsection{Risultati analitici globali}
- Derivano dalla combinazione dei risultati precedenti.\\
- Innanzitutto occorre calcolare le probabilità che i task entrino nel Cloudlet piuttosto che nel Cloud:
- \begin{center}
- $P_{cloud} = P_{loss} = 0,92007$\\~\\
- $P_{clet} = 1 - P_{cloud} = 0,07993$\\~\\
- \end{center}
- Tempi di risposta globali e per classe:
- \begin{center}
- Siano\\
- $E[T_{glob}]$ Tempo di risposta globale\\
- $[T_{1\_glob}]$ Tempo di risposta globale dei task di classe 1\\
- $E[T_{2\_glob}] $ Tempo di risposta globale dei task di classe 2\\
- $E[N_{glob}]$ popolazione media globale \\
- $[N_{1\_glob}]$ popolazione media globale di task di classe 1\\
- $E[N_{2\_glob}] $ popolazione media globale di task di classe 2\\~\\
- Allora\\~\\
- $E[T_{1\_glob}] = p_{clet}*E[T_{1\_clet}] + p_{cloud}*E[T_{1\_cloud}] = 3,857915$ s\\~\\
- $E[T_{2\_glob}] = p_{clet}*E[T_{2\_clet}] + p_{cloud}*E[T_{2\_cloud}] = 4,478180$ s\\~\\
- $E[T_{glob}]= p_{clet}*E[T_{clet}] + p_{cloud}*E[T_{cloud}] = 4,174377$ s\\~\\
- ***
- \end{center}
- \begin{center}
- $E[N_{1\_glob}] = \lambda_{tot}*E[T_{1\_glob}] = 25,04626$ tasks\\~\\
- $E[N_{2\_glob}] = \lambda_1*E[T_{2\_glob}] = 26,08985$ tasks\\~\\
- $E[N_{glob}] = \lambda_2*E[T_{glob}] = 51,136112$ tasks \\~\\
- \end{center}
- Il throughput globale è dato dalla somma dei throughput dei singoli sottosistemi (Cloudlet e Cloud). Inoltre, osservando tutto il sistema come fosse una blackbox e sapendo che raggiunge la stabilità, è possibile utilizzare in alternativa la Legge di Little. Pertanto:
- \begin{center}
- $X_{glob} = X_{clet} + X_{cloud} = \lambda_{tot} = 12,25 $\\~\\
- $X_{1\_glob} = X_{1\_clet} + X_{1\_cloud} = \lambda_1 = 6,00$\\~\\
- $X_{2\_glob} = X_{2\_clet} + X_{2\_cloud}= \lambda_2 = 6,25 $\\~\\
- \end{center}
- \newpage
- \subsection{Modello delle specifiche}
- \subsubsection{Next-event simulation}
- Per costruire un modello di simulazione Next-Event bisogna affinare la descrizione dello stato del sistema e della sua evoluzione nel tempo. Per \textit{stato del sistema} si intende una completa caratterizzazione del sistema ad un certo istante di tempo, descritto tramite variabili di stato.
- Dunque, in questo capitolo (cioè a livello delle specifiche) si fornirà una descrizione dello stato del sistema intesa come una raccolta di variabili matematiche (le variabili di stato) messe in relazione tramite equazioni ed espressioni logiche e tramite un algoritmo che le metta in relazione e ne determini l'evoluzione nel tempo.\\
- La \textit{Next-Event Simulation} si basa su alcuni concetti chiave come: (1) stato del sistema, (2) eventi, (3) clock di simulazione, (4) scheduling degli eventi e (5) event-list. In particolare:
- %che devono essere rispettati indipendentemente dalla implementazione.
- %Nelle prossime righe alla loro definizione teorica viene aggiunta una descrizione su come lo sviluppo ha tenuto conto dei vari aspetti, mostrando in modo chiaro il flusso della simulazione.
- \begin{itemize}
- \item \textbf{Stato del sistema}: lo stato rappresenta un insieme di variabili che identifica univocamente il sistema in un certo istante di tempo.
- \item \textbf{Evento}: occorrenza necessaria per il cambiamento dello stato del sistema. Ad ogni evento è associato un tipo.
- \item \textbf{Clock di simulazione}: rappresenta il valore corrente del tempo di simulazione.
- Il sistema simulato è dinamico ed evolve nel tempo, per cui è necessario tenere traccia del valore corrente di simulazione per poter scandire lo scorrere del tempo.
- \item \textbf{Event-scheduling}: meccanismo di avanzamento del tempo che serve a garantire che gli eventi (e quindi la simulazione stessa) si verifichino nell'ordine corretto.
- \item \textbf{Event-list}: è la struttura dati che contiene gli eventi ordinati in base al tempo in cui dovranno verificarsi. Tramite la scansione di questa lista è possibile determinare quale sarà il prossimo evento da schedulare.
- \end{itemize}
- Una volta individuate le variabili di stato che descrivono il sistema ed i tipi di eventi bisogna costruire l'algoritmo che definisce i cambiamenti di stato che avranno luogo al verificarsi di un evento.\\
- Un modello di simulazione next-event è costituito dai seguenti quattro passaggi:
- \begin{itemize}
- \item \textbf{Inizializzazione:} il clock di simulazione viene inizializzato (solitamente a zero) e in seguito viene determinata e schedulata la prima occorrenza di ogni evento possibile, inizializzando in tal modo la lista di eventi;
- \item \textbf{Processamento dell'evento corrente:} la event-list viene scansionata per determinare l'evento più imminente, quindi viene avanzato il clock di simulazione al momento in cui è prevista l'occorrenza di questo e lo stato del sistema viene aggiornato. Questo evento è noto come l'evento corrente.
- \item \textbf{Scheduling dei nuovi eventi:} i nuovi eventi (se ce ne sono) che possono essere generati dall'evento corrente vengono inseriti nella lista degli eventi (in ordine cronologico).
- \item \textbf{Terminazione:} il processo di avanzamento del clock di simulazione continua finché non viene soddisfatta una condizione di terminazione. Questa condizione può essere specificata come uno pseudo-evento che si verifica una sola volta al termine della simulazione. Può essere basata sul raggiungimento di un numero arbitrario di eventi da processare, sul superamento del tempo di simulazione o sulla stima di una misura di uscita.
- \end{itemize}
- Il modello di simulazione viene quindi inizializzato una sola volta all'inizio della simulazione, poi si alterna tra il secondo passaggio ed il terzo passaggio (pianificazione degli eventi successivi) finché non viene rilevato un criterio di terminazione.\\
- \subsubsection{La next-event simulation in pratica}
- In questo specifico caso lo \textbf{stato del sistema} è identificato da:
- \begin{itemize}
- \item \textbf{$n_{i\_clet}(t)$:} rappresenta il numero di job di classe \textit{i} presenti nel Cloudlet;
- \item \textbf{$n_{i\_cloud} (t)$:} rappresenta il numero di job di classe \textit{i} presenti nel Cloud ad un certo istante \textit{t};
- \item \textbf{N:} numero di server nel Cloudlet. \'E infatti necessario sapere il livello di occupazione del Cloudlet per applicare l'algoritmo di dispatching;
- \item \textbf{s:} stato del singolo server (0 o 1 se idle o busy).
- \end{itemize}
- Gli \textbf{eventi} possono essere invece di due tipologie (una per ogni sottosistema):
- \begin{itemize}
- \item \textbf{arrivo}: evento che si verifica quando perviene al sistema un nuovo task. Il tempo di riferimento è quindi il tempo di arrivo che è pari al tempo intercorso tra il suo e quello del task precedente
- \begin{center}
- tempo evento arrivo: $\tau_{a_n} = t_n - t_{n-i}$
- \end{center}
- \begin{center}
- tempo completamento task: $\tau_{c} = t_{service} + t_{arrival}$
- \end{center}
- Inoltre, quando si verifica un tale evento verranno incrementate le variabili di stato relativi al numero di task attualmente presenti nel sistema.
- \item \textbf{completamento}: evento secondo cui il sistema porta a termine l’esecuzione di uno specifico task. Tale evento viene aggiornato di volta in volta al valore dato dalla differenza tra il tempo di completamento del task e il tempo in cui si è verificato l'ultimo arrivo nel sistema
- \begin{center}
- tempo evento completamento: $\tau_{c_n} = t_{c_n} - t_{last arrive}$
- \end{center}
- Infine viene decrementata opportunamente la popolazione del sistema e viene aumentato il numero di completamenti.
- \end{itemize}
- Si può notare come il tempo relativo all'evento arrivo rimanga fissato per tutto il tempo di vita dell'evento. Questo non avviene per i completamenti, il cui tempo viene decrementato ad ogni arrivo.
- Per semplificare la simulazione, il \textit{tempo di simulazione} viene incrementato dei soli tempi legati agli eventi di tipo arrivo. Solo una volta terminati gli arrivi, si prendono in considerazione i tempi di servizio, in modo tale da garantire la correttezza della simulazione.\\
- L'avanzamento del tempo della simulazione attraversa 3 fasi:
- \begin{enumerate}
- \item \textbf{estrazione}
- \item \textbf{processamento}
- \item \textbf{rimozione del primo evento in ordine temporale dalla lista}
- \end{enumerate}
- In Listing \ref{simulation} lo pseudocodice:\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Python, caption=pseudocodice del flusso della simulazione, label={simulation}]
- Simulation() {
- int i = 0;
- while(i < TOTAL_PACKETS){
- Event e = generateArrival();
- eventList.add(e);
- sortList();
- handleFirstEvent();
- i++;
- }
- }
- handleFirstEvent(){
- while(first event is not an arrival){
- if(firstEvent is a Cloudlet completion)
- Cloudlet.processCompletion();
- else if(firstEvent is a Cloud completion)
- Cloud.processCompletion();
- remove_event_from_list();
- }
- }
- \end{lstlisting}
- \end{minipage}
- L'algoritmo di avanzamento del tempo di simulazione funziona quindi in tal modo: all'inizio di ogni ciclo\footnote{per ciclo si intende il tempo che intercorre tra un arrivo ed il successivo, o anche la singola iterazione della simulazione} viene aggiunto un nuovo arrivo alla lista di eventi. Dopo aver ordinato la lista sulla base dell'\textit{eventTime}, gli eventi vengono estratti con la seguente logica:
- \begin{itemize}
- \item se l'evento in cima è di tipo arrivo, viene processato. Questo comporta l'inserimento di un evento di tipo completamento nella lista di eventi.
- \item se l'evento è un completamento, viene processato e rimosso dalla lista. In seguito si estrae un nuovo evento.
- \end{itemize}
- In figura \ref{event_list} un esempio di inserimento e rimozione degli eventi dalla eventList.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.5\textwidth]{event_list.png}
- \caption{inserimento e rimozione dalla lista di eventi}
- \label{event_list}
- \end{figure}
- \end{center}
- Si noti che il tempo di simulazione evolve eseguendo gli eventi in ordine crescente rispetto al tempo in cui è stato pianificato il loro accadimento. Il tempo quindi non scorre in modo continuo ma avanza in modo discontinuo tra un evento e l'altro. A livello computazionale, l'orologio di simulazione viene congelato durante l'esecuzione dell'algoritmo che determina il cambiamento di stato in modo tale che quest'ultimo si verifichi in modo istantaneo rispetto all'orologio di simulazione.
- La simulazione procede fintanto che non viene raggiunta la condizione di uscita, che in tal caso è relativa al raggiungimento del numero di eventi di tipo arrivo determinati dall'utente\footnote{parametro ITERATIONS nel file \textit{config.properties}}. Considerato che ad ogni arrivo corrisponde un completamento, la simulazione termina quando il numero di eventi processati è il doppio del valore stabilito dall'utente in fase di configurazione.
- Tenendo conto di quanto detto finora è possibile schematizzare nella figura \ref{flusso_eventi} il flusso di simulazione.
- \begin{center}
- \begin{figure}[h]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/flusso_eventi.png}
- \caption{flusso della simulazione}
- \label{flusso_eventi}
- \end{figure}
- \end{center}
- Le operazioni di processamento degli eventi arrivo e completamento sono state volutamente lasciate generiche perché non esistono solamente eventi che cambiano lo stato del sistema (ad esempio incrementando o decrementando le popolazioni). Basti pensare ad eventi legati al campionamento delle statistiche.
- Entrando più nel dettaglio quindi, in caso di estrazione di un evento di tipo arrivo, il Job corrispondente viene inviato al Controller. Questo, sulla base dell'algoritmo di dispatching scelto\footnote{i vari algoritmi di dispatching sono trattati nel dettaglio nel paragrafo \ref{algoritmi_dispatch}}, decide se dirottare il pacchetto verso il Cloud o verso il Cloudlet.
- %RIMUOVERE? GIà DETTO IN ALTRE OCCASIONI
- \textcolor{red}{In quest'ultimo caso il sistema tiene conto del fatto che ogni Server viene trattato come un oggetto a sé stante e pertanto si potrebbero effettuare statistiche anche sullo stato di utilizzazione del server\footnote{Per ulteriori considerazioni sull'importanza di avere statistiche per ciascun server si veda il paragrafo \ref{sviluppi_futuri}}.}
- Sia che il pacchetto vada nel Cloudlet che nel Cloud, viene incrementato il valore relativo al numero di Job attualmente presenti nel sistema e viene aggiunto un evento di completamento alla lista di eventi. Infine viene aggiornato il tempo di simulazione e viene decrementato il tempo relativo agli eventi di tipo completamento che devono ancora essere processati.
- In caso di estrazione di un evento di tipo completamento, il sottosistema presso cui il Job ha terminato la sua esecuzione si occupa non solo di decrementare la propria popolazione attuale ma consente al sistema di aggiornare le statistiche riguardanti popolazione media e tempi medi di servizio globali.
- \newpage
- \subsection{Modello computazionale}
- In questo paragrafo viene illustrato come il modello delle specifiche è stato tradotto in un modello computazionale. Per rendere la discussione più fluida, viene trattato solo quanto necessario ai fini della comprensione dell'implementazione effettiva del modello delle specifiche e del codice. Per una spiegazione più approfondita delle Features si invita alla lettura della sezione \ref{implementazione}.
- Nella prima parte viene mostrata la struttura del codice, realizzato nel linguaggio di programmazione Java, coadiuvata dalla descrizione delle funzionalità di ciascuna classe. Successivamente viene mostrata l'implementazione effettiva del modello\footnote{Si noti che il codice mostrato all'interno di questo paragrafo può differire leggermente dal codice reale. Sono state infatti omesse le funzioni che si occupano delle stampe su console e su file per incentrare la trattazione solo sulle entità fondamentali}.
- \subsubsection{Classi}
- Il codice è suddiviso in package, ciascuno relativo ad una macro-area funzionale di interesse. La struttura dei pacchetti e del codice è la seguente:
- \begin{itemize}
- \item cloud
- \begin{itemize}
- \item Cloud
- \end{itemize}
- \item cloudlet
- \begin{itemize}
- \item Cloudlet
- \item CloudletController
- \item DispatchAlgorithm
- \item Server
- \end{itemize}
- \item event
- \begin{itemize}
- \item CompletionHandler
- \item Event
- \item EventGenerator
- \item Server
- \end{itemize}
- \item job
- \begin{itemize}
- \item Job
- \end{itemize}
- \item results
- \begin{itemize}
- \item CSVLogger
- \item PerformanceLogger
- \item Printer
- \item ReadStatisticsCSV
- \end{itemize}
- \item simulation
- \begin{itemize}
- \item Simulation
- \end{itemize}
- \item statistics
- \begin{itemize}
- \item BatchMeans
- \item ConfidenceInterval
- \item JobStatistics
- \item Statistics
- \item TimeStatistics
- \end{itemize}
- \item system
- \begin{itemize}
- \item SystemConfiguration
- \end{itemize}
- \item variablesGenerator
- \begin{itemize}
- \item library
- \begin{itemize}
- \item Rngs
- \item Rvgs
- \item Rvms
- \end{itemize}
- \item Arrivals
- \item Clock
- \item InitGenerator
- \item Services
- \end{itemize}
- \end{itemize}
- In seguito sono descritte le entità fondamentali del sistema di simulazione e, in modo sintetico, le loro funzionalità:
- \begin{itemize}
- \item \textbf{Cloud}: classe che implementa il sistema Cloud, occupandosi della gestione dei task in arrivo per prendere servizio al suo interno e del loro processamento
- \item \textbf{cloudlet package}:
- \begin{itemize}
- \item \textbf{Cloudlet}: classe che implementa il sistema Cloudlet, occupandosi della gestione sia dei task in servizio al suo interno sia dei serventi di cui è composto
- \item \textbf{Server}: classe che implementa ogni singolo servente che compone il Cloudlet. \'E descritto dal codice identificativo, dal job attualmente in servizio e da una variabile booleana che indica il suo stato attuale (busy/idle)
- \item \textbf{CloudletController}: classe che implementa il Controller del Cloudlet e che quindi si occupa di effettuare il dispatching dei task in arrivo secondo l'algoritmo stabilito dall'utente
- \item \textbf{DispatchAlgorithm}: classe che implementa gli algoritmi di dispatching
- \end{itemize}
- \item \textbf{event package}:
- \begin{itemize}
- \item \textbf{Event}: classe che rappresenta un generico evento specificato poi dal tipo associato (se arrivo o completamento), dal job che lo ha generato e dal tempo di accadimento
- \item \textbf{EventGenerator}: classe che si occupa della generazione di eventi di arrivo e di completamento
- \item \textbf{CompletionHandler}: classe che si occupa della gestione degli eventi di completamento (specializzati poi a Cloudlet e Cloud)
- \end{itemize}
- \item \textbf{Job}: classe che rappresenta una richiesta di servizio. \'E descritta dalla classe di appartenenza, dal tempo di arrivo e dal tempo di completamento
- \item \textbf{Simulation}: classe che si occupa di avviare la simulazione e di gestire la lista di eventi in modo tale che la simulazione possa avanzare correttamente.
- \item \textbf{statistics package}:
- \begin{itemize}
- \item \textbf{Statistics}: classe di supporto per il campionamento delle statistiche. Implementa l'algoritmo di Welford
- \item \textbf{TimeStatistics}: classe che si occupa del campionamento delle statistiche relative ai tempi di risposta
- \item \textbf{JobStatistics}: classe che si occupa del campionamento delle statistiche relative a popolazioni medie e throughput
- \item \textbf{BatchMeans}: classe che implementa e gestisce le statistiche tramite il metodo dei BatchMeans
- \item \textbf{ConfidenceInterval}: classe che implementa l'algoritmo per il calcolo dell'intervallo di confidenza
- \end{itemize}
- \item \textbf{variablesGenerator package:}
- \begin{itemize}
- \item \textbf{InitGenerator}: classe che si occupa dell'istanziazione delle librerie per la generazione dei numeri random secondo Lehmer (\textbf{rngs}\textbf{rvgs}). Contiene al suo interno anche funzioni per la selezione del SEED iniziale, dello stream e delle distribuzioni
- \item \textbf{Arrivals}: classe che si occupa dell'estrazione randomica dei tempi di arrivo di un task e della determinazione dell'appartenenza alla classe
- \item \textbf{Services}: classe che si occupa dell'estrazione dei tempi di servizio
- \item \textbf{Clock}: classe che istanzia il Clock di simulazione.
- \end{itemize}
- \end{itemize}
- \subsubsection{Inizializzazione}
- Dopo la breve panoramica delle classi che compongono il codice, si può vedere ora come queste vengano inizializzate all'inizio di ogni \textit{run}.
- Lo scopo di questo sotto-paragrafo è spiegare cosa avviene all'inizio della simulazione per alcune classi fondamentali, in modo tale da familiarizzare con gli attributi che le compongono e, di conseguenza, con la struttura del sistema implementato.\\
- Iniziando dal \textbf{Cloudlet}, viene mostrato in Listing \ref{clet_init} cosa avviene appena inizia la simulazione. \\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Inizializzazione del Cloudlet, label={clet_init}]
- private static Cloudlet instance;
- private int n1;
- private int n2;
- private int numberOfServers;
- private ArrayList<Server> serverList;
- private Cloudlet(){
- n1 = 0;
- n2 = 0;
- numberOfServers = SystemConfiguration.N;
- initServers();
- }
- public static Cloudlet getInstance(){
- if(instance == null)
- instance = new Cloudlet();
- return instance;
- }
- private void initServers(){
- serverList = new ArrayList<>();
- for (int i = 0; i<numberOfServers; i++) {
- serverList.add(new Server(i));
- }
- }
- \end{lstlisting}
- \end{minipage}\\
- Il Cloudlet, così come molte delle classi analizzate in questo sotto-paragrafo, è stato implementato usando il pattern \textit{Singleton} per poter avere una sola istanza attiva alla volta e consentire gli aggiornamenti corretti delle variabili di stato del sistema. Nel costruttore, \texttt{n1} e \texttt{n2} rappresentano i Job rispettivamente di classe 1 e 2 attualmente in servizio nel Cloudlet e sono settati a 0 all'inizio della simulazione. I serventi che compongono il Cloudlet sono istanziati tramite \texttt{serverList}, una lista di oggetti di tipo Server. Questa costruzione è un punto di forza della simulazione perché permette non solo di avere statistiche al livello del singolo elemento, ma anche una semplice futura estensione del codice a nuove funzionalità (basti pensare ai casi in cui è necessario avere dati per ogni server, e.g. predictive maintenance dell'infrastruttura).\\
- La classe \textbf{Cloud} risulta più semplice rispetto al Cloudlet. Viene mostrato in Listing \ref{cloudinit}.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Inizializzazione del Cloud, label={cloudinit}]
- private static Cloud instance = new Cloud();
- private int n1;
- private int n2;
- private Cloud(){
- n1 = 0;
- n2 = 0;
- }
- public static Cloud getInstance(){ return instance;}
- \end{lstlisting}
- \end{minipage}\\
- \'E di particolare interesse poi l'inizializzazione delle classi riguardanti le statistiche. Partendo dalla classe \textbf{TimeStatistics}, si noti come la fase di init contenga solamente le variabili legate ai tempi di risposta, come mostrato in Listing \ref{timestat_init}:\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Inizializzazione TimeStatistics, label={timestat_init}]
- private static TimeStatistics instance = null;
- private double meanResponseTime;
- private double meanResponseTimeCloudlet;
- private double meanResponseTimeCloud;
- private double meanResponseTimeClass1;
- private double meanResponseTimeClass2;
- private double meanResponseTimeClass1Cloudlet;
- private double meanResponseTimeClass2Cloudlet;
- private double meanResponseTimeClass1Cloud;
- private double meanResponseTimeClass2Cloud;
- private TimeStatistics(){
- resetStatistics();
- }
- public static TimeStatistics getInstance()
- {
- if(instance == null)
- instance = new TimeStatistics();
- return instance;
- }
- public void resetStatistics(){
- this.meanResponseTime = 0.0;
- this.meanResponseTimeCloudlet = 0.0;
- this.meanResponseTimeCloud = 0.0;
- this.meanResponseTimeClass1 = 0.0;
- this.meanResponseTimeClass2 = 0.0;
- this.meanResponseTimeClass1Cloudlet = 0.0;
- this.meanResponseTimeClass2Cloudlet = 0.0;
- this.meanResponseTimeClass1Cloud = 0.0;
- this.meanResponseTimeClass2Cloud = 0.0;
- }
- \end{lstlisting}
- \end{minipage}\\
- Per quanto riguarda popolazioni e throughput è stata utilizzata la classe \textbf{JobStatistics}. L'inizializzazione è mostrata in Listing \ref{jobstat_init}. Per evitare di ripetere il procedimento banale di settare tutte le variabili al valore 0, viene nel codice omessa la funzione \texttt{resetStatistics}.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Inizializzazione JobStatistics, label={jobstat_init}]
- private static JobStatistics instance = null;
- private static Statistics statistics;
- private static BatchMeans batchMeans;
- //POPULATION MEANS
- private double meanGlobalPopulation;
- private double meanCloudletPopulation;
- private double meanCloudPopulation;
- private double meanGlobalPopulation_1;
- private double meanCloudletPopulation_1;
- private double meanCloudPopulation_1;
- private double meanGlobalPopulation_2;
- private double meanCloudletPopulation_2;
- private double meanCloudPopulation_2;
- //POPULATION VARIANCE
- private double varGlobalPopulation;
- private double varCloudletPopulation;
- private double varCloudPopulation;
- private double varGlobalPopulation_1;
- private double varCloudletPopulation_1;
- private double varCloudPopulation_1;
- private double varGlobalPopulation_2;
- private double varCloudletPopulation_2;
- private double varCloudPopulation_2;
- //COMPLETED
- private long completedCloudlet_1;
- private long completedCloudlet_2;
- private long completedCloud_1;
- private long completedCloud_2;
- //ITERATIONS & CLOCK
- private long globalIteration;
- private long actualIteration;
- private double globalTime;
- private double actualTime;
- private double batchSize;
- private int actualBatch;
- private JobStatistics(){
- resetStatistics();
- }
- public static JobStatistics getInstance(){
- if(instance == null)
- instance = new JobStatistics();
- return instance;
- }
- \end{lstlisting}
- \end{minipage}\\
- Per quanto riguarda la classe \textbf{Batch}, per ciascuna delle variabili riportate in Listing \ref{batch_init} viene inizializzato un nuovo \texttt{ArrayList} di \texttt{Double} che serve a contenere le medie campionate per ogni singolo Batch relative alla statistica di interesse:\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Inizializzazione Batch, label={batch_init}]
- //BATCH MEANS
- private ArrayList<Double> BMGlobalPopulation;
- private ArrayList<Double> BMCloudletPopulation;
- private ArrayList<Double> BMCloudPopulation;
- private ArrayList<Double> BMGlobalPopulation_1;
- private ArrayList<Double> BMCloudletPopulation_1;
- private ArrayList<Double> BMCloudPopulation_1;
- private ArrayList<Double> BMGlobalPopulation_2;
- private ArrayList<Double> BMCloudletPopulation_2;
- private ArrayList<Double> BMCloudPopulation_2;
- //BATCH VARIANCE
- private ArrayList<Double> BMVarGlobalPopulation;
- private ArrayList<Double> BMVarCloudletPopulation;
- private ArrayList<Double> BMVarCloudPopulation;
- private ArrayList<Double> BMVarGlobalPopulation_1;
- private ArrayList<Double> BMVarCloudletPopulation_1;
- private ArrayList<Double> BMVarCloudPopulation_1;
- private ArrayList<Double> BMVarGlobalPopulation_2;
- private ArrayList<Double> BMVarCloudletPopulation_2;
- private ArrayList<Double> BMVarCloudPopulation_2;
- //THROUGHPUT
- private ArrayList<Double> avgSystemT;
- private ArrayList<Double> avgCloudletT;
- private ArrayList<Double> avgCloudT;
- private ArrayList<Double> avgSystemT1;
- private ArrayList<Double> avgCloudletT1;
- private ArrayList<Double> avgCloudT1;
- private ArrayList<Double> avgSystemT2;
- private ArrayList<Double> avgCloudletT2;
- private ArrayList<Double> avgCloudT2;
- private ArrayList<Double> varSystemT;
- private ArrayList<Double> varCloudletT;
- private ArrayList<Double> varCloudT;
- \end{lstlisting}
- \end{minipage}
- Per terminare la panoramica sull'inizializzazione, è importante menzionare la classe \textbf{SystemConfiguration}, avente il compito di scansionare il file di configurazione ed estrarre tutti i parametri necessari alla simulazione:
- \subsubsection{Run}
- Il \texttt{main} della simulazione si trova nella classe \textbf{Simulation} e viene riportato in Listing \ref{main}. \\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=main della simulazione, label={main}]
- private static void run(){
- initialize();
- for(int i = 0; i < SystemConfiguration.ITERATIONS; i++){
- Event e = EventGenerator.getInstance().
- generateArrival();
- eventList.add(e);
- sortEventList();
- handleEvent();
- }
- jobStatistics.
- setGlobalTime(jobStatistics.getGlobalTime() +
- handleEvent());
- }
- \end{lstlisting}
- \end{minipage}\\
- Tramite \texttt{initialize()} viene inizializzato l'\texttt{ArrayList eventList}, e vengono settati i parametri come indicati nel file di configurazione. Vengono poi salvate istanze di alcune classi, in modo da rendere il codice più leggibile.
- Per ogni ciclo viene generato un nuovo evento di tipo arrivo. Ad ogni evento viene associato il tempo di arrivo, la classe e, se abilitato nel file di configurazione, la size del job\footnote{per maggiori informazioni vedere \ref{operation_enabled}}. In Listing \ref{eventGenerator} sono mostrate le fasi di generazione del tempo di arrivo (o più correttamente, di inter-arrivo) e di decisione della classe.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Generazione di un evento, label={eventGenerator}]
- public Event generateArrival(){
- double arrival = Arrivals.getInstance().
- getArrival();
- Job job;
- if(SystemConfiguration.OPERATIONS_ENABLED)
- job = new Job(Arrivals.getInstance().
- determineJobClass(),
- arrival,
- Services.getInstance().
- getJobOperations());
- else
- job = new Job(Arrivals.getInstance().
- determineJobClass(),
- arrival, 0);
- return new Event(0, job);
- }
- /**
- * Return arrival times
- */
- public double getArrival(){
- double total_rate = getTotalRate();
- return exponential(total_rate,0);
- }
- public double exponential(double rate, int stream){
- selectStream(stream);
- return this.rvgs.exponential(1/rate);
- }
- /**
- * Return job class
- */
- public int determineJobClass(){
- double p1 =
- SystemConfiguration.ARRIVAL_RATE_1/getTotalRate();
- double p = init.uniform();
- if(p <= p1){
- return 1;
- }
- else {
- return 2;
- }
- }
- \end{lstlisting}
- \end{minipage}\\
- Una volta generato un evento di tipo arrivo, questo viene inserito nella \texttt{eventList}. Questa viene ordinata con il metodo presentato in Listing \ref{sort}.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Ordinamento della eventList, label={sort}]
- private static void sortEventList(){
- eventList.sort((o1, o2) -> {
- if (o1.getEventTime() < o2.getEventTime())
- return -1;
- else if(o1.getEventTime() == o2.getEventTime()){
- if(o1.getType() != 0)
- return -1;
- else
- return 1;
- }
- else
- return 1;
- });
- }
- \end{lstlisting}
- \end{minipage}\\
- A questo punto viene chiamata la funzione \texttt{handleEvent()}. Si scorre la lista ordinata e si prende il primo evento disponibile, se esiste (cosa vera a meno che non si parli del termine della simulazione). Dopo aver preso le attuali popolazioni dei due sistemi si analizza effettivamente l'elemento estratto. Se l'evento è un completamento allora questo deve essere processato dal sistema di riferimento. In alternativa il pacchetto deve essere smistato e il tempo aggiornato. In caso di evento di tipo arrivo, i tempi relativi ai completamenti rimanenti nella eventList vengono decrementati. Questo comportamento viene mostrato in Listing \ref{handleEvent} .\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=gestione della eventList, label={handleEvent}]
- private static double handleEvent(){
- for (Event event: eventList)
- event.setValid(true);
- Iterator i = eventList.iterator();
- double time = 0;
- int[] numberOfJobsInCloudlet = {0,0};
- int[] numberOfJobsInCloud = {0,0};
- while(i.hasNext()){
- numberOfJobsInCloudlet = Cloudlet.getInstance().
- getJobsInCloudlet();
- numberOfJobsInCloud = Cloud.getInstance().
- returnJobsInCloud();
- Event e = (Event) i.next();
- time = e.getEventTime();
- if(e.getType() == 0){ // arrival
- break;
- }
- else if(e.getType() == 1){ // cloudlet
- if(e.isValid()) {
- cloudlet.processCompletion(e);
- i.remove();
- }
- }
- else{ // cloud
- if(e.isValid()) {
- cloud.processCompletion(e);
- i.remove();
- }
- }
- }
- if(eventList.size() != 0) {
- jobStatistics.updatePopulationMeans(
- numberOfJobsInCloudlet,
- numberOfJobsInCloud);
- Event e = eventList.get(0);
- cloudletController.dispatchArrivals(e);
- jobStatistics.setGlobalTime(
- jobStatistics.getGlobalTime() +
- e.getJob().getArrivalTime());
- jobStatistics.setActualTime(
- jobStatistics.getActualTime() +
- e.getJob().getArrivalTime());
- eventList.remove(0);
- for (Event event : eventList) {
- if(event.isValid())
- event.setEventTime(
- event.getEventTime() - time);
- }
- }
- else
- return time;
- return 0;
- }
- \end{lstlisting}
- \end{minipage}\\
- Il motivo per cui all'inizio tutti gli eventi vengono settati a \texttt{TRUE} è dato dal fatto che ad ogni arrivo corrisponde un nuovo completamento. Ogni completamento generato durante il ciclo ha \texttt{isValid = FALSE} e, al termine del ciclo, questo non subisce lo scorrere del tempo.
- In caso di termine della simulazione la funzione ritorna il valore dell'ultimo completamento. In questo modo è possibile aggiornare correttamente il clock.\\
- In caso di evento di tipo arrivo viene chiamata la funzione \texttt{dispatchArrivals(e)}. Sulla base di quanto settato nel file di configurazione, viene scelto l'algoritmo di dispatch. Essendo un argomento affrontato nel dettaglio nel paragrafo \ref{algoritmi_dispatch}, viene qui riportato solamente il comportamento del sistema con algoritmo standard.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Gestione degli arrivi, label={dispatch}]
- public void dispatchArrivals(Event e){
- DispatchAlgorithm.getInstance().getAlgorithm(e);
- }
- public void getAlgorithm(Event e){
- switch (algorithmType){
- case 1: defaultAlgorithm(e);
- break;
- case 2: sizeBasedBAlgorithm(e);
- break;
- case 3: firstClassinCloudletAlgorithm(e);
- break;
- case 4: thresholdAlgorithm(e,
- SystemConfiguration.THRESHOLD);
- break;
- }
- }
- /**
- * Basic algoritm
- */
- public void defaultAlgorithm(Event e){
- int[] numberOfJobsInCloudlet = Cloudlet.getInstance().getJobsInCloudlet();
- int totalJobsInCloudlet = numberOfJobsInCloudlet[0] + numberOfJobsInCloudlet[1];
- if(totalJobsInCloudlet == numberOfServers)
- Cloud.getInstance().processArrival(e);
- else
- Cloudlet.getInstance().processArrival(e);
- }
- \end{lstlisting}
- \end{minipage}\\
- Nel caso in cui il processamento del Job venga affidato al Cloudlet, la prima operazione effettuata è l'associazione di un tempo di completamento al pacchetto. Successivamente il Job viene affidato al primo Server libero della lista e viene generato un evento di tipo completamento. Lo stato del sistema viene inoltre aggiornato, tenendo conto della classe da processare.
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Arrivo al Cloudlet, label={arrival_cloudlet}]
- public void processArrival(Event e) {
- Job job = e.getJob();
- double completionTime =
- Services.getInstance().getCloudletServiceTime(
- job.getJobClass(),
- job.getOperations());
- int i = 0;
- for(Server s: serverList){
- if(!s.isBusy()){
- increaseN(job.getJobClass());
- s.setBusy(true);
- job.setCompletionTime(completionTime);
- s.setJobInService(job);
- sendCompletionToSimulation(job, i);
- break;
- }
- i++;
- }
- }
- \end{lstlisting}
- \end{minipage}\\
- Nel caso in cui il Job sia inviato al Cloud, il metodo diventa ancora più semplice, non dovendo tenere conto delle statistiche a livello del singolo Server. Il procedimento è analogo a quanto visto per il caso del Cloudlet e viene riportato in Listing \ref{arrival_cloud}.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Arrivo al Cloud, label={arrival_cloud}]
- public void processArrival(Event e) {
- Job j = e.getJob();
- int jobclass = j.getJobClass();
- double completionTime =
- Services.getInstance().getCloudServiceTime(
- jobclass,
- j.getOperations());
- j.setCompletionTime(completionTime);
- increaseN(jobclass);
- sendCompletionToSimulation(j);
- }
- \end{lstlisting}
- \end{minipage}\\
- Il metodo \texttt{sendCompletionToSimulation} si occupa di aggiungere un nuovo evento di tipo completamento alla event-list. \\
- La generazione dei tempi di servizio è semplice ma richiede un gran numero di funzioni. Il sistema deve infatti tenere conto della classe del Job, del sistema che sta effettuando il processamento, della distribuzione scelta dall'utente e dall'uso o meno della size. Le operazioni \texttt{getCloudletServiceTime} e \texttt{getCloudServiceTime}, riportate in Listing \ref{getServiceTime}, permettono la chiamata della funzione corretta. \\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Funzioni per tempo di servizio, label={getServiceTime}]
- // SERVICE TIME CLOUD
- public double getCloudServiceTime(int jobclass,
- double numberOfOperations){
- if(SystemConfiguration.OPERATIONS_ENABLED)
- return getCloudServiceTimePerOperation(
- jobclass, numberOfOperations);
- else
- return
- getCloudServiceTimeWithoutOperations(jobclass);
- }
- // SERVICE TIME CLOUDLET
- public double getCloudletServiceTime(int jobclass,
- double numberOfOperations){
- //hyperexponential using operations
- if(SystemConfiguration.HYPEREXPO_ENABLED &&
- SystemConfiguration.OPERATIONS_ENABLED)
- return
- getCloudletHyperExpServiceTimePerOperation(
- jobclass, numberOfOperations);
- //hyperexponential without using operations
- else if (SystemConfiguration.HYPEREXPO_ENABLED)
- return
- getCloudletHyperExpServiceTimeWithoutOperations(jobclass);
- //exponential using operations
- else if(SystemConfiguration.OPERATIONS_ENABLED)
- return
- getCloudletExpServiceTimePerOperation(jobclass,
- numberOfOperations);
- //exponential without using operations
- else
- return
- getCloudletServiceTimeWithoutOperations(jobclass);
- }
- \end{lstlisting}
- \end{minipage}\\
- Per non appesantire questa discussione viene qui riportata in Listing \ref{getCloudletExpo} solo una delle varie funzioni che permettono di generare un corretto tempo di servizio. La differenza con le altre risiede principalmente nella scelta dello stream e del tasso utilizzato come parametro della distribuzione desiderata. \\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Tempo di servizio per il Cloudlet - distribuzione esponenziale, label={getCloudletExpo}]
- private double getCloudletServiceTimeWithoutOperations(int job_class){
- double service_rate;
- int stream;
- if(job_class == 1) {
- service_rate = SystemConfiguration.CLOUDLET_M1;
- stream = 2;
- }
- else {
- service_rate = SystemConfiguration.CLOUDLET_M2;
- stream = 3;
- }
- return InitGenerator.getInstance().
- exponential(service_rate, stream);
- }
- public double exponential(double rate, int stream){
- selectStream(stream);
- return this.rvgs.exponential(1/rate);
- }
- \end{lstlisting}
- \end{minipage}\\
- Esaminando brevemente la funzione \texttt{handleEvent} (in Listing \ref{handleEvent}) si può notare che l'aggiornamento delle popolazioni medie viene eseguito prima di ogni processamento dell'evento di tipo arrivo. Per calcolare le diverse medie viene utilizzato l'algoritmo di Welford, riportato in Listing \ref{welford}\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Algoritmo di Welford, label={welford}]
- public double[] computeMeanAndVariance(double oldVar,
- double oldMean, double newValue, long n){
- double diff = (newValue - oldMean);
- double[] MV = new double[2];
- MV[1] = oldVar + diff * diff * (n - 1) / n;
- MV[0] = oldMean + (diff / n);
- return MV;
- }
- \end{lstlisting}
- \end{minipage}\\
- Supponiamo ora che l'evento estratto dalla event-list sia una completamento. Anche in questo caso i metodi relativi a Cloudlet e Cloud sono molto simili e differiscono solo nella gestione dei server. In Listing \ref{comparisoncletcloud}.\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=Completamento in Cloudlet e Cloud, label={comparisoncletcloud}]
- //CLOUDLET
- public void processCompletion(Event e){
- Server s = serverList.get(e.getAdditionalInfo());
- if(!s.isBusy())
- System.exit(-1);
- s.setBusy(false);
- decreaseN(s.getJobInService().getJobClass());
- CompletionHandler.getInstance().handleCompletion(
- EventGenerator.getInstance().
- generateCompletion(1, s.getJobInService()));
- }
- //CLOUD
- public void processCompletion(Event e){
- decreaseN(e.getJob().getJobClass());
- CompletionHandler.getInstance().handleCompletion(
- EventGenerator.getInstance().
- generateCompletion(2, e.getJob()));
- }
- //GENERATE COMPLETION
- public Event generateCompletion(int cloudletOrCloud, Job job){
- if(cloudletOrCloud == 1 || cloudletOrCloud == 2)
- return new Event(cloudletOrCloud, job);
- else
- return null;
- }
- \end{lstlisting}
- \end{minipage}\\
- La funzione \texttt{handleCompletion} effettua l'aggiornamento dei tempi di risposta relativi a classe e sistema, utilizzando l'algoritmo di Welford per il calcolo della media, esattamente come avviene per la popolazione media.\\
- In questo paragrafo è stata quindi riportata una panoramica riguardante l'implementazione del flusso riportato in figura \ref{flusso_eventi}. La spiegazione delle funzioni \textit{core} della simulazione non è certamente sufficiente per dimostrare la robustezza e la bontà del codice. Per quanto sarebbe interessante approfondire ogni scelta effettuata nella fase di sviluppo, la trattazione risulterebbe eccessivamente lunga. Per questo motivo, per ulteriori approfondimenti riguardanti il codice e la teoria su cui si basa, si rimanda il lettore allo studio del capitolo \ref{implementazione} e alla lettura del codice allegato a questa discussione.
- \subsection{Verifica}
- La simulazione è stata sottoposta a verifica per capire se il modello computazionale fosse consistente con il modello delle specifiche. Ci si è posti la seguente domanda:
- \begin{center}
- \textit{Stiamo implementando il modello in modo corretto?}
- \end{center}
- Il paper \textit{Verifying and Validating Simulation Models, R. G. Sargent} \cite{verify} suggerisce alcuni metodi di verifica di un modello.
- In particolare è stato utilizzato il \textbf{dynamic testing}, approccio attraverso cui il software viene testato sotto diverse condizioni. Tecniche comunemente usate nel dynamic testing sono
- \begin{itemize}
- \item studio della relazione tra differenti input-output per la verifica della coerenza e l'investigazione sulla presenza di anomalie;
- \item check di consistenza sui singoli oggetti protratti per tutto lo sviluppo del codice;
- \item riprogrammazione di componenti core della simulazione con lo scopo di determinare se i risultati ottenuti sono equivalenti.
- \end{itemize}
- Il processo di verifica ha quindi coinvolto nella sua interezza la fase di sviluppo del codice, permettendo di ottenere sempre risultati coerenti con il modello delle specifiche.
- \subsection{Validazione}
- Mentre tramite il processo di verifica si esamina la consistenza tra il modello computazionale e quello delle specifiche, con il processo di validazione si pone il focus sulla consistenza tra il modello computazionale ed il sistema che si sta analizzando. La domanda fondamentale di questa fase è quindi:
- \begin{center}
- \textit{Stiamo implementando il modello giusto?}
- \end{center}
- Per rispondere, si può fare ancora riferimento a \cite{verify}. Secondo Sargent esistono tre diversi approcci per confermare la validazione di un modello, in seguito descritti brevemente.
- Il primo approccio viene chiamato Independent Verification and Validation (\textbf{IV\&V}). Questo prevede la presenza di una persona esterna al team di sviluppo e al committente che, tramite la sua professionalità ed esperienza, decida (in modo soggettivo) della validità del sistema. Un altro modo - più oggettivo - si basa sul confronto dei risultati della simulazione con l'output di un sistema reale: se l'esperto non riesce a distinguere con certezza il sistema simulato da quello reale, allora si può dire che il modello sia valido.
- Il secondo approccio, sconsigliato dall'autore del paper, si basa sull'utilizzo di \textit{score}: a diversi aspetti del modello vengono associati dei punteggi e se la simulazione li supera, allora può essere considerata valida. Il problema risiede nella difficoltà di individuare sia i valori degli Score, sia le categorie da dover valutare. Non esistendo metriche universali (e non potrebbe essere altrimenti data l'unicità di ciascuna simulazione) si tenta quindi di dare valore oggettivo a qualcosa che per natura non è oggettivo.
- L'ultimo approccio è sicuramente il più adottato e il più semplice: la validità di un modello viene confermata dal team di sviluppo sulla base di test e valutazioni protratti lungo tutto il corso del processo di implementazione.
- Quest'ultimo è stato il metodo scelto. di seguito sono elencati alcuni dei test che il team ha effettuato per confermare la validità del modello:
- \begin{labeling}{Comparison to other models aaa}
- \item [\textbf{Extreme-Condition Test}:] il comportamento del sistema è risultato plausibile in caso di condizioni limite quali
- aumento/diminuzione drastica prima del flusso entrante e poi dei tassi di servizio e presenza di 0 o infiniti server nel Cloudlet
- \item[\textbf{Event Validity Test}:] Gli eventi generati dalla simulazione sono coerenti con quelli di un caso reale
- \item[\textbf{Comparison to other models}:] i risultati ottenuti dalla simulazione sono stati comparati con quelli ottenuti da un corretto modello analitico
- \end{labeling}
- \newpage
- \section{Implementazione}\label{implementazione}
- Il modello delle specifiche ed in seguito il modello computazionale hanno portato allo sviluppo di un'applicazione di simulazione in Java. All'interno della stessa si trovano anche dei componenti non previsti dai modelli elencati ma che inglobano funzionalità prettamente di ausilio (vedere capitolo Features Aggiuntive).
- \subsection{Features aggiuntive}
- In questo paragrafo vengono descritte le varie funzionalità aggiuntive della simulazione. Queste feature non sono indispensabili per il funzionamento del flusso di base ma lasciano all'utente la libertà di modificare a proprio piacimento alcune caratteristiche riguardanti modalità di esecuzione della simulazione o varianti nell'implementazione.
- \subsubsection{Verbose e CSVlogger}
- Le prime feature analizzate sono certamente le più semplici e riguardano la gestione dell'output della simulazione. I parametri \texttt{VERBOSE} e \texttt{CSVLOGGER} controllano queste funzioni ed essendo booleani possono essere attivati o disattivati tramite i valori \texttt{true} o \texttt{false}.
- Settando a true la verbosità è possibile stampare in console i risultati ottenuti al termine della simulazione. Le stampe riguardano i seguenti valori:
- \begin{itemize}
- \item percentuale di completamento della simulazione
- \item parametri della simulazione quali arrival rate, service rate, numero di server nel Cloudlet e seed
- \item probabilità di perdita del Cloudlet
- \item throughput
- \item completamenti
- \item tempi di servizio
- \item popolazioni medie
- \item performance della simulazione riguardanti tempo reale, tempo simulato e RAM utilizzata
- \end{itemize}
- Anche settando a false il parametro della verbosità alcune stampe non invasive saranno comunque presenti. I risultati in consolle vengono stampati a schermo tramite la classe \textbf{PerformanceLogger} e la classe \textbf{Printer}, che si occupa di aspetti puramente di estetica della grafica di output.
- \texttt{CSVLOGGER} è invece il parametro attraverso cui l'utente decide se scrivere su file o no i risultati ottenuti. I file sono i seguenti:
- \begin{itemize}
- \item \textbf{AVGjobs.csv}: file scritto in modalità append. Ogni volta che viene eseguita la simulazione viene aggiunta una riga con i risultati riguardanti le popolazioni medie per ciascuna classe e sistema
- \item \textbf{BatchMeans.csv}: file sovrascritto ogni volta che viene avviata la simulazione. Presenta per ogni batch i valori relativi alle popolazioni medie per classe e sistema. Contiene quindi tante righe quanti sono i batch scelti e viene scritto solamente se il parametro \textit{BATCH} nel file di configurazione ha come flag \textit{true}
- \item \textbf{MeansInOneSimulation.csv}: file sovrascritto ogni volta che viene avviata la simulazione. Contiene 2000 righe e ciascuna rappresenta la popolazione media di sistema e classi considerando la corrente iterazione e le precedenti. Questo permette di osservare la transizione dello stato del sistema da una situazione iniziale in cui questo è vuoto verso la stazionarietà.
- \item \textbf{ResponseTime.csv}: file scritto in modalità append. Ogni volta che viene eseguita la simulazione viene aggiunta una riga con i risultati riguardanti il tempo medio di servizio per ciascuna classe e sistema
- \item \textbf{ResponseTimeMeansInOneSimulation.csv}: file sovrascritto ogni volta che viene avviata la simulazione. Contiene tante righe quanti sono i pacchetti inviati durante la simulazione. Per questo motivo, al fine di evitare dimensioni eccessive, le informazioni salvate per ciascuna riga sono ridotte al minimo. Per ogni Job vengono infatti salvati solo i dati relativi alla classe, a chi ha completato la richiesta e quale è stato il tempo di servizio.
- \item \textbf{ServerStatus.csv}: file sovrascritto ogni volta che viene avviata la simulazione. Contiene tante righe quanti sono i server presenti nel Cloudlet e per ciascuno di questi riporta l'utilizzazione e i pacchetti completati.
- \item \textbf{SystemSimulation.csv}: file scritto in modalità append. Per ciascun Run della simulazione vengono riportate scritte le informazioni relative alle performance. In particolare per questo semplice caso sono scritti tempo reale di esecuzione, tempo di simulazione e RAM utilizzata dal processo.
- \item \textbf{Throughput.csv} \textcolor{red}{file scritto in modalità append. Ogni volta che viene eseguira la simulazione viene aggiunta. una riga con i risultati riguardanti il throughput globale e per classe}.
- \item \textbf{ThroughputBatch.csv} \textcolor{red}{TODO}
- \item \textbf{BatchMeansPopulationCI.csv} \textcolor{red}{TODO}
- \item \textbf{BatchVariances.csv} \textcolor{red}{TODO}
- \item \textbf{VarianceJobs.csv} \textcolor{red}{TODO}
- \end{itemize}
- \subsection{File di configurazione}
- Il file di configurazione \textit{config.properties} all'interno della directory \textit{resources} è stato ideato per consentire all'utente di settare e modificare i parametri fondamentali di simulazione in modo tale da poter interagire attivamente con il sistema. Illustriamo dunque le funzionalità e le possibili configurazioni per ogni parametro presente nel file:
- \begin{itemize}
- \item ARRIVAL\_RATE\_1: tasso di arrivi della classe 1;
- \item ARRIVAL\_RATE\_2: tasso di arrivi della classe 2;
- \item CLOUDLET\_M1: tasso di servizio dei task di classe 1 da parte del Cloudlet;
- \item CLOUDLET\_M1: tasso di servizio dei task di classe 2 da parte del Cloudlet;
- \item CLOUD\_M1: tasso di servizio dei task di classe 1 da parte del Cloud;
- \item CLOUD\_M2: tasso di servizio dei task di classe 2 da parte del Cloud;
- \item N: consente di impostare il numero di server che formano il Cloudlet;
- \item HYPEREXPOENABLED (boolean): se pari a \textit{false} la distribuzione dei tempi di servizio del Cloudlet sarà esponenziale, altrimenti sarà iper-esponenziale;
- \item PHASE\_P: consente di settare la fase in caso di distribuzione iper-esponenziale;
- \item OPERATIONS\_ENABLED (boolean): se settato a \texttt{true} impone alla simulazione di associare un numero di operazioni richieste ad ogni job.
- \item SEED: consente di impostare il SEED della simulazione
- \item ITERATIONS: consente di impostare la durata della simulazione;
- \item ALGORITHM: consente di decidere l'algoritmo di dispatching. Può assumere quattro diversi valori:
- \begin{enumerate}
- \item algoritmo standard (default);
- \item algoritmo size-based;
- \item algoritmo \textit{first class on Cloudlet};
- \item algoritmo basato su soglia \textit{threshold algorithm};
- \end{enumerate}standard
- \item THRESHOLD: consente di selezionare il valore di soglia per l'algoritmo 4;
- \item BATCH (boolean): se impostato a \textit{true} la simulazione utilizzerà il metodo dei \textit{Batch Means};
- \item NUM\_BATCH: consente di impostare il numero di batch per la simulazione (impostato a 64 per default);
- \item VERBOSE (boolean): se impostato a \texttt{true} aumenta la quantità di log stampati su console
- \item MULTI\_RUN (boolean): se impostato a \texttt{true} permette l'esecuzione consecutiva della simulazione cambiando in modo automatico il SEED. Viene utilizzato insieme al parametro \texttt{RUNS} che decide il numero di volte che la simulazione dovrà essere eseguita.
- \item CSV\_LOGGER (boolean): abilita la scrittura su file .csv delle statistiche collezionate durante la simulazione.
- \end{itemize}
- Nel paragrafo 4.2 verranno spiegati nel dettaglio il funzionamento di VERBOSE, MULTI\_RUN, CSV\_LOGGER e ALGORITHM.
- \subsubsection{Multi-Run}
- Avviare la simulazione in modalità \textit{Multi-Run} permette di eseguire più volte il processo utilizzando seed diversi. Per usare questa funzionalità bisogna settare il parametro \textit{MULTI\_RUN} a true e decidere il numero di cicli imponendo \textit{RUNS} al numero voluto.
- Si noti che l'utilizzo del multi-run disabilita automaticamente la verbosità ed impedisce al programma di scrivere sui file \textit{ResponseTimeMeansInOneSimulation.csv} e \textit{MeansInOneSimulation.csv}. Questo al fine di evitare inutili scritture su file che verranno sovrascritti all'inizio di ciascun nuovo ciclo.
- Per il primo ciclo della simulazione il programma utilizza il seed imposto dall'utente in fase di configurazione. Il seed utilizzato per il ciclo i-esimo è dato da \textit{SEED} + i.
- \newpage
- \subsection{Algoritmi di dispatching}\label{algoritmi_dispatcher}
- Uno degli obiettivi principali di qualsiasi simulazione dovrebbe sempre essere quello di osservare come i risultati ottenuti dal processo varino a seconda dei diversi parametri in input e delle scelte algoritmiche adottabili. Per questo motivo è stata posta molta cura nel concedere più libertà possibile all'utente in fase di scelta dell'algoritmo di dispatching, elemento considerato fondamentale per gli scopi della simulazione.
- Per scegliere la condizione di smistamento è possibile andare a modificare il parametro \texttt{ALGORITHM} presente nel file di configurazione. Di seguito vengono descritte a fondo le differenti soluzioni.
- \subsubsection{Algoritmo di default}
- L'algoritmo più semplice adottabile dal controllo è certamente il \textbf{default algorithm}, corrispondente al valore 1 del parametro \texttt{ALGORITHM}. Essendo stato analizzato abbondantemente nei precedenti capitoli, viene qui solo riassunto il suo funzionamento \\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Python, caption=default algorithm, label={dispatch1}]
- if(event is an arrival){
- if(totalJobsInCloudlet == numberOfServers){
- Cloud.processArrival(e);
- }
- else{
- Cloudlet.processArrival(e);
- }
- }
- \end{lstlisting}
- \end{minipage}
- \subsubsection{Algoritmo alternativo 1: size-based non-preemptive}
- Il primo metodo di dispatching alternativo che l'utente può scegliere è l'algoritmo \textbf{size based}, corrispondente al valore 2 del parametro \texttt{ALGORITHM}. Per poter garantire la corretta esecuzione è necessario inoltre settare a \texttt{true} il parametro \texttt{OPERATIONS\_ENABLED}\footnote{ i dettagli del parametro in questione sono presentati nel paragrafo \ref{operation_enabled}}.\\
- Seguendo l'algoritmo descritto in Listing \ref{dispatch2}, si supponga di inviare nel Cloudlet soltanto i task aventi tempo di servizio inferiore alla media. Dalla teoria si ha che $ P(size < E[S]) = 0.6332$. In generale il tempo di servizio di ciascuna classe è dato da
- \begin{center}
- $E[S_k] = \int_{x_{k-1}}^{x_k} t f^n(t) dt = \int_{x_{k-1}}^{x_k} t \frac{\mu e^{-\mu t}}{F(x_k)-F(x_{k-1})} = \int_{x_{k-1}}^{x_k} t \frac{\mu e^{-\mu t}}{p_k} dt$
- \end{center}
- Nel caso specifico di $size < E[S]$ si ha che
- \begin{center}
- $E[S_1] = \int_{0}^{\frac{1}{\mu}} t \frac{\mu e^{-\mu t}}{0.6332} dt$
- \end{center}
- Per ciascuna classe quindi
- \begin{center}
- $E[S_1_{class\_1}] = \int_{0}^{\frac{1}{\mu_{1\_clet}}} t \frac{\mu e^{-\mu t}}{0.6332} dt$
- \end{center}
- \begin{center}
- $E[S_1_{class\_1}] = \int_{0}^{\frac{1}{\mu_{1\_clet}}} t \frac{\mu_{1\_clet} e^{-\mu_{1\_clet} t}}{0.6332} dt = \int_{0}^{\frac{1}{0.45}} t \frac{0.45 e^{-0.45 t}}{0.6332} dt = 0.927354 $ s \\~\\
- $E[S_1_{class\_2}] = \int_{0}^{\frac{1}{\mu_{2\_clet}}} t \frac{\mu_{2\_clet} e^{-\mu_{2\_clet} t}}{0.6332} dt = \int_{0}^{\frac{1}{0.27}} t \frac{0.27 e^{-0.27 t}}{0.6332} dt = 1.545 $ s
- \end{center}
- A questo punto è possibile risolvere il sistema presentato al paragrafo \ref{system} con i seguenti parametri:\\
- \begin{center}
- $\lambda'_{1\_clet} = 6.00*0.6332 = 3.7992 $\\
- $\lambda'_{2\_clet} = 6.25*0.6332 = 3.9575 $\\
- $\mu'_{1\_clet} = \frac{1}{0.927354} = 1.0783 $\\
- $\mu'_{2\_clet} = \frac{1}{1.5456} = 0.6470 $\\
- \end{center}
- \'E quindi è possibile ricavare i nuovi risultati analitici:\\
- \begin{center}
- %probabilità che il Cloudlet sia saturo
- $P_{loss}\footnote{Indica la probabilità che il Cloudlet sia saturo} = 0.723346 $
- %lambda_in_cloudlet totale
- $\lambda'_{tot\_clet} = (1-P_{loss})*(0.6332*(\lambda'_{1\_clet}) + 0.6332*(\lambda'_{2\_clet})= 2.145922 $ tasks/s\\~\\
- %lambda_in_cloud totale
- $\lambda'_{tot\_cloud} = P_{loss}*((\lambda'_{1\_clet} * 0.6332) + (\lambda'_{2\_clet}* 0.6332)) + \lambda_{tot}*(0.3668) = 10.096728 $ tasks/s \\~\\
- $ E[T_{clet}] = \frac{\lambda_{1\_in\_clet}}{\lambda_{clet}}*E[T_{1\_clet}] + \frac{\lambda_{2\_in\_clet}}{\lambda_{clet}}* E[T_{2\_clet}] = 1.23992848$ s\\~\\
- $E[T_{1\_clet}] = E[S_1_{class\_1}] = 0.927354 $ s\\~\\
- $E[T_{2\_clet}] = E[S_1_{class\_2}] = 1.545 $ s\\~\\
- $E[T_{1\_cloud}] = (P(size > E[S])* \int_{1/\mu_{1\_cloud}}^{\infty} t \frac{\mu_{1\_cloud} e^{-\mu_{1\_cloud} t}}{0.3668} dt) + (P(size < E[S])* \int_{0}^{1/\mu_{1\_cloud}} t \frac{\mu_{1\_cloud} e^{-\mu_{1\_cloud} t}}{0.3668} dt)
- = \int_{0}^{\frac{1}{0.25}} t \frac{0.25 e^{-0.25 t}}{0.3668} dt = 8.02354*0.3668 + (1.66924*0.6332) = $ s \\~\\
- $E[T_{1\_cloud}] = P(size > E[S])(p_{class1}(tempo di risposta job grandi classe 1) + (p_{class2}(tempo di risposta job grandi classe 2)) + (P(size < E[S]))(P_{loss})(p_{class1}(tempo di risposta job piccoli classe 1) + (p_{class2}(tempo di risposta job piccoli classe 2))$
- $E[T_{2\_cloud}] = $ s\\~\\
- $E[T_{cloud}]= $ s\\~\\
- $E[N_{clet}] = $
- $E[N_{1\_cloud}] = 19.028272 $\\~\\
- $E[N_{2\_cloud}] = 28.40906 $\\~\\
- $E[N_{cloud}] = $\\~\\
- \end{center}
- TODO SPECIFICARE BENE COSA RAPPRESENTA PLOSS!!!!!!!
- TODO SPECIFICARE BENE I LAMBDA
- Bisogna specificare che $P_{loss}$ non è la probabilità di entrare nel Cloud. Quest'ultima può essere calcolata come
- \begin{center}
- $P(size > E[S]) + (P(size < E[S])*P_{loss} = 0.824794$
- \end{center}
- Lo pseudocodice è il seguente\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Python, caption=size based algorithm, label={dispatch2}]
- if(event is an arrival){
- if (totalJobsInCloudlet >= numberOfServers ||
- (jobClass == 2 && operations > 1.0) ||
- (jobClass == 1 && operations > 1.0)){
- Cloud.processArrival(e);
- }else{
- Cloudlet.processArrival(e);
- }
- }
- \end{lstlisting}
- \end{minipage}
- \subsubsection{Algoritmo alternativo 2: first class on Cloudlet}
- Il terzo algoritmo che l'utente può scegliere, chiamato \textbf{first class on Cloudlet algorithm} si basa su un'idea molto semplice: i job di classe 1 godono di un tasso di servizio più elevato, quindi verranno serviti in meno tempo rispetto agli altri.
- Lo pseudocodice è il seguente\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=first class on Cloudlet algorithm, label={dispatch3}]
- if(event is an arrival){
- if(totalJobsInCloudlet >= numberOfServers || jobClass == 2){
- Cloud.processArrival(e);
- }else{
- Cloudlet.processArrival(e);
- }
- }
- \end{lstlisting}
- \end{minipage}
- Adottando questo algoritmo, cambia il modello analitico rispetto all'algoritmo standard. Infatti, poiché il Cloudlet accetta solo task di classe 1 la catena di Markov risulta mono-dimensionale, come visibile in figura:
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{MM33.png}
- \caption{Modello della rete}
- \label{key}
- \end{figure}
- \end{center}
- Pertanto, i nuovi risultati analitici sono:
- \begin{center}
- $P_{loss} = p_{class\_1}*p_3 + p_{class\_2} = 0.8985142 $\\~\\
- $\lambda_{clet} = \lambda_1*(1-p_3) = 1,242932 $ tasks/s\\~\\
- $\lambda_{cloud} = \lambda_2 + (\lambda_1 - \lambda_{clet}) = 11,007067 $ tasks/s\\~\\
- $ E[T_{clet}] = E[T_{1\_clet}] = 1/\mu_{1clet}= 2,222222$ s\\~\\
- $E[T_{1\_cloud}] = \frac{1}{\mu_{1\_cloud}} = 4,00000$ s \\~\\
- $E[T_{2\_cloud}] = \frac{1}{\mu_{2\_cloud}} = 4.54545$ s\\~\\
- $p_1 = $
- $E[T_{cloud}]= \frac{\lambda_1 - \lambda_{clet}}{\lambda_{tot}} * E[T_{1\_cloud}] + \frac{\lambda_2}{\lambda_{tot}} * E[T_{2\_cloud}] = 4,309355$ s\\~\\
- $E[N_{clet}] = E[N_{1_clet}] = \lambda_{clet}*E[T_{clet}] = 2.762071 $ tasks \\~\\
- $E[N_{1\_cloud}] = (\lambda_1 - \lambda_{clet})*E[T_{1\_cloud}] = 19.028272 $ tasks \\~\\
- $E[N_{2\_cloud}] = \lambda_2*E[T_{2\_cloud}] = 28.40906 $ tasks \\~\\
- $E[N_{cloud}] = \lambda_{cloud}*E[T_{cloud}] = 47.433400 $ tasks \\~\\
- \end{center}
- Bisogna quindi notare come la probabilità di perdita sia pari alla probabilità che un job di qualsiasi classe non venga servito dal cloudlet. A seguito della risoluzione della catena di Markov, si trova che la probabilità di essere nello stato 3 (stato di saturazione del Cloudlet) è pari a 0.7928. A questo però bisogna aggiungere che tutti i job di classe 2 sono scartati a priori dal Controller, da qui la formula della $P_{loss}$ mostrata poco fa.
- \subsubsection{Algoritmo alternativo 3: threshold-based algorithm}
- L'ultimo algoritmo nasce da un problema osservato nel comportamento dell'algoritmo \textit{first class on cloudlet}: la scarsa utilizzazione del Cloudlet stesso. Per sfruttare al meglio quest'ultimo si è deciso quindi sia di non inviare più solo job di class 1 (con cui si era già notato un miglioramento nei tempi di risposta) sia di evitare di sovraccaricare il Cloudlet oltre una certa soglia (da qui il nome dell'algoritmo). In particolare, in caso di superamento della stessa, i task di classe 2 vengono inviati al Cloud, mentre i task di classe 1 possono comunque prendere servizio presso il Cloudlet. La motivazione alla base di questa scelta risiede nel fatto che i job di classe 1 godono di un tasso di servizio maggiore e pertanto possono essere completati in minor tempo, portando un vantaggio qualora il Cloudlet sia quasi saturo, incrementandone comunque l'utilizzazione inviando anche task di class 2.\\
- Lo pseudocodice è il seguente\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Python, caption=first class on Cloudlet algorithm, label={dispatch3}]
- if(event is an arrival){
- if((totalJobsInCloudlet >= numberOfServers) ||
- (totalJobsInCloudlet > soglia && jobClass == 2)){
- Cloud.getInstance().processArrival(e);
- }else{
- Cloudlet.getInstance().processArrival(e);
- }
- }
- \end{lstlisting}
- \end{minipage}
- Sono stati testati diversi valori di threshold per poter trovare quello che fornisse il minor tempo di risposta globale possibile, pur non avendo introdotto prelazione. Lo svantaggio di questo algoritmo è un peggioramento del tempo di risposta del Cloud, che viene sottoposto ad un carico maggiore rispetto all'algoritmo di default.
- Si noti che impostando il valore soglia a 0 si torna al caso dell'algoritmo \textit{first class in Cloudlet}. Infatti non appena il Cloudlet non è vuoto tutti i task di classe 2 verranno inviati sul Cloud.
- Si ricorda che per poter eseguire questo algoritmo è necessario impostare il parametro \texttt{THRESHOLD} alla soglia desiderata.
- In conclusione, empiricamente è stato osservato che $14$ è il valore per cui si ottengono i risultati migliori. Non sono stati riportati i risultati analitici vista la complessità della Catena di Markov risultante: bidimensionale fintanto che la popolazione totale nel sistema è pari a THRESHOLD, monodimensionale (processo di nascita-morte) di soli task di classe 1 successivamente.
- \subsubsection{Batch}
- La tecnica dei Batch Means consente di eliminare il problema del bias iniziale nel calcolo dell'intervallo di stima. Per implementarla è stato seguito l'algoritmo del libro \textit{Discrete-Event Simulation:
- a first course} di L. Leemis e S. Park. L'algoritmo prevede di dividere la sequenza di dati in input $x_1,x_2,.....x_n$ in \textit{k} batch di dimensione \textit{b} e di calcolare per ognuno di essi la media relativa alla statistica di interesse:
- \begin{center}
- $x_1,....x_b,x_{b+1},...,x_{2b},........,x_{n-b},...x_n$\\~\\
- $\bar{x_j} = \frac{1}{b}\sum_{k=1}^b x_{j-1}_{b+i}$\\~\\
- \end{center}
- Poi si calcola la media $\bar{x}$ e la deviazione standard s delle medie dei batch $\bar{x_1},\bar{x_2},...,\bar{x_k}$. Scelto poi un livello di confidenza $1-\alpha$, si calcola il valore critico
- $t^* = idfStudent(k-1,1-\frac{\alpha}{2})$ e si calcolano gli estremi dell'intervallo di confidenza:
- \begin{center}
- $\bar{x}\pm \frac{t^*s}{\sqrt{k-1}} $\\~\\
- \end{center}
- Va notato che la scelta della coppia (b,k) non influisce sul punto di stima ma solo sull'ampiezza dell'intervallo di confidenza.\\
- Perchè questa tecnica elimina il problema del bias iniziale? Perchè le statistiche di ogni batch vengono inizializzate allo stato del sistema nel momento in cui le stime dei batch vengono azzerate. \\
- Poiché il sistema in considerazione contiene un infinite server si può ritenere che il sistema raggiunga la stazionarietà, per questo motivo sono state realizzate statistiche \textit{infinite-horizon} applicando il metodo dei Batch Means. Si esegue quindi una long run e si partizionano i dati in input in batch di dimensione prefissata. La coppia di parametri (b,k) è stata scelta in modo tale che k = 64, così che la metodologia sia ancora più valida vista la notevole dimensione b dei singoli batch\footnote{Si ricorda che il parametro k è configurabile nel file \textit{config.properties} settando la variabile NUM\_BATCH}.
- \subsubsection{Abilitare le operazioni}\label{operation_enabled}
- Per quanto detto fino a questo punto il Job viene considerato come un oggetto avente come attributi la classe di appartenenza, il tempo di arrivo ed il tempo di completamento. Ogni volta che questo viene preso in carico da uno qualsiasi dei sottosistemi verrà generato un tempo di servizio che dipende unicamente dal tasso di servizio del sottosistema scelto. Questo è corretto ai fini della simulazione ma è sicuramente un comportamento distante da quello reale. In tal caso la size del Job sarebbe decisa solo nel momento del processamento e non sarebbe una proprietà del job stesso come invece dovrebbe essere. Abilitare le operazioni permette di dare alla simulazione un comportamento più simile al caso reale.
- Una volta attivato questo flag, ad ogni Job generato viene associato un valore relativo al numero di operazioni richieste. Il tempo impiegato dal sistema per processare tutte le operazioni diventa quindi il nuovo tempo di servizio.
- In questo modo il sistema ha un comportamento più realistico: ogni server ha un proprio rate di operazioni/secondo che rimane costante nel tempo e ciò che varia è la grandezza del job di volta in volta da servire.
- \\
- Abilitare le operazioni è ovviamente un approccio che porta a risultati corretti, gli stessi ottenibili con metodi standard. \`E interessante mostrare come questo sia vero andando ad esaminare l'implementazione dell'estrazione di un numero con distribuzione esponenziale.
- Viene qui descritto il processo di generazione di un evento di tipo arrivo\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=generazione di un evento di tipo arrivo, label={arrival}]
- public Event generateArrival(){
- double arrival = getArrival();
- int jobClass = determineJobClass();
- Job job;
- if(OPERATIONS_ENABLED)
- job = new Job(jobClass, arrival, getJobOperations());
- else
- job = new Job(jobClass, arrival, 0);
- return new Event(0, job);
- } \end{lstlisting}
- \end{minipage}
- la funzione \texttt{getJobOperations()} ritorna un valore da una distribuzione esponenziale con parametro 1.
- Quando uno dei sistemi deve stabilire il tempo di servizio associato al job preso in esame, vengono richiamate le seguenti funzioni\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=generazione di un evento di tipo arrivo, label={arrival}]
- public double getServiceTime(int jobclass, double numberOfOperations){
- if(OPERATIONS_ENABLED)
- return getExpServiceTimePerOperation(jobclass, numberOfOperations);
- else
- return getServiceTimeWithoutOperations(jobclass);
- }
- private double getExpServiceTimePerOperation(int jobClass, double numberOfOperations){
- if(jobClass == 1)
- return (1/SYSTEM_RATE_1) * numberOfOperations;
- else
- return (1/SYSTEM_RATE_2) * numberOfOperations;
- }
- private double getServiceTimeWithoutOperations(int job_class){
- double service_rate;
- int stream;
- if(job_class == 1) {
- service_rate = SYSTEM_RATE_1;
- stream = 2;
- }
- else {
- service_rate = SYSTEM_RATE_2;
- stream = 3;
- }
- return exponential(service_rate, stream);
- }
- \end{lstlisting}
- \end{minipage}
- A livello di codice, andando a guardare le librerie \texttt{RVGS} e \texttt{RNGS}, si ha che per generare un tempo di servizio con distribuzione esponenziale si deve chiamare\\
- \begin{minipage}{\linewidth}
- \begin{lstlisting}[language=Java, caption=exponential function, label={dispatch3}]
- //funzione che richiede il valore
- public double exponential(double rate){
- return exponential(1/rate);
- }
- //funzione exponential in rvgs
- public double exponential(double m)
- /* =========================================================
- * Returns an exponentially distributed positive real number.
- * NOTE: use m > 0.0
- * =========================================================
- */
- {
- return (-m * Math.log(1.0 - rngs.random()));
- }\end{lstlisting}
- \end{minipage}
- quindi, facendo particolare attenzione a quel fattore \texttt{-m} utilizzato dalla funzione \texttt{exponential} e ricordando come è stato generato il valore relativo al numero di operazioni, si capisce facilmente che
- \begin{center}
- \texttt{return exponential(1/SERVICE\_RATE)}\\
- =\\
- \texttt{return (1/SYSTEM\_RATE)*exponential(1)}\\
- =\\
- \texttt{return (1/SYSTEM\_RATE)*numberOfOperations}
- \end{center}
- Il risultato ottenuto è quindi lo stesso. Tuttavia i benefici sulla comprensione del codice sono molteplici.
- Per prima cosa è certamente più naturale pensare che un job abbia un numero fisso di operazioni e che il tempo di servizio dipenda dalla velocità con cui il server riesce a processarle.
- In più ci sono modifiche sostanziali per l'uso degli stream. Con l'approccio di default senza operazioni il RNG adotta uno stream diverso per ciascuna combinazione di classe del job e sistema da cui viene servito. Nel nostro caso la simulazione di base prevede 5 differenti stream. Abilitando le operazioni invece sarebbero necessari solo due stream, uno per gli arrivi e uno per l'estrazione del numero di operazioni richieste. \\
- Dalla teoria si ha che\footnote{Per una semplice dimostrazione leggere pagina 2 delle note di Renato Feres, professore della Washington University in St. Louis, disponibili al seguente link \textit{https://www.math.wustl.edu/~feres/Math450Lect03.pdf}}
- \begin{center}
- Sia X una R.V. continua con PDF $f_X(x)$ e CDF $F_X(x)$ e sia $Y = aX + b$. Allora la PDF di Y è data da\\~\\
- $f_Y(y) = |\frac{1}{a}|f_X(\frac{(y-b)}{a})$
- \end{center}
- Questo vuol dire che se $X$ è distribuita esponenzialmente con parametro 1 allora $Y = \frac{X}{\mu}$ è esponenzialmente distribuita con parametro $\frac{1}{\mu}$.
- \subsection{Risultati generati}
- \subsubsection{Popolazione media}
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Errore \\ [0.5ex]
- \hline\hline
- $E[N]_{global}$ & 51.136112 j & 51.634704 j & 0.9750\% \\
- \hline
- $E[N]_{Clet}$ & 2.915702 j & 2.917707 j & 0.0687\% \\
- \hline
- $E[N]_{Cloud}$ & 48.220410 j & 48.716997 j & 1.0298\% \\
- \hline
- $E[N]_{1}$ & 23.147490 j & 23.390956 j & 1.0518\% \\
- \hline
- $E[N]_{2}$ & 27.988622 j & 28.243748 j & 0.9115\% \\
- \hline
- $E[N]_{Clet_1}$ & 1.065637 j & 1.068201 j & 0.2406\% \\
- \hline
- $E[N]_{Clet_2}$ & 1.850065 j & 1.849505 j & 0.0302\% \\
- \hline
- $E[N]_{Cloud_1}$ & 22.081853 j & 22.322755 j & 1.0906\% \\
- \hline
- $E[N]_{Cloud_2}$ & 26.138557 j & 26.394242 j & 0.9782\% \\
- \hline
- \end{tabular}
- \end{center}\\
- grafici sottostanti ottenuti dalla simulazione presentata nella tabella \ref{table:standard3}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/globalPopPerTime.png}
- \caption{Arrivare alla stazionarietà - popolazione globale}
- \label{fig:globalPopPertime}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/cloudPopPerTime.png}
- \caption{Arrivare alla stazionarietà - popolazione Cloud}
- \label{fig:cloudPopPertime}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/cloudletPopPerTime.png}
- \caption{Arrivare alla stazionarietà - popolazione Cloudlet}
- \label{fig:cletPopPertime}
- \end{figure}
- \end{center}
- Invece per quanto riguarda la popolazione media in differenti run si ha che, utilizzando la run presente alla tabella \ref{table:fastMR}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/globalPopMultirun.png}
- \caption{Arrivare alla stazionarietà - popolazione Cloudlet}
- \label{fig:cletPopmr}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/cloudletpopMultirun.png}
- \caption{Arrivare alla stazionarietà - popolazione Cloudlet}
- \label{fig:cletPopmr}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/cloudPopMultirun.png}
- \caption{Arrivare alla stazionarietà - popolazione Cloudlet}
- \label{fig:cletPopmr}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{tabular}{||c c||}
- \hline
- Misura & Sperimentale\\ [0.5ex]
- \hline\hline
- $E[N]_{global}$ & 44.108593 j\\
- \hline
- $E[N]_{Clet}$ & 19.007473 j\\
- \hline
- $E[N]_{Cloud}$ & 25.101120 j\\
- \hline
- $E[N]_{1}$ & 18.436802 j\\
- \hline
- $E[N]_{2}$ & 25.671791 j\\
- \hline
- $E[N]_{Clet_1}$ & 6.944089 j\\
- \hline
- $E[N]_{Clet_2}$ & 12.063384 j\\
- \hline
- $E[N]_{Cloud_1}$ & 11.492713 j\\
- \hline
- $E[N]_{Cloud_2}$ & 13.608408 j\\
- \hline
- \end{tabular}
- \end{center}\\
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/finite_horizon_pop.png}
- \caption{Finite Horizon Response Time}
- \label{fig:fhpop}
- \end{figure}
- \end{center}
- \subsubsection{Throughput}
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Errore \\ [0.5ex]
- \hline\hline
- $X_{global}$ & 12,25 & 12.250871 & 0.0071\% \\
- \hline
- $X_{Clet}$ & 0,97906 & 0.97769 & 0.1399\% \\
- \hline
- $X_{Cloud}$ & 11,27094 & 11.27317 & 0,0197\% \\
- \hline
- $X_{1\_global}$ & 6,00005 & 5.99864 & 0,0023\% \\
- \hline
- $X_{2\_global}$ & 6,24995 & 6.25222 & 0.0363\% \\
- \hline
- $X_{Clet_1}$ & 0,47954 & 0.47808 & 0.0030\% \\
- \hline
- $X_{Clet_2}$ & 0,49952 & 0.49960 & 0.0160\% \\
- \hline
- $X_{Cloud_1}$ & 5,5205 & 5.52055 & 0,0096\% \\
- \hline
- $X_{Cloud_2}$ & 5,75043 & 5.75262 & 0.0380\% \\
- \hline
- \end{tabular}
- \end{center}\\
- \begin{center}
- \begin{tabular}{||c c||}
- \hline
- Misura & Sperimentale\\ [0.5ex]
- \hline\hline
- $X_{global}$ & 12.250878 \\
- \hline
- $X_{Clet}$ & 6.383127 \\
- \hline
- $X_{Cloud}$ & 5.867751 \\
- \hline
- $X_{1\_global}$ & 5.998646 \\
- \hline
- $X_{2\_global}$ & 6.252232 \\
- \hline
- $X_{Clet_1}$ & 3.125872 \\
- \hline
- $X_{Clet_2}$ & 3.257255 \\
- \hline
- $X_{Cloud_1}$ & 2.872775 \\
- \hline
- $X_{Cloud_2}$ & 2.994977 \\
- \hline
- \end{tabular}
- \end{center}\\
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/finite_horizon_th.png}
- \caption{Finite Horizon Throughput}
- \label{fig:fhrt}
- \end{figure}
- \end{center}
- \newpage
- \section{Test}
- \textcolor{red}{INTRODUZIONE}
- \subsection{Ambiente di Test}
- In questa sezione non solo vengono mostrati gli strumenti a livello hardware e software con cui è stata implementata la simulazione, ma anche i risultati ottenuti a livello di performance. In fase di sviluppo è stata prestata molta cura nei riguardi dell'ottimizzazione generale della simulazione, perlopiù in termini di utilizzazione della RAM e tempo reale speso per ottenere risultati in output.\\
- Per prima cosa viene mostrata una breve descrizione delle macchine e dei software utilizzati, successivamente sono riportate le performance ottenute.
- Il codice della simulazione è stato realizzato in Java, utilizzando come IDE di sviluppo \textbf{Jetbrain Intellij} nelle seguenti versioni
- \begin{itemize}
- \item Intellij Ultimate Edition 2018.3.5
- \item Intellij Ultimate Edition 2019.1.3
- \item Intellij Community Edition 2019.1.3
- \end{itemize}
- Le uniche librerie esterne aggiuntive sono \textt{RNGS}, \textt{RVGS} e \textt{RVMS}.
- Per lo sviluppo di grafici è stato utilizzato \textbf{Matlab R2019A}. L'utilizzo di una versione uguale o successiva a questa è necessaria per il run del livescript Matlab, per via della funzione \texttt{readmatrix} introdotta proprio con la release R2019A.
- Per tutto ciò che riguarda la reportistica è stato usato il linguaggio Latex, sfruttando le funzionalità di \textbf{Overleaf} per la condivisione, scrittura simultanea ed esportazione. \\
- Nella seguente tabella vengono mostrati i terminali su cui è stata sviluppata e testata la simulazione.
- \begin{center}
- \begin{tabular}{||c c c c c||}
- \hline
- Fisso/Portatile & Modello & CPU & RAM & OS \\ [0.5ex]
- \hline\hline
- P & HP Spectre & i7 7500U & 8 & W10 \\
- \hline
- P & Acer Aspire V & i7 4500U & 12 & W10 \\
- \hline
- P & Macbook Pro & i7 9th gen. & 16 & macOS Mojave \\
- \hline
- F & Assemblato & i5 7600K & 8 & W10 \\
- \hline
- \end{tabular}
- \end{center}\\
- \subsubsection{Performance della simulazione}
- Una buona simulazione dovrebbe poter girare per un tempo indefinito su qualsiasi terminale. Per questo motivo è stata posta particolare attenzione al consumo in termini di RAM utilizzata.
- Al fine di ottenere questa informazione, viene misurato il valore della RAM utilizzata prima dell'esecuzione e poco prima della terminazione della simulazione. Viene quindi mostrata all'utente la differenza di questi due valori.
- In Figura \ref{fig:ramsim} viene mostrata l'utilizzazione della RAM al crescere del tempo di simulazione. I valori ottenuti riguardano il terminale Acer Aspire V ma gli altri terminali ottengono i medesimi risultati.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{immagini/grafici/ram_sim_time.png}
- \caption{Utilizzazione della RAM al variare del tempo di simulazione}
- \label{fig:ramsim}
- \end{figure}
- \end{center}
- Dal grafico si può vedere come il consumo di RAM sia indipendente dal tempo di simulazione e nel 70\% dei casi sia inferiore a 44MB. Lo stesso comportamento si ritrova relazionando questo valore al tempo reale della simulazione, figura \ref{fig:ramreal}. Questo risultato è stato ottenuto ponendo particolare attenzione nel non salvare in memoria liste dalla crescita non controllata.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{immagini/grafici/ram_real_time.png}
- \caption{RAM utilizzata al variare del tempo reale}
- \label{fig:ramreal}
- \end{figure}
- \end{center}
- \subsubsection{Tempo di Simulazione vs Real-Time}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{immagini/grafici/sim_time_real_time.png}
- \caption{rapporto tra tempo di simulazione e tempo reale}
- \label{fig:realsim}
- \end{figure}
- \end{center}
- Per ripetere le simulazioni che hanno permesso di ottenere i grafici \ref{fig:ramsim}, \ref{fig:ramreal} e \ref{fig:realsim} vedere la tabella \ref{table:ramsim} presente nella appendice \ref{replicare_test}.
- \subsection{Tecniche Utilizzate}
- Brevemente si illustrano gli strumenti utilizzati per poter determinare i seguenti indici prestazionali:
- \begin{itemize}
- \item Tempo medio di risposta: tempo medio che intercorre tra l'ingresso e l'uscita dal sistema di un task
- \item Throughput: numero medio di task completati nell'unità di tempo
- \item Popolazione media: numero medio di richieste in servizio
- \end{itemize}
- Queste metriche sono stati calcolate sia globalmente (a livello di sistema) che per sottosistema, sia per classe.
- \subsubsection{Welford's One-Pass Algorithm}
- Per il calcolo delle medie è stato utilizzato l'algoritmo \textit{one-pass} di Welford, che presenta il vantaggio di impiegare un tempo \textit{O(n)} e di non richiedere una conoscenza preliminare sulla dimensione del campione \textit{n}. Si riporta in seguito l'algoritmo utilizzato:
- \begin{center}
- $\bar{x}_i = \bar{x}_{i-1} + \frac{1}{i} (x_i - \bar{x}_{i-1}) $ \\~\\
- $v_i = v_{i-1} + \frac{i-1}{i} (x_i - \bar{x}_{i-1})^2 $
- \end{center}
- Dove $\bar{x}_i$ e $\frac{v_i}{i}$ sono rispettivamente la media e la varianza di \textit{i} campioni.
- Dunque tramite tale algoritmo è stato possibile aggiornare in modo incrementale gli indici prestazionali.
- \subsubsection{Batch Means e intervallo di confidenza}
- La presenza di un Infinite-Server (il Cloud) fa presumere che il sistema sia stazionario, perciò si è scelto di realizzare statistiche di tipo Infinite-Horizon, note anche come steady-state statistics. \\
- Statistiche di questo tipo sono prodotte simulando il funzionamento del sistema per un tempo effettivamente infinito ed hanno la peculiarit° di non essere influenzate dalle condizioni iniziali, poiché - essendo il tempo pressocché infinito - il sistema “perde memoria” dello stato iniziale. Viene quindi trascurato il bias iniziale.
- Per generare le statistiche steady-state è stata utilizzata la tecnica dei Batch-Means. Questa consente di eliminare il problema del bias iniziale nel calcolo dell'intervallo di stima. Per implementarla è stato seguito l'algoritmo del libro \textit{Discrete-Event Simulation:
- a first course} di L. Leemis e S. Park. L'algoritmo prevede di dividere la sequenza di dati in input $x_1,x_2,.....x_n$ in \textit{k} batch di dimensione \textit{b} e di calcolare per ognuno di essi la media relativa alla statistica di interesse:
- \begin{center}
- $x_1,....x_b,x_{b+1},...,x_{2b},........,x_{n-b},...x_n$\\~\\
- $\bar{x_j} = \frac{1}{b}\sum_{k=1}^b x_{j-1}_{b+i}$\\~\\
- \end{center}
- Poi si calcola la media $\bar{x}$ e la deviazione standard s delle medie dei batch $\bar{x_1},\bar{x_2},...,\bar{x_k}$. Scelto poi un livello di confidenza $1-\alpha$, si calcola il valore critico
- $t^* = idfStudent(k-1,1-\frac{\alpha}{2})$ e si calcolano gli estremi dell'intervallo di confidenza:
- \begin{center}
- $\bar{x}\pm \frac{t^*s}{\sqrt{k-1}} $\\~\\
- \end{center}
- Va notato che la scelta della coppia (b,k) non influisce sul punto di stima ma solo sull'ampiezza dell'intervallo di confidenza.\\
- Perchè questa tecnica elimina il problema del bias iniziale? Perchè le statistiche di ogni batch vengono inizializzate allo stato del sistema nel momento in cui le stime dei batch vengono azzerate. \\
- \'E stata quindi eseguita una long run e sono stati partizionati i dati in input in batch di dimensione prefissata. La coppia di parametri (b,k) è stata scelta in modo tale che k = 64, così che la metodologia sia ancora più valida vista la notevole dimensione b dei singoli batch\footnote{Si ricorda che il parametro k è configurabile nel file \textit{config.properties} settando la variabile NUM\_BATCH}.
- \subsection{Risultati della simulazione}
- In questa sezione vengono illustrati (riportando i relativi grafici) ed analizzati i risultati ottenuti dal simulatore, confrontandoli quando necessario con i risultati analitici ottenuti nel paragrafo Modello analitico e risultati.
- Al fine di rendere più piacevole la lettura, i parametri con cui è stata generata ciascuna run, e quindi a ciascun risultato, sono illustrati nell'appendice \ref{replicare_test}.
- Nel confronto tra i valori sperimentali (ottenuti senza l'utilizzo dei batch con una simulazione molto lunga) e quelli analitici, viene inoltre riportato l'errore percentuale, calcolato come
- \begin{center}
- $Errore_{perc} = \frac{|experimental\_value - accepted\_value|}{accepted\_value}$ x 100\%
- \end{center}
- Successivamente vengono presentati i valori ottenuti utilizzando i Batch, ponendo enfasi sugli intervalli di confidenza.
- \subsubsection{Probabilità di perdita}
- Sono qui mostrati i risultati relativi alla probabilità di perdita del Cloudlet, da cui è poi facilmente calcolabile il flusso effettivamente entrante nel Cloudlet.
- Settando i parametri dell'esperimento come riportato nella tabella \ref{table:standard3_OP} dell'appendice \ref{replicare_test}, si ricavano i seguenti risultati:
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Errore \\ [0.5ex]
- \hline\hline
- $P_{Clet}$ & 0.079923 & 0.079981 & 0.0757\% \\
- \hline
- $P_{Cloud}$ & 0.920077 & 0.920019 & 0.0063\% \\
- \hline
- $\lambda_{Clet}$ & 0.979057 tasks/s & 0.979767 tasks/s & 0.7257\% \\
- \hline
- $\lambda_{Cloud}$ & 11.270946 tasks/s & 11.270223 tasks/s & 0.0063\% \\
- \hline
- \end{tabular}
- \end{center}
- Come si vede dalla tabella, l'errore della simulazione in caso di long-run (dalla durata real-time inferiore a 12 secondi) è sempre inferiore all'1\%. Questa lievissima discrepanza può essere dovuta alle approssimazioni poco precise effettuate da Java.
- In aggiunta, si riportano i dati ottenuti nel caso in cui il Cloudlet sia configurato con N=20 serventi:\\
- \begin{center}
- \begin{tabular}{||c c||}
- \label{}
- \hline
- Misura & Sperimentale\\ [0.5ex]
- \hline\hline
- $P_{Clet}$ & 0.521278\\
- \hline
- $P_{Cloud}$ & 0.478723 \\
- \hline
- $\lambda_{Clet}$ & 6.385649 tasks/s \\
- \hline
- $\lambda_{Cloud}$ & 5.864350 tasks/s \\
- \hline
- \end{tabular}
- \end{center}\\
- Dai valori della tabella soprastante, si può apprezzare la diminuzione della probabilità di perdita visto il numero maggiore di serventi a disposizione del Cloudlet per poter processare i task in servizio.\\
- \'E inoltre interessante notare come la probabilità che un Task sia assegnato al Cloud nel caso $N=20$ risenta dell'algoritmo di dispatching utilizzato, come possibile vedere nella Tabella Cambiando solamente le configurazioni relative a questo aspetto si ottengono i risultati della seguente tabella. Questo tipo di confronto risulterà di fondamentale importanza anche nei successivi sotto-paragrafi.
- \begin{center}
- \begin{tabular}{||c c||}
- \hline
- Algoritmo & Probabilità di entrare nel Cloud\\ [0.5ex]
- \hline\hline
- Standard & 0.478722\\
- \hline
- Size Based & 0.368462\\
- \hline
- First-class & 0.520981 \\
- \hline
- Treshold & 0.438809 \\
- \hline
- \end{tabular}
- \end{center}
- \subsubsection{Tempo di risposta}
- Vengono qui illustrati i valori sperimentali riguardanti il tempo di risposta per classe e globale, sia per il sistema nella sua interezza sia per Cloudlet e Cloud.
- Per dimostrare la bontà della simulazione, si riportano i risultati ottenuti tramite una long-run con la configurazione di default della simulazione, riportata nella tabella \ref{table:standard3}.
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Errore \\ [0.5ex]
- \hline\hline
- $E[S]_{global}$ & 4.174377 s & 4.174335 s & 0.0010\% \\
- \hline
- $E[S]_{Clet}$ & 2.978080 s & 2.982218 s & 0.1389\% \\
- \hline
- $E[S]_{Cloud}$ & 4.278293 s & 4.277724 s & 0.0133\% \\
- \hline
- $E[S]_{1}$ & 3.857915 s & 3.858477 s & 0.0145\% \\
- \hline
- $E[S]_{2}$ & 4.478180 s & 4.477383 s & 0.0178\% \\
- \hline
- $E[S]_{Clet_1}$ & 2.222222 s & 2.226104 s & 0.1744\% \\
- \hline
- $E[S]_{Clet_2}$ & 3.703704 s & 3.705765 s & 0.0556\% \\
- \hline
- $E[S]_{Cloud_1}$ & 4.000000 s & 3.999842 s & 0.0040\% \\
- \hline
- $E[S]_{Cloud_2}$ & 4.545455 s & 4.544396 s & 0.0233\% \\
- \hline
- \end{tabular}
- \end{center}
- In seguito sono stati eseguiti i test anche per il Cloudlet con N = 20 serventi (ottenuti eseguendo la simulazione con la configurazione riportata nella tabella \ref{table:standard20}), come mostrati qui di seguito:
- \begin{center}
- \begin{tabular}{||c c||}
- \hline
- Misura & Sperimentale \\ [0.5ex]
- \hline\hline
- $E[S]_{global}$ & 3.600439 s\\
- \hline
- $E[S]_{Clet}$ & 2.977774 s\\
- \hline
- $E[S]_{Cloud}$ & 4.277793 s\\
- \hline
- $E[S]_{1}$ & 3.073385 s\\
- \hline
- $E[S]_{2}$ & 4.106117 s\\
- \hline
- $E[S]_{Clet_1}$ & 2.221204 s\\
- \hline
- $E[S]_{Clet_2}$ & 3.703826 s\\
- \hline
- $E[S]_{Cloud_1}$ & 4.000643 s\\
- \hline
- $E[S]_{Cloud_2}$ & 4.543635 s\\
- \hline
- \end{tabular}
- \end{center}\\
- Come si può vedere dai valori, sono rimasti invariati i tempi di risposta del Cloudlet e del Cloud, mentre è diminuito il tempo di risposta globale. Questo è dovuto al fatto che il Cloudlet, in questa configurazione, possiede più serventi e inoltre gode (per costruzione) di un tasso di servizio maggiore per i Task sia di classe 1 sia di classe 2.
- \'E inoltre interessante confrontare la distribuzione esponenziale con quella iper-esponenziale del Cloudlet, inizialmente indicata dalla traccia e poi sostituita con una distribuzione esponenziale per poter effettuare più semplicemente l'analisi ed il testing del sistema. Come si può notare dalla figura \ref{fig:cletPopmr} le due distribuzioni presentano un andamento molto simile, di media uguale. Questo è concorde con il risultato atteso, dal momento in cui le due distribuzioni devono presentare lo stesso valore medio.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/expo-hyperexpo.png}
- \caption{Exponential vs Hyper-exponential}
- \label{fig:cletPopmr}
- \end{figure}
- \end{center}
- A livello di sistema, si è poi voluto controllare l'effettivo raggiungimento di una condizione stazionaria del sistema, studiandone il comportamento transitorio. A tal fine, è stato preso spunto dall'esempio 8.4.1 presente nel Capitolo 8 del libro \textit{Discrete-evetn simulation: a first course}. Sono quindi state eseguite 20 repliche indipendenti con SEED iniziale \texttt{12345} e sono stati poi incrementati di volta in volta i task da processare, in particolare il numero di task eseguiti sono: 50, 100, 150, 200, 250, 300, 350, 400, 600, 1000, 1500, 2000, 3000, 5000. Come si vede in Figura \ref{fig:fhrt}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/finite_horizon_rt.png}
- \caption{Finite Horizon Response Time}
- \label{fig:fhrt}
- \end{figure}
- \end{center}
- Come si può vedere dai grafici viene raggiunta la stazionarietà intorno ai 2000 tasks processati.\\
- Avendo dimostrato la stazionarietà del sistema, si è poi proceduto ad effettuare le statistiche \textit{steady state} tramite il metodo dei Batch Means. In seguito si riportano i valori delle medie campionarie relative ai tempi di risposta ed i corrispettivi intervalli di confidenza:
- \textcolor{red}{Un errore così lieve potrebbe essere dovuto alla scelta di un SEED particolarmente fortunato. Al fine di dimostrare come la generazione di numeri casuali non influenzi la correttezza del modello si riportano grafici in figure \ref{fig:rtCloudlet},\ref{fig:rtcloud} e \ref{fig:rtg}, che illustrano l'andamento dei tempi di risposta al variare del SEED iniziale. Per riprodurre l'esperimento è sufficiente seguire la configurazione presente nella tabella \ref{table:multi_run}. I risultati sono i seguenti}:
- \begin{labeling}{Media sperimentale globale:----}
- \item[Media analitica globale: ] 4.174377 j/s
- \item[Media sperimentale globale: ] 4.173972 j/s
- \item[Media analitica Cloudlet: ] 2.978080 j/s
- \item[Media sperimentale Cloudlet: ] 2.978088 j/s
- \item[Media analitica Cloud: ] 4.278293 j/s
- \item[Media sperimentale Cloud: ] 4.277855 j/s
- \end{labeling}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/global_response_staandard.png}
- \caption{Response Time generale}
- \label{fig:rtg}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/cloudlet_response_staandard.png}
- \caption{Response Time Cloudlet}
- \label{fig:rtCloudlet}
- \end{figure}
- \end{center}
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/cloud_response_staandard.png}
- \caption{Response Time Cloud}
- \label{fig:rtcloud}
- \end{figure}
- \end{center}
- La simulazione risulta quindi estremamente robusta al variare del SEED iniziale scelto.\\
- In merito agli algoritmi di dispatching, risulta di particolare importanza il confronto tra i diversi tempi di risposta. In figura \ref{table:comparisonDispatch} viene mostrata l'effettiva diminuzione del tempo di risposta globale applicando l'algoritmo \textit{First class in Cloudlet} e adottando un algoritmo con soglia rispetto all'algoritmo di default.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.8\textwidth]{immagini/grafici/comparison.png}
- \caption{Confronto del tempo di risposta globale tra i differenti algoritmi di dispatching}
- \label{fig:rtg}
- \end{figure}
- \end{center}
- Si riportano quindi le medie dei tempi di risposta per i singoli algoritmi, ottenuta con la configurazione presentata nella tabella \ref{table:comparisonDispatch}:
- \begin{center}
- \begin{labeling}{First-Class----}
- \item[Standard: ] 3.600516 j/s
- \item[First-Class: ] 3.426126 j/s
- \item[Treshold: ] 3.373777 j/s
- \end{labeling}
- \end{center}
- \subsubsection{Popolazione media}
- %
- %
- \subsubsection{Throughput}
- \subsubsection{Gli algoritmi a confronto}
- %transitorio per tempo di risposta globale, popolazione e throughput
- %MISSING: grafico con istogrammi
- \subsection{Intervalli di confidenza}
- \textbf{Iterations = 3000000, Algoritmo 1, Batch = true, N = 3}\\
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Intervallo di confidenza [0.5ex]
- \hline
- $E[N]_{global}$ & 51.136112 j & 51.133165 j & \pm 0.675516
- \hline
- $E[N]_{Clet}$ & 2.915702 j & 2.915805 j & \pm 0.002982
- \hline
- $E[N]_{Cloud}$ & 48.220410 j & 48.217359 j & \pm 0.674481
- \hline
- $E[N]_{1}$ & 23.147490 j & 23.135246 j & \pm 0.467684
- \hline
- $E[N]_{2}$ & 27.988622 j & 27.997919 j & \pm 0.510519
- \hline
- $E[N]_{Clet\_1}$ & 1.065637 j & 1.064221 j & \pm 0.077448
- \hline
- $E[N]_{Clet\_2}$ & 1.850065 j & 1.851584 j & \pm 0.078621
- \hline
- $E[N]_{Cloud\_1}$ & 22.081853 j & 22.071024 j & \pm 0.450362
- \hline
- $E[N]_{Cloud\_2}$ & 26.138557 j & 26.146335 j & \pm 0.479542
- \hline
- \end{tabular}
- \end{center}
- \begin{center}
- \begin{tabular}{|c c|}
- \hline
- Misura & Sperimentale
- \hline
- $X_{glob}$ & 12.266818 \pm 0.031244
- \hline
- $X_{clet}$ & 0.984746 \pm 0.0075365
- \hline
- $X_{cloud}$ & 11.282072 \pm 0.025595
- \hline
- \end{tabular}
- \end{center}
- \newline
- \textbf{Algoritmo 2, Iterations = 3000000, Operations_enabled = true, N = 3}
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Intervallo di confidenza [0.5ex]
- \hline\hline
- $E[N]_{global}$ & 51.136112 j & 51.028552 j & \pm 0.664834
- \hline
- $E[N]_{Clet}$ & 2.488910000 j & 2.915805 j & \pm 0.010118
- \hline
- $E[N]_{Cloud}$ & 48.220410 j & 48.539642 j & \pm 0.662515
- \hline
- $E[N]_{1}$ & 23.147490 j & 22.893755 j & \pm 0.472253
- \hline
- $E[N]_{2}$ & 27.988622 j & 28.134797 j & \pm 0.478493
- \hline
- $E[N]_{Clet_1}$ & 1.065637 j & 1.380699 j & \pm 0.026945
- \hline
- $E[N]_{Clet_2}$ & 1.850065 j & 1.108211 j & \pm 0.027674
- \hline
- $E[N]_{Cloud_1}$ & 22.081853 j & 21.513056 j & \pm 0.466632
- \hline
- $E[N]_{Cloud_2}$ & 26.138557 j & 27.026586 j & \pm 0.475047
- \hline
- \end{tabular}
- \end{center}
- \begin{center}
- \textbf{Tempi di risposta}
- \begin{tabular}{||c c c||}
- \hline
- Misura & Analitico & Sperimentale \\ [0.5ex]
- \hline\hline
- $E[S]_{global}$ & 4.174377 s & 4.165065 s\\
- \hline
- $E[S]_{Clet}$ & 2.978080 s & 0.959334 s\\
- \hline
- $E[S]_{Cloud}$ & 4.278293 s & 5.026268 s\\
- \hline
- $E[S]_{1}$ & 3.857915 s & 3.817823 s \\
- \hline
- $E[S]_{2}$ & 4.478180 s & 4.497999 s \\
- \hline
- $E[S]_{Clet_1}$ & 2.222222 s & 0.928900 s\\
- \hline
- $E[S]_{Clet_2}$ & 3.703704 s & 1.000162 s\\
- \hline
- $E[S]_{Cloud_1}$ & 4.000000 s & 4.769828s\\
- \hline
- $E[S]_{Cloud_2}$ & 4.545455 s & 5.251011 s \\
- \hline
- \end{tabular}
- \end{center}
- \begin{center}
- \begin{tabular}{|c c|}
- \hline Misura & Sperimentale \\
- \hline
- $X_{glob}$ & 12.2668099 \pm 0.031252\\
- \hline
- $X_{clet}$ & 2.596327 \pm 0.005576\\
- \hline
- $X_{cloud}$ & 9.670482 \pm 0.028742\\
- \hline
- \end{tabular}
- \end{center}
- \textbf{Algoritmo 3, N = 3000000}
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Intervallo di confidenza \\ [0.5ex]
- \hline\hline
- $E[N]_{global}$ & 51.136112 j & 50.175619 & \pm 0.662415 \\
- \hline
- $E[N]_{Clet}$ & 2.488910000 j & 2.762124 & \pm 0.0112929 \\
- \hline
- $E[N]_{Cloud}$ & 48.220410 j & 47.413495& \pm 0.658418\\
- \hline
- $E[N]_{1}$ & 23.147490 j & 21.789066 & \pm 0.470330\\
- \hline
- $E[N]_{2}$ & 27.988622 j & 28.386552 & \pm 0.480845 \\
- \hline
- $E[N]_{Clet_1}$ & 1.065637 j & 2.762124& \pm 0.011293\\
- \hline
- $E[N]_{Clet_2}$ & 1.850065 j & 0.0 & 0.0 \\
- \hline
- $E[N]_{Cloud_1}$ & 22.081853 j & 19.026942 & \pm 0.464261\\
- \hline
- $E[N]_{Cloud_2}$ & 26.138557 j & 28.386552 & \pm 0.480845\\
- \hline
- \end{tabular}
- \end{center}\\
- \textbf{Tempi di risposta}
- \begin{center}
- \begin{tabular}{||c c c||}
- \hline
- Misura & Analitico & Sperimentale \\ [0.5ex]
- \hline\hline
- $E[S]_{global}$ & 4.174377 s & 4.095425 s\\
- \hline
- $E[S]_{Clet}$ & 2.978080 s & 2.226081 s\\
- \hline
- $E[S]_{Cloud}$ & 4.278293 s & 4.306071 s\\
- \hline
- $E[S]_{1}$ & 3.857915 s & 3.633552 s \\
- \hline
- $E[S]_{2}$ & 4.478180 s & 4.538266 s \\
- \hline
- $E[S]_{Clet_1}$ & 2.222222 s & 2.226081 s\\
- \hline
- $E[S]_{Clet_2}$ & 3.703704 s & 0.0 s\\
- \hline
- $E[S]_{Cloud_1}$ & 4.000000 s & 4.000722s\\
- \hline
- $E[S]_{Cloud_2}$ & 4.545455 s & 4.538263 s \\
- \hline
- \end{tabular}
- \end{center}
- \begin{center}
- \begin{tabular}{|c c|}
- \hline Misura & Sperimentale
- \hline
- $X_{glob}$ & 12.266836 \pm 0.031247\\
- \hline
- $X_{clet}$ & 1.237997 \pm 0.016677\\
- \hline
- $X_{cloud}$ & 11.0288398 \pm 0.038428\\
- \hline
- \end{tabular}
- \end{center}
- \textbf{Algoritmo 4, Threshold = 14, N = 3000000. Server = 20}
- \begin{center}
- \begin{tabular}{||c c c c||}
- \hline
- Misura & Analitico & Sperimentale & Intervallo di confidenza \\ [0.5ex]
- \hline\hline
- $E[N]_{global}$ & 51.136112 j & 39.904198 & \pm 0.520649 \\
- \hline
- $E[N]_{Clet}$ & 2.762124 & 16.322569 & \pm 0.063066 \\
- \hline
- $E[N]_{Cloud}$ & 48.220410 j & 23.581629 & \pm 0.490581 \\
- \hline
- $E[N]_{1}$ & 23.147490 j & 12.406721 & \pm 0.215987 \\
- \hline
- $E[N]_{2}$ & 27.988622 j & 27.497477 & \pm 0.476256 \\
- \hline
- $E[N]_{Clet_1}$ & 1.065637 j & 12.406721 & \pm 0.215987 \\
- \hline
- $E[N]_{Clet_2}$ & 1.850065 j & 3.915848 & \pm 0.172357 \\
- \hline
- $E[N]_{Cloud_1}$ & 22.081853 j & 0.0 & 0.0 \\
- \hline
- $E[N]_{Cloud_2}$ & 26.138557 j & 23.581629 & \pm 0.490581\\
- \hline
- \end{tabular}
- \end{center}\\
- \textbf{Tempi di risposta}
- \begin{center}
- \begin{tabular}{||c c c||}
- \hline
- Misura & Analitico & Sperimentale \\ [0.5ex]
- \hline\hline
- $E[S]_{global}$ & 4.174377 s & 3.371953 s\\
- \hline
- $E[S]_{Clet}$ & 2.978080 s & 2.458442 s\\
- \hline
- $E[S]_{Cloud}$ & 4.278293 s & 4.539726 s\\
- \hline
- $E[S]_{1}$ & 3.857915 s & 2.223915 s \\
- \hline
- $E[S]_{2}$ & 4.478180 s & 4.395970 s \\
- \hline
- $E[S]_{Clet_1}$ & 2.222222 s & 2.223914 s\\
- \hline
- $E[S]_{Clet_2}$ & 3.703704 s & 3.692009 s\\
- \hline
- $E[S]_{Cloud_1}$ & 4.000000 s & 0.00s\\
- \hline
- $E[S]_{Cloud_2}$ & 4.545455 s & 4.539726 s \\
- \hline
- \end{tabular}
- \end{center}
- \begin{center}
- \begin{tabular}{|c c|}
- \hline Misura & Sperimentale \\
- \hline
- $X_{glob}$ & 12.266837 \pm 0.031247\\
- \hline
- $X_{clet}$ & 1.237997 \pm 0.016677\\
- \hline
- $X_{cloud}$ & 11.028840 \pm 0.038428\\
- \hline
- \end{tabular}
- \end{center}
- \begin{center}
- \begin{tabular}{|c c|}
- \hline Misura & Sperimentale \\
- \hline
- $X_{glob}$ & 11.846496 \pm 0.024971\\
- \hline
- $X_{clet}$ & 6.638604 \pm 0.013780\\
- \hline
- $X_{cloud}$ & 5.207892 \pm 0.025405\\
- \hline
- \end{tabular}
- \end{center}
- \newpage
- \subsection{Sviluppi futuri}\label{sviluppi_futuri}
- Nonostante la trattazione abbia risposto alle richieste presenti nella traccia del progetto, sono molte le aree di interesse da poter ancora approfondire. In questa sezione verranno forniti degli spunti per implementazioni future.\\
- Un aspetto interessante da approfondire è relativo allo studio dell'utilizzazione dei singoli serventi. Nella simulazione descritta finora ogni task in arrivo viene inviato al primo servente libero, dove l'ordinamento è condizionato dall'ID di quest'ultimo. La conseguenza è sì l'ottenimento di risultati corretti ma uno squilibrio nella distribuzione del carico di lavoro. Questo comportamento si può notare su soli tre server, come illustrato in figura \ref{fig:server3}.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{immagini/grafici/serverStatus3.png}
- \caption{Utilizzazione per 3 server}
- \label{fig:server3}
- \end{figure}
- \end{center}
- La non equa distribuzione del carico nei vari serventi è ancora più evidente all'aumentare del numero di server. In figura \ref{fig:server20} si può notare come il livello di utilizzazione cali drasticamente per i server con ID più alto: i server con ID piccoli (per costruzione) vengono selezionati per primi quando liberi. Altre tecniche di scheduling possono certamente mitigare questa situazione per cui sarebbe interessante - in una versione futura - sperimentare nuovi algoritmi di assegnazione dei task ai serventi dei sottosistemi e osservare come varia l'utilizzazione.
- \begin{center}
- \begin{figure}[H]
- \centering
- \includegraphics[width=0.7\textwidth]{immagini/grafici/serverStatus20.png}
- \caption{Utilizzazione per 20 server}
- \label{fig:server20}
- \end{figure}
- \end{center}
- Un ulteriore sviluppo futuro riguarda gli algoritmi di dispatching. In questo progetto non è mai stata utilizzata la prelazione, sarebbe quindi interessante introdurla. Dalla teoria sono infatti noti i vantaggi di quest'ultima in termini di riduzione dei tempi di risposta globali.
- Infine si potrebbe creare una Demo di simulazione del sistema tramite il software di simulazione Arena. Questo infatti consente all'utente di costruire un modello sperimentale posizionando moduli (di processi o logici), uniti tramite connettori che servono per specificare il flusso delle entità.
- \textcolor{red}{FAR PARTIRE IL MULTIRUN DALLO STESSO STREAM INVECE CHE DA SEED DIVERSO, IN MODO DA EVITARE SOVRAPPOSIZIONI}
- \newpage
- \begin{appendices}
- \section{Replicare i test} \label{replicare_test}
- Vengono qui riportate le informazioni necessarie alla corretta replicazione dei test presentati all'interno della relazione.
- Nelle tabelle presentate le colonne seguono la seguente corrispondenza:
- \begin{labeling}{hyper----}
- \item[seed ] SEED
- \item[algo. ] ALGORITHM
- \item[hyper. ] HYPEREXPO\_ENABLED
- \item[ops. ] OPERATIONS\_ENABLED
- \item[N ] N
- \item[batch ] BATCH
- \item[m.r. ] MULTI\_RUN
- \item[run ] RUNS
- \item[iter. ] ITERATIONS
- \end{labeling}
- I valori corrispondenti ai tassi di arrivo e servizio non sono riportati in quanto assumono sempre i valori richiesti dalla traccia.
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 12345 & 1 & FALSE & FALSE & 3 & TRUE & FALSE & - & 10000000\\
- \hline
- \end{tabular}
- \caption{simulazione standard con N=3}
- \label{table:standard3}
- \end{table}
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 12345 & 1 & FALSE & TRUE & 3 & TRUE & FALSE & - & 10000000\\
- \hline
- \end{tabular}
- \caption{simulazione standard con N=3 e OPERATIONS}
- \label{table:standard3_OP}
- \end{table}
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 12345 & 1 & FALSE & FALSE & 20 & TRUE & FALSE & - & 10000000\\
- \hline
- \end{tabular}
- \caption{simulazione standard con N=20}
- \label{table:standard20}
- \end{table}
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 12345 & 1 & FALSE & TRUE & 3 & TRUE & TRUE & 30 & 1000000\\
- \hline
- 12345 & 3 & FALSE & TRUE & 3 & TRUE & TRUE & 30 & 1000000\\
- \hline
- 12345 & 4(14) & FALSE & TRUE & 3 & TRUE & TRUE & 30 & 1000000\\
- \hline
- \end{tabular}
- \caption{Comparazione tra algoritmi di dispatching}
- \label{table:comparisonDispatch}
- \end{table}
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 12345 & 1 & FALSE & FALSE & 3 & FALSE & TRUE & 50 & 10000000\\
- \hline
- \end{tabular}
- \caption{simulazione con Multi-Run}
- \label{table:multi_run}
- \end{table}
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 12345 & 1 & FALSE & TRUE & 3 & TRUE & TRUE & 30 & 1000000\\
- \hline
- \end{tabular}
- \caption{simulazione veloce con Multi-Run}
- \label{table:fastMR}
- \end{table}
- \begin{table}[h!]
- \centering
- \begin{tabular}{|c c c c c c c c c|}
- \hline
- seed & algo. & hyper. & ops. & N & batch & m.r. & run & iter. \\ [0.5ex]
- \hline\hline
- 987654321 & 1 & FALSE & FALSE & 3 & TRUE & FALSE & - & *\\
- \hline
- \end{tabular}
- \caption{simulazione per performance del sistema}
- \label{table:ramsim}
- \end{table}
- \noindent *\\
- La simulazione è stata eseguita con molteplici volte con le seguenti iterazioni:
- \begin{multicols}{3}
- \begin{itemize}
- \item 100000
- \item 200000
- \item 300000
- \item 400000
- \item 500000
- \item 600000
- \item 700000
- \item 800000
- \item 900000
- \item 1000000
- \item 1100000
- \item 1200000
- \item 1300000
- \item 1400000
- \item 1500000
- \item 1600000
- \item 1700000
- \item 1800000
- \item 1900000
- \item 2000000
- \item 3000000
- \item 4000000
- \item 5000000
- \item 6000000
- \item 7000000
- \item 8000000
- \item 9000000
- \item 10000000
- \item 11000000
- \item 12000000
- \item 13000000
- \item 14000000
- \item 15000000
- \item 16000000
- \item 17000000
- \item 18000000
- \end{itemize}
- \end{multicols}
- \end{appendices}
- \newpage
- \begin{thebibliography}{9}
- \bibitem{spectrum}
- %n. cognome, n2. cognome.
- %\textit{titolo paper}
- %editore, anno
- %disponibile al link
- %\texttt{link}
- H. Takagi, B. H. Walke.
- \textit{Spectrum Requirement Planning in Wireless Communications: Model and Metholody for IMT-Advanced}
- John Wiley, 2008
- \bibitem{verify}
- R. G. Sargent.
- \textit{Verifying and Validating Simulation Models}
- Syracuse University (NY), 1994
- \bibitem{book1}
- L.Leemis, S. Park.
- \textit{Discrete-Event simulation: a first course}
- The college of William and Mary (Williamsburg), 1994
- \bibitem{verify}
- R. G. Sargent.
- \textit{Verifying and Validating Simulation Models}
- Syracuse University (NY), 1994
- \bibitem{hyperexpo}
- P.J. Smith, A. Firag, P.A. Dmochowski, M. Shafi.
- \textit{Analysis of the M/M/N/N Queue with two types of arrival process: Applications to future mobile raadio systems}
- Yuri Sotskov, 2011
- \end{thebibliography}
- \newpage
- \section{TODO}
- \begin{enumerate}
- \item Modello delle specifiche da integrare e correggere
- \item Modificare Figura 6 (ordine crescente)
- \item Modello computazionale run
- \item Analisi (a parole) algoritmo threshold
- \item Tutti i test!!!!!!
- \item Rileggere tutto una volta
- \item PULIRE IL CODICE! TOGLIERE LE VARIANZE, COMMENTARE ECC.
- \end{enumerate}
- SCALETTA CAPITOLI:
- \begin{enumerate}
- \item Introduzione
- \item Modello concettuale [Risultati analitici]
- \item Modello delle specifiche
- \item Modello computazionale
- \item Verifica
- \item Validazione
- \item Test [I]
- \item Sviluppi futuri
- \end{enumerate}
- \end{document}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement