diff --git a/docs/report/analisi.tex b/docs/report/analisi.tex index 3609de0..cac7ce8 100644 --- a/docs/report/analisi.tex +++ b/docs/report/analisi.tex @@ -1,18 +1,33 @@ -\section{Analisi dell'algoritmo} -L'algoritmo proposto in~\cite{bernstein2019fast} è basato su un approccio \textit{divide et impera}: l'operando viene diviso dalla funzione -\texttt{jumpdivstep}, che prende in input due polinomi $f, g$, di grado al più $n$ e con $\delta = \deg{f} - \deg{g}$ e individua -un \textit{pivot} $j$, che divide i polinomi a metà. La funzione \texttt{jumpdivstep} è quindi chiamata ricorsivamente passando come parametri le due -metà dei polinomi appena individuate, finché la loro dimensione non è sufficientemente piccola (vedi~\ref{impl}); questo punto viene invocata la -funzione \texttt{divstep}, che gestisce il caso base della ricorsione. -La funzione \texttt{jumpdivstep} prende come input di partenza la rappresentazione riflessa di modulo $f(x)$ ed elemento da invertire $a(x)$, e ritorna alla fine - la rappresentazione riflessa dell'inverso di $a(x)$, $\mathcal{H}_{0,1}$, con $V(x) \equiv a^{-1}(x)$. +\section{Analisi dell'algoritmo}\label{analisi} +In ~\cite{bernstein2019fast} gli autori descrivono due metodi per il calcolo di massimo comun divisore e inverso moltiplicativo: il primo per numeri interi, +il secondo per anelli di polinomi; nello specifico, andremo a sfruttare quest'ultimo per anelli di polinomi a coefficienti binari per le ragioni precedentemente citate. + +L'algoritmo di inversione che andiamo ad analizzare è basato su un approccio \textit{divide et impera}: il polinomio da invertire e il modulo vengono suddivisi dalla funzione +\texttt{jumpdivstep}, che prende in input due polinomi $f(x), g(x)$, di grado al più $n=2p-1$, con $\delta = \deg{(f(x))} - \deg{(g(x))}$ e individua +un \textit{pivot} per suddividere gli operandi in due metà\footnote{Questa scelta si è rivelata essere ottimale, come riportato in ~\cite{barenghi2020comprehensive}, ma +qualsiasi valore di $j$ compreso tra $1$ ed $n-1$ è valido}, ovvero $j = \lfloor \frac{n}{2} \rfloor$. + +La funzione \texttt{jumpdivstep} è quindi chiamata ricorsivamente passando come parametri le due +metà dei polinomi appena individuate, finché la loro dimensione non è sufficientemente piccola (ovvero fin quando la dimensione non è pari o inferiore a quella di una \textit{machine word}): +a questo punto viene invocata la funzione \texttt{divstep}, che gestisce il caso base della ricorsione; +i risultati trovati vengono quindi ricombinati fino ad ottenere il risultato finale. + +Nello specifico, la funzione \texttt{invert} chiama la funzione \texttt{jumpdivstep} passando come parametri le rappresentazioni riflesse del modulo $f(x)$ e dell'elemento da invertire $a(x)$: per rappresentazione riflessa +intendiamo il polinomio ottenuto invertendo il coefficiente del termine $x^i$ con quello del termine $x^{\deg(S(x))-i}$, ottenuto tramite la funzione \texttt{mirror}; alla fine, la funzione +ritorna la rappresentazione riflessa dell'inverso di $a(x)$, $H_{0,1}$, ottenuta dal prodotto dei risultati parziali calcolati dalle chiamate ricorsive. \begin{algorithm} \small \SetAlgoLined - \BlankLine \SetKwFunction{jumpdivstep}{jumpdivstep} \SetKwFunction{invert}{invert} + \KwIn{$f(x), g(x)$: polinomi binari\newline + $n$: grado massimo di $f(x)$\newline + $\delta = \deg{f(x)} - \deg{g(x)}$} + \KwOut{$P\times Q$: matrice di polinomi, risultato parziale dell'inversione} + \KwData{$ws$: dimensione in bit di una \textit{machine word}\newline + $P$, $Q$: matrici di polinomi, contengono i risultati parziali delle due chiamate ricorsive} + \BlankLine \SetKwFunction{divstep}{divstep} \SetKwProg{Fn}{function}{:}{} @@ -23,39 +38,55 @@ \section{Analisi dell'algoritmo} } $j \leftarrow \lfloor \frac{n}{2} \rfloor$\; - $\delta, \mathcal{P} \leftarrow$ \texttt{jumpdivstep}($j, \delta, f(x)\mod x^j, g(x)\mod x^j$)\; - $f^{\prime}(x) \leftarrow \mathcal{P}_{0,0}\cdot f(x) + \mathcal{P}_{0,1}\cdot g(x)$\; - $g^{\prime}(x) \leftarrow \mathcal{P}_{1,0}\cdot f(x) + \mathcal{P}_{1,1}\cdot g(x)$\; - $\delta, \mathcal{Q} \leftarrow$ \texttt{jumpdivstep}($n-j, \delta, \frac{f^{\prime}(x)}{x^j}, \frac{g^{\prime}(x)}{x^j}$)\; - - \Return$\delta, (\mathcal{P}\times\mathcal{Q})$ - } - \BlankLine - \Fn{\invert{$f(x), a(x)$}}{ - $S(x) \leftarrow$ \texttt{MIRROR}($f(x)$)\; - $R(x) \leftarrow$ \texttt{MIRROR}($a(x)$)\; - $\delta, \mathcal{H} \leftarrow$ \texttt{jumpdivstep}($2m - 1, 1, S(x), R(x)$)\; - $V(x) \leftarrow$ \texttt{MIRROR}($\mathcal{H}_{0,1}$)\; - \Return$V(x)$\; + $\delta, P \leftarrow$ \texttt{jumpdivstep}($j, \delta, f(x)\mod x^j, g(x)\mod x^j$)\; + $\bar{f(x)} \leftarrow P_{0,0}\cdot f(x) + P_{0,1}\cdot g(x)$\; + $\bar{g(x)} \leftarrow P_{1,0}\cdot f(x) + P_{1,1}\cdot g(x)$\; + $\delta, Q \leftarrow$ \texttt{jumpdivstep}($n-j, \delta, \frac{\bar{f(x)}}{x^j}, \frac{\bar{g(x)}}{x^j}$)\; + \Return{$\delta, (P\times Q)$}\; } + \caption{\texttt{jumpdivstep}} + \end{algorithm} - \caption{jumpdivstep} + \begin{algorithm} + \small + \SetAlgoLined + \KwIn{$f(x)$: polinomio irriducibile di $GF(2^p)$\newline + $a(x)$: elemento invertibile di $GF(2^p)$} + \KwOut{$V(x)$, con $a^{-1}(x) \equiv V(x) \in GF(2^p)$} + \SetKwFunction{invert}{invert} + + \SetKwFunction{divstep}{divstep} + \SetKwProg{Fn}{function}{:}{} + \BlankLine + \Fn{\invert{$f(x), a(x)$}}{ + $S(x) \leftarrow$ \texttt{mirror}($f(x)$)\; + $R(x) \leftarrow$ \texttt{mirror}($a(x)$)\; + $\delta, H \leftarrow$ \texttt{jumpdivstep}($2p - 1, 1, S(x), R(x)$)\; + $V(x) \leftarrow$ \texttt{mirror}($H_{0,1}$)\; + \Return$V(x)$\; + + } + \caption{\texttt{invert}} \end{algorithm} - \subsection*{\textbf{\textit{Simulazione} dell'algoritmo}} Possiamo, partendo dall'algoritmo qui presentato, ricostruire un albero di ricorsione tracciando tutte le - chiamate ed i vari parametri necessari: la prima chiamata a \texttt{jumpdivstep} (riga 14) è la radice dell'albero, - la prima chiamata effettuata (riga 6) corrisponde al figlio destro di un nodo, mentre la seconda (riga 9) corrisponde al + + + + \subsection*{\textbf{\textit{Simulazione} dell'algoritmo}} Possiamo, partendo dall'algoritmo qui presentato, ricostruire un albero di ricorsione binario tracciando tutte le + chiamate ed i vari parametri necessari: la prima chiamata a \texttt{jumpdivstep} (\texttt{invert}, riga 4) è la radice dell'albero, + la prima chiamata effettuata (\texttt{jumpdivstep}, riga 6) corrisponde al figlio destro di un nodo, mentre la seconda (\texttt{jumpdivstep}, riga 9) corrisponde al figlio sinistro; quando la dimensione degli operandi è pari o inferiore alla \textit{word size}, ossia quando viene invocata la funzione \texttt{divstep}, il nodo corrispondente nell'albero di ricorsione risulta essere una foglia. Analizzando l'albero di ricorsione ed i parametri relativi ai nodi, possiamo inoltre determinare le dimensioni - dei vettori che contengono i risultati intermedi ($\mathcal{P}, \mathcal{Q}$) e gli operandi intermedi - ($f^{\prime}(x), g^{\prime}(x)$), nonché gli indici di accesso ai suddetti per ogni chiamata. Da qui, possiamo \textit{simulare} + dei vettori che contengono i risultati intermedi ($P, Q$) e gli operandi intermedi + ($\bar{f(x)}, \bar{g(x)}$), nonché gli indici di accesso ai suddetti per ogni chiamata. Da qui, possiamo \textit{simulare} le chiamate attraversando l'albero usando un approccio \textit{depth-first}, dando priorità ai figli destri - (che per costruzione corrispondono alla prima chiamata). + (che per costruzione corrispondono alla prima chiamata). È inoltre interessante notare che le operazioni ed i parametri necessari per ogni chiamata dipendano solo dalla - dimensione dei parametri di input, e non dai parametri stessi; questo ci permetterà di effettuare tutte le ottimizzazioni - riportate in~\ref{ott}, e quindi poter generare una versione + dimensione dei parametri di input, e non dai parametri stessi: dato che le dimensioni sono note tramite un'analisi statica, possiamo derivare + l'albero di ricorsione a compile time; questo ci permetterà di effettuare tutte le ottimizzazioni + riportate in~\ref{impl}, e quindi poter generare una versione iterativa di \texttt{jumpdivstep} specifica per dimensione dell'input. \subsubsection*{Contenuto dei nodi} @@ -65,7 +96,7 @@ \section{Analisi dell'algoritmo} \item \texttt{n}: grado massimo dei operandi ricevuti in input \item \texttt{j}: grado massimo degli operandi passati alla prima chiamata ricorsiva (figlio destro) \item \texttt{n-j}: grado massimo degli operandi passati alla seconda chiamata ricorsiva (figlio sinistro) - \item \texttt{num\_digits\_(n|j|nminusj)}: numero di \texttt{DIGIT} (vedi~\ref{impl}) necessari a contenere gli operandi di cui sopra + \item \texttt{num\_digits\_(n|j|nminusj)}: dimensione degli operandi di cui sopra, espressa in \texttt{digit} \end{itemize} diff --git a/docs/report/images/mean.tex b/docs/report/images/mean.tex new file mode 100644 index 0000000..b90216b --- /dev/null +++ b/docs/report/images/mean.tex @@ -0,0 +1,233 @@ + +\begin{figure} + \centering + \begin{tikzpicture}[scale=0.9] + \pgfplotsset{every axis/.append style={semithick}, legend style={nodes={scale=0.7, transform shape}, at={(1,0)},anchor=south east}} + + \begin{semilogyaxis}[ + xlabel=p (bit),ylabel=Tempo (cicli di clock), grid=major, xticklabel style={ + /pgf/number format/fixed, + /pgf/number format/precision=5 + }, scaled x ticks=false ] + + \addplot[no marks, color=olive] coordinates{ + (7187, 1159197.4) + (8237, 1469920.2) + (10853, 2336473.4) + (13109, 3246316.8) + (13397, 3347390.0) + (15331, 4277250.6) + (16067, 4695806.2) + (16229, 4694091.6) + (19709, 6764716.4) + (20981, 7556269.0) + (21611, 8000344.2) + (22901, 8858165.2) + (23371, 9267820.8) + (25579, 10906522.6) + (28277, 13221080.6) + (28411, 13423327.6) + (30803, 15622464.4) + (35117, 20323059.0) + (35507, 20936273.0) + (36629, 22957209.2) + (40787, 27063629.4) + (42677, 29510000.0) + (48371, 37725077.4) + (52667, 45033239.4) + (58171, 54986958.0) + (61717, 61625946.6) + (83579, 110553683.6) + }; + \addlegendentry{KTT} + + \addplot[no marks, color=brown] coordinates{ + (7187, 6368874.4) + (8237, 8364095.6) + (10853, 13922595.2) + (13109, 20491931.0) + (13397, 21293264.8) + (15331, 28056795.4) + (16067, 30382587.2) + (16229, 31722889.2) + (19709, 45575386.6) + (20981, 51657051.6) + (21611, 54956980.4) + (22901, 62186967.6) + (23371, 64996685.6) + (25579, 76589311.4) + (28277, 94263290.2) + (28411, 94610992.2) + (30803, 112420385.4) + (35117, 145454923.6) + (35507, 148202625.6) + (36629, 158941209.0) + (40787, 196929065.2) + (42677, 214790361.0) + (48371, 274893671.4) + (52667, 325854983.0) + (58171, 399131155.0) + (61717, 448249901.0) + (83579, 834007747.8) + }; + \addlegendentry{BCH} + + \addplot[no marks, color=blue] coordinates { + (7187, 1561699.8) + (8237, 1827586.0) + (10853, 3110983.6) + (13109, 3770875.2) + (13397, 3678711.8) + (15331, 4900348.2) + (16067, 4806660.2) + (16229, 5133151.8) + (19709, 7576635.0) + (20981, 7857809.2) + (21611, 7268007.2) + (22901, 8562007.6) + (23371, 8120296.6) + (25579, 9097204.4) + (28277, 13504138.2) + (28411, 13120726.4) + (30803, 12347247.6) + (35117, 14105630.4) + (35507, 14518979.4) + (36629, 15177688.2) + (40787, 17682828.6) + (42677, 19342802.0) + (48371, 22206770.4) + (52667, 22177420.0) + (58171, 29189824.2) + (61717, 31306422.6) + (83579, 48987526.4) + }; + \addlegendentry{Fermat-comp} + + \addplot[no marks, color=orange] coordinates{ + (7187, 10597590.4) + (8237, 17184007.0) + (10853, 25297424.2) + (13109, 33119433.8) + (13397, 34034539.2) + (15331, 42226171.0) + (16067, 45221734.2) + (16229, 46011999.6) + (19709, 81895383.8) + (20981, 89587471.2) + (21611, 94080496.0) + (22901, 101717262.2) + (23371, 105224090.2) + (25579, 119787535.4) + (28277, 143408586.6) + (28411, 142583988.2) + (30803, 163023836.2) + (35117, 256737134.2) + (35507, 261421235.4) + (36629, 274770918.6) + (40787, 320387425.4) + (42677, 343968765.2) + (48371, 417034409.0) + (52667, 474298878.0) + (58171, 568372615.0) + (61717, 623609013.0) + (83579, 1370972271.0) + }; + \addlegendentry{Fermat-sq} + + \addplot[no marks, color=purple] coordinates { + (7187, 809715.8) + (8237, 915526.2) + (10853, 1771415.4) + (13109, 2103486.2) + (13397, 2047749.8) + (15331, 2939877.8) + (16067, 2740291.6) + (16229, 2917695.0) + (19709, 4695404.2) + (20981, 4895648.2) + (21611, 4576126.0) + (22901, 5257624.8) + (23371, 5057833.2) + (25579, 5597524.4) + (28277, 9083607.2) + (28411, 8978193.0) + (30803, 8485064.2) + (35117, 9378049.2) + (35507, 9621184.2) + (36629, 10076641.2) + (40787, 12150942.0) + (42677, 13344390.2) + (48371, 14827613.0) + (52667, 13711557.0) + (58171, 21056187.8) + (61717, 22448997.0) + (83579, 35664757.6) + }; + \addlegendentry{Fermat-tab} + + \addplot[no marks, color=red] coordinates { + (7187, 2301133.4) + (8237, 2390625.0) + (10853, 4044599.2) + (13109, 5300937.4) + (13397, 5446870.6) + (15331, 6648405.6) + (16067, 6702943.8) + (16229, 6724461.8) + (19709, 10310837.6) + (20981, 11196952.2) + (21611, 11407319.0) + (22901, 11667615.0) + (23371, 11805428.0) + (25579, 13449986.4) + (28277, 20024899.6) + (28411, 17511886.6) + (30803, 19631753.0) + (35117, 21432919.4) + (35507, 22369455.6) + (36629, 23348801.4) + (40787, 28987888.4) + (42677, 32262773.2) + (48371, 34922057.2) + (52667, 39038512.2) + (58171, 50907356.2) + (61717, 54401236.2) + (83579, 85570203.0) + }; + \addlegendentry{BY before} + + \addplot[no marks, color=green] coordinates { + (7187, 1782584.6) + (8237, 1962955.5) + (10853, 3299358.6) + (13109, 4362019.9) + (13397, 4522305.42) + (15331, 5368479.5) + (16067, 5286806.16) + (16229, 5325745.7) + (19709, 8352941.2) + (20981, 9162305.2) + (21611, 9307480.6) + (22901, 9655103.68) + (23371, 9723034.62) + (25579, 11202767.42) + (28277, 14555232.2) + (28411, 14622453.44) + (30803, 17820851.56) + (35117, 17008580.68) + (35507, 17287261.4) + (36629, 18419434.4) + (40787, 24264261.8) + (42677, 26849432.52) + (48371, 27695913.8) + (52667, 30734590.3) + (58171, 42328589.2) + (61717, 45814829.52) + (83579, 71488995.4) + }; + \addlegendentry{BY after} + + \end{semilogyaxis}% +\end{tikzpicture}% +\caption{Tempi di esecuzione} +\end{figure} \ No newline at end of file diff --git a/docs/report/images/memory.tex b/docs/report/images/memory.tex new file mode 100644 index 0000000..2406474 --- /dev/null +++ b/docs/report/images/memory.tex @@ -0,0 +1,106 @@ +\begin{figure} + \centering +\pgfplotsset{every axis/.append style={semithick}, legend style={nodes={scale=0.7, transform shape}, at={(1,0)},anchor=south east}} +\begin{tikzpicture}[scale=0.8] +\begin{axis}[ + xlabel=p (bit),ylabel=Memoria occupata (KByte), grid=major, ticklabel style={ + /pgf/number format/fixed, + /pgf/number format/precision=5 + }, scaled ticks=false ] + + \addplot[no marks, color=blue] coordinates { + (7187, 7.375) + (8237, 8.75) + (10853, 11.0) + (13109, 13.125) + (13397, 13.5) + (15331, 15.375) + (16067, 15.875) + (16229, 15.875) + (19709, 19.71875) + (20981, 21.09375) + (21611, 21.59375) + (22901, 22.71875) + (23371, 23.09375) + (25579, 25.59375) + (28277, 27.84375) + (28411, 27.96875) + (30803, 30.46875) + (35117, 34.90625) + (35507, 35.28125) + (36629, 36.15625) + (40787, 40.03125) + (42677, 42.15625) + (48371, 47.53125) + (52667, 51.875) + (58171, 57.5) + (61717, 60.875) + (83579, 82.125) + }; + \addlegendentry{P} + + \addplot[no marks, color=red] coordinates { + (7187, 6.9375) + (8237, 7.9375) + (10853, 10.5) + (13109, 12.71875) + (13397, 13.0) + (15331, 14.90625) + (16067, 15.625) + (16229, 15.78125) + (19709, 19.1875) + (20981, 20.40625) + (21611, 21.03125) + (22901, 22.3125) + (23371, 22.75) + (25579, 24.90625) + (28277, 27.5625) + (28411, 27.6875) + (30803, 30.03125) + (35117, 34.21875) + (35507, 34.59375) + (36629, 35.6875) + (40787, 39.78125) + (42677, 41.625) + (48371, 47.1875) + (52667, 51.40625) + (58171, 56.78125) + (61717, 60.25) + (83579, 81.5625) + }; + \addlegendentry{Q} + + \addplot[no marks, color=orange] coordinates { + (7187, 10.9375) + (8237, 12.84375) + (10853, 16.375) + (13109, 19.59375) + (13397, 20.109375) + (15331, 22.9375) + (16067, 23.796875) + (16229, 23.875) + (19709, 29.421875) + (20981, 31.421875) + (21611, 32.234375) + (22901, 33.984375) + (23371, 34.59375) + (25579, 38.171875) + (28277, 41.734375) + (28411, 41.921875) + (30803, 45.59375) + (35117, 52.15625) + (35507, 52.71875) + (36629, 54.140625) + (40787, 60.046875) + (42677, 63.09375) + (48371, 71.25) + (52667, 77.6875) + (58171, 86.0) + (61717, 91.109375) + (83579, 123.046875) + }; + \addlegendentry{$\bar{f(x)}$, $\bar{g(x)}$} +\end{axis}% +\end{tikzpicture}% +\caption{Memoria occupata} +\end{figure} \ No newline at end of file diff --git a/docs/report/images/tstat.tex b/docs/report/images/tstat.tex new file mode 100644 index 0000000..4f2f27e --- /dev/null +++ b/docs/report/images/tstat.tex @@ -0,0 +1,206 @@ +\begin{figure} + \centering +\pgfplotsset{every axis/.append style={semithick}, legend style={nodes={scale=0.7, transform shape}, at={(1,0)},anchor=south east}} +\begin{tikzpicture}[scale=0.9] + \begin{semilogyaxis}[ + xlabel=p (bit),ylabel=t statistica (in modulo), grid=major, xticklabel style={ + /pgf/number format/fixed, + /pgf/number format/precision=5 + }, scaled x ticks=false ] + + \addplot[no marks, color=olive] coordinates { + (7187, 652.005696) + (8237, 3019.920377) + (10853, 1910.771944) + (13109, 5071.778073) + (13397, 2946.893161) + (15331, 5332.226134) + (16067, 2139.75731) + (16229, 998.246284) + (19709, 1332.526004) + (20981, 4239.90178) + (21611, 8454.250835) + (22901, 1920.498214) + (23371, 5492.804618) + (25579, 1155.64429) + (28277, 8096.484658) + (28411, 1371.076919) + (30803, 6732.774469) + (35117, 4094.864009) + (35507, 1734.952881) + (36629, 5973.390682) + (40787, 8408.629239) + (42677, 23009.76453) + (48371, 20572.562632) + (52667, 16117.718704) + (58171, 11429.139155) + (61717, 19250.383818) + (83579, 1419.418492) + }; + \addlegendentry{KTT} + + \addplot[no marks, color=brown] coordinates { + (7187, 86.646338) + (8237, 125.408114) + (10853, 64.681601) + (13109, 372.819976) + (13397, 130.796415) + (15331, 141.441714) + (16067, 928.621171) + (16229, 197.779837) + (19709, 204.312264) + (20981, 1011.501825) + (21611, 353.268775) + (22901, 554.996088) + (23371, 201.444914) + (25579, 83.641382) + (28277, 1285.511342) + (28411, 226.541613) + (30803, 617.673131) + (35117, 346.507444) + (35507, 573.58292) + (36629, 720.523447) + (40787, 318.858938) + (42677, 92.41314) + (48371, 4425.944718) + (52667, 7515.104843) + (58171, 1120.57332) + (61717, 531.092093) + (83579, 304.239061) + }; + \addlegendentry{BCH} + + \addplot[no marks, color=blue] coordinates { + (7187, 0.493086) + (8237, 0.08653) + (10853, 1.309049) + (13109, 4.778504) + (13397, 0.782128) + (15331, 0.71157) + (16067, 2.079124) + (16229, 0.580534) + (19709, 0.672241) + (20981, 1.0493) + (21611, 0.083094) + (22901, 0.567385) + (23371, 1.04121) + (25579, 0.660099) + (28277, 0.861794) + (28411, 1.653982) + (30803, 2.134661) + (35117, 0.048959) + (35507, 0.06948) + (36629, 3.96631) + (40787, 2.752093) + (42677, 3.304725) + (48371, 0.341822) + (52667, 1.160096) + (58171, 2.671217) + (61717, 2.201135) + (83579, 1.496464) + }; + \addlegendentry{Fermat-comp} + + \addplot[no marks, color=orange] coordinates { + (7187, 1.162409) + (8237, 2.330743) + (10853, 2.12729) + (13109, 3.016198) + (13397, 1.238996) + (15331, 0.330162) + (16067, 1.078995) + (16229, 3.658359) + (19709, 4.467738) + (20981, 2.591605) + (21611, 4.04695) + (22901, 1.106657) + (23371, 1.312441) + (25579, 1.322171) + (28277, 0.266311) + (28411, 0.262227) + (30803, 1.901191) + (35117, 1.544098) + (35507, 2.154404) + (36629, 0.747209) + (40787, 1.713264) + (42677, 1.281831) + (48371, 0.530638) + (52667, 2.117118) + (58171, 1.600775) + (61717, 2.704511) + (83579, 2.992715) + }; + \addlegendentry{Fermat-sq} + + \addplot[no marks, color=purple] coordinates { + (7187, 1.646462) + (8237, 0.293479) + (10853, 3.342243) + (13109, 0.860273) + (13397, 1.182994) + (15331, 0.875522) + (16067, 1.25272) + (16229, 0.116413) + (19709, 0.001627) + (20981, 1.131281) + (21611, 0.481985) + (22901, 0.268159) + (23371, 1.231348) + (25579, 1.886799) + (28277, 1.441204) + (28411, 1.222019) + (30803, 0.758732) + (35117, 0.690352) + (35507, 0.351563) + (36629, 2.346714) + (40787, 0.764265) + (42677, 1.863431) + (48371, 0.727855) + (52667, 4.463352) + (58171, 3.378872) + (61717, 1.119912) + (83579, 1.95091) + }; + \addlegendentry{Fermat-tab} + + \addplot[no marks, color=green] coordinates { + (7187, 0.342964) + (8237, 1.79303) + (10853, 2.511967) + (13109, 0.05001) + (13397, 2.238948) + (15331, 2.499593) + (16067, 4.175354) + (16229, 0.568396) + (19709, 0.462919) + (20981, 0.405652) + (21611, 2.010867) + (22901, 0.140311) + (23371, 4.014809) + (25579, 0.045285) + (28277, 0.236084) + (28411, 0.81202) + (30803, 1.22736) + (35117, 0.06737) + (35507, 3.550464) + (36629, 2.543941) + (40787, 3.429449) + (42677, 0.312068) + (48371, 2.789529) + (52667, 1.693412) + (58171, 0.0794) + (61717, 2.885019) + (83579, 4.281391) + }; + \addlegendentry{BY} + + \addplot[no marks, color=black, style=dashed] coordinates { + (7187, 4.5) + (83579, 4.5) + }; + + + \end{semilogyaxis}% +\end{tikzpicture}% +\caption{Valori della t di Student} +\end{figure} \ No newline at end of file diff --git a/docs/report/impl-ott.tex b/docs/report/impl-ott.tex index c580e5f..a47ddd1 100644 --- a/docs/report/impl-ott.tex +++ b/docs/report/impl-ott.tex @@ -4,13 +4,15 @@ \subsection*{\textbf{Rappresentazione dei polinomi}} coefficiente di un polinomio binario in formato Big-Endian (leggendo da sinistra a destra, i primi elementi che si incontrano sono i coefficienti di grado più alto) -Una \textit{machine word} $A_i$ è considerata un \texttt{DIGIT} ed i byte che -compongono un \texttt{DIGIT} sono in formato Big Endian; allo stesso modo, -anche gli elementi con più \texttt{DIGIT} sono rappresentati in +Una \textit{machine word} è considerata un \texttt{digit} ed i byte che +compongono un \texttt{digit} sono in formato Big Endian; allo stesso modo, +anche gli elementi con più \texttt{digit} sono rappresentati in formato Big Endian. \begin{table} + \caption{Rappresentazione dei polinomi, singolo byte} \begin{tabular}{lll} - Bin & Hex & Polinomio \\ + \hline + \textbf{Bin} & \textbf{Hex} & \textbf{Polinomio} \\ \hline 0000 0000 & 0x00 & 0 \\ 0000 0001 & 0x01 & 1 \\ @@ -20,34 +22,64 @@ \subsection*{\textbf{Rappresentazione dei polinomi}} 0000 1111 & 0x0F & $x^3+x^2+x+1$ \\ $\cdots$ & $\cdots$ & $\cdots$ \\ 1111 1111 & 0xFF & $x^7+x^6+x^5+\cdots+x+1$ \\ + \hline \end{tabular} - \caption{Rappresentazione dei polinomi, singolo byte} \end{table} \subsubsection*{Estensioni dell'ISA x86} L'implementazione proposta in~\cite{benchmark} utilizza AVX, un'estensione dell' Instruction Set Architecture di x86 che permette di lavorare su più parole di memoria in parallelo, portando notevoli vantaggi nelle operazioni aritmetiche: ciò significa, -su una macchina a 64 bit (dimensione di un \texttt{DIGIT}), lavorare su 128 o 256 bit. +su una macchina a 64 bit (dimensione di un \texttt{digit}), lavorare su 128 o 256 bit. Questo ci permette inoltre di avere un'implementazione molto efficiente per i prodotti, utilizzando funzioni -altamente specializzate per polinomi di 8 \texttt{DIGIT} o meno e loro combinazioni per dimensioni -maggiori~\cite{bodrato2007towards}; gli intrinsics permettono anche l'implementazione delle diverse versioni di -\texttt{divstep}. +altamente specializzate per polinomi di 8 \texttt{digit} o meno e loro combinazioni per dimensioni +maggiori, come riportato in~\cite{bodrato2007towards}; gli intrinsics, funzioni gestite direttamente dal compilatore che permettono di usare +istruzioni specifiche dell'architettura per cui si sta compilando come fossero chiamate a funzioni standard, permettono inoltre +l'implementazione delle diverse versioni di \texttt{divstep}. \subsection*{\textbf{Punti critici}}\label{crit} -Analizzando l'esecuzione dell'algoritmo tramite \texttt{callgrind}, notiamo che la +Tramite un'analisi di complessità asintotica, supportata dai risultati sperimentali ottenuti tramite \texttt{callgrind}, notiamo che la maggior parte del tempo di esecuzione è dovuta a \texttt{gf2x\_scalarprod}: ciò non ci sorprende, in quanto -questa funzione è invocata due volte per il calcolo di $f^{\prime}(x)$ e $g^{\prime}(x)$ (righe 7-8), e altre quattro per $\mathcal{P \times \mathcal{Q}}$ (riga 10); inoltre, -per quest'ultima operazione, sono necessarie altrettante chiamate a memcpy, per spostare i risultati ottenuti da un vettore temporaneo alla +questa funzione è invocata due volte per il calcolo di $\bar{f(x)}$ e $\bar{g(x)}$ (\texttt{jumpdivstep}, righe 7-8), e altre quattro per $P \times Q$ (\texttt{jumpdivstep}, riga 10); inoltre, +per quest'ultima operazione, sono necessarie altrettante chiamate a \texttt{memcpy}, per spostare i risultati ottenuti da un vettore temporaneo alla destinazione desiderata. +\begin{algorithm} + \small + \SetAlgoLined + \SetKwFunction{scalarprod}{scalarprod} + \KwIn{$a_0, a_1, b_0, b_1$: array di polinomi\newline + $na, nb$: dimensioni degli array di polinomi} + \KwOut{$res = a_0\cdot b_0 + a_1 \cdot b_1$, dimensione $na+nb$} + \BlankLine + \SetKwProg{Fn}{function}{:}{} -La funzione \texttt{gf2x\_scalarprod} prende in input due coppie di polinomi ($a_{0},a_{1}$, $b_{0},b_{1}$), di dimensione rispettivamente $na$ e $nb$ \texttt{DIGIT}, e + \Fn{\scalarprod{$na, a_0, a_1, nb, b_0, b_1$}}{ + + \texttt{DIGIT} tmp[$na*2$]\; + \texttt{DIGIT} tmp2[$na*2$]\; + \texttt{DIGIT} buffer[$na$]\; + \texttt{memset}(buffer, 0x00, ($na-nb$)*\texttt{DIGIT\_SIZE\_B})\; + \BlankLine + \texttt{memcpy}(buffer+($na-nb$), $b_0$, $nb$*\texttt{DIGIT\_SIZE\_B})\; + \texttt{GF2X\_MUL}($na*2$, tmp, $a_0$, buffer)\; + \BlankLine + \texttt{memcpy}(buffer+($na-nb$), $b_1$, $nb$*\texttt{DIGIT\_SIZE\_B})\; + \texttt{GF2X\_MUL}($na*2$, tmp2, $a_1$, buffer)\; + \BlankLine + \texttt{gf2x\_add}($na*2$, tmp, tmp, tmp2)\; + \texttt{memcpy}(res, tmp+($na-nb$), ($na+nb$)*\texttt{DIGIT\_SIZE\_B})\; + \Return{res} + } + \caption{\texttt{gf2x\_scalarprod} (per $na > nb$)} + \end{algorithm} + +La funzione \texttt{gf2x\_scalarprod} prende in input due coppie di polinomi ($a_{0},a_{1}$, $b_{0},b_{1}$), di dimensione rispettivamente $na$ e $nb$ \texttt{digit}, e produce in output il prodotto scalare $res = a_{0} \cdot b_{0} + a_{1} \cdot b_{1}$, di dimensione $nr = na+nb$; in realtà, per poter eseguire le moltiplicazioni -tra polinomi, è necessario spostare l'operando più corto in un buffer e aggiungere zeri nelle posizioni dei coefficienti più significativi mancanti, fino +tra polinomi, è necessario spostare l'operando più corto in un buffer (righe 6, 8) e aggiungere zeri nelle posizioni dei coefficienti più significativi mancanti (riga 5), fino a raggiungere la dimensione dell'altro operando. -Una volta calcolati i prodotti, questi vengono ulteriormente manipolati, troncando i coefficienti superflui, shiftandoli (calcolo di $f^{\prime}$ e $g^{\prime}$, righe 7-8) e +Una volta calcolati i prodotti, questi vengono ulteriormente manipolati, troncando i coefficienti superflui, shiftandoli (\texttt{jumpdivstep}, righe 7-8) e spostandoli da una posizione all'altra; analizzando come questi polinomi vengono manipolati, possiamo andare a salvare i risultati direttamente nelle posizioni corrette, riduendo i tempi di esecuzione. @@ -55,43 +87,79 @@ \subsection*{\textbf{Ottimizzazioni}}\label{ott} \subsubsection*{Allocazione dei polinomi} Il primo passo nell'unrolling dell'algoritmo ricorsivo consiste nell'allocare in una volta sola tutta la memoria necessaria per salvare -i risultati e gli operandi intermedi, ossia $ \mathcal{P}, \mathcal{Q}, f^{\prime}$ e $g^{\prime}$; le stesse porzioni di memoria vengono riutilizzate da diverse +i risultati e gli operandi intermedi, ossia $ P, Q, \bar{f(x)}$ e $\bar{g(x)}$; le stesse porzioni di memoria vengono riutilizzate da diverse chiamate in momenti diversi, per cui viene presa la dimensione massima per ogni \textit{slot}, individuabile percorrendo il ramo destro dell'albero di ricorsione -dalla radice all'ultima foglia. Abbiamo quindi, con un albero di ricorsione di profondità $d$: +dalla radice all'ultima foglia. Partendo con operandi di grado $n_0-1$, \texttt{digit} di dimensione $s$ e parole di memoria di dimensione $ws$ +(entrambe espresse in bit), avremo un albero di ricorsione di profondità $d=\lceil \log_{2}\frac{n}{s} \rceil$; per ogni livello, avremo +\begin{equation*} + j_{i} = \floor*{\left(\floor*{\frac{n_i}{2}} + ws - 2\right) \cdot \frac{1}{ws-1}} \cdot (ws-1) +\end{equation*} +\begin{equation*} + n_{i} = j_{i-1} \qquad (i \neq 0) +\end{equation*} +Le operazioni di somma, prodotto e divisione che includono $ws$ sono necessarie ad ottenere, alla fine della ricorsione, polinomi di grado $ws-1$\footnote{In alcuni casi +i polinomi ottenuti sono di grado inferiore per \textit{mancanza di coefficienti}}, in modo da sfruttare appieno gli intrinsics di AVX. + +Partendo da quanto appena trovato, possiamo calcolare il numero di \texttt{digit} necessario a memorizzare i vari polinomi: +\begin{equation*} + \begin{aligned} + \mathrm{\texttt{num\_digits\_n}_i} = \ceil*{\frac{n_i}{s}}\\ + \mathrm{\texttt{num\_digits\_j}_i} = \ceil*{\frac{j_i}{s}}\\ + \mathrm{\texttt{num\_digits\_nminusj}_i} = \ceil*{\frac{n_i - j_i}{s}}\\ + \end{aligned} +\end{equation*} + +Possiamo quindi individuare le dimensioni degli slot dei vari array in base al livello di profondità $i$: \begin{itemize} - \item $\mathcal{P}$: 4 array composti da $d$ componenti, ognuno di dimensione \texttt{num\_digits\_j}; - \item $\mathcal{Q}$: 4 array composti da $d$ componenti, ognuno di dimensione \texttt{num\_digits\_nminusj}; - \item $f^{\prime}$: 1 array composto da $d-1$ componenti, ognuno di dimensione \texttt{num\_digits\_n} + \texttt{num\_digits\_j}; - \item $g^{\prime}$: come al punto precedente. + \item $P$: $d$ slot di dimensione $\mathrm{\texttt{num\_digits\_j}}_i$, 4 array + \item $P$: $d$ slot di dimensione $\mathrm{\texttt{num\_digits\_nminusj}}_i$, 4 array + \item $\bar{f(x)}$: $d-1$ slot di dimensione $\mathrm{\texttt{num\_digits\_n}}_i + \mathrm{\texttt{num\_digits\_j}}_i$, 1 array + \item $\bar{g(x)}$: come al punto precedente. \end{itemize} Tenendo traccia delle dimensioni dei vari componenti è poi possibile determinare gli indici di accesso agli array per i vari valori di $d$. \subsubsection*{Scomposizione dei prodotti} + Come accenato, le funzioni per il calcolo del prodotto tra polinomi richiedono operandi di dimensione uguale: invece di aggiungere coefficienti -nulli al polinomio più corto~($a$), possiamo dividere il polinomio più lungo ($b$) in due parti: la parte \textit{inferiore} ($b_{0}$, coefficienti meno significativi), -della stessa dimensione di $a$, viene moltiplicata direttamente con $a$ stesso; il procedimento viene quindi ripetuto considerando ora il polinomio $a$ e -la parte restante dell'altro polinomio, $b_{1}$, fino ad esaurimento. -I vari sottoprodotti che vengono calcolati vanno quindi sommati: dati due sottoprodotti successivi $r_i$, $r_{i+1}$, abbiamo che $\deg{r_{i+1}}-\deg{r_i} = na$, -(in modo simile a quanto sopra, $na$ indica la dimensione del poliniomio più corto alla $i$-esima iterazione). +nulli al polinomio più corto~($a = 0, a_1$), possiamo dividere il polinomio più lungo ($b = b_0, b_1$) in due parti: +\begin{center} + \begin{tabular}{cccc} + & $0$ & $a_1$ & $\times$ \\ + & $b_0$ & $b_1$ & =\\ + \hline + & $0\cdot b_1$ &$a_1\cdot b_1$ & +\\ + &\hspace{-9ex}$0\cdot b_0$&\hspace{-9ex}$a_1\cdot b_0$&\hspace{-10ex}\-- + \end{tabular} +\end{center} +la parte \textit{inferiore} ($b_{1}$, coefficienti meno significativi), +della stessa dimensione di $a_1$, viene moltiplicata direttamente con $a_1$ stesso; il procedimento viene quindi ripetuto considerando ora il polinomio $a_1$ e +la parte restante dell'altro polinomio, $b_{0}$, fino ad esaurimento. + + +I vari sottoprodotti che vengono calcolati vanno quindi sommati: dati due sottoprodotti successivi $r_i$, $r_{i+1}$, abbiamo che $\deg({r_{i+1}})-\deg({r_i}) = na$ +(in modo simile a quanto sopra, $na$ indica la dimensione del poliniomio più corto alla $i$-esima iterazione): con riferimento all'esempio, abbiamo che $r_1 = a_1\cdot b_1$ e $r_2 = a_1\cdot b_0$, +per cui i $na$ coefficienti meno significativi di $r_1$ vengono sommati ai $na$ coefficienti più significativi di $r_2$, mentre i restanti ($na$ per $r_1$, $nb$ per $r_2$) vengono semplicemente riportati +come sono nel risultato, in quanto i sottoprodotti restanti sono nulli. + Quindi, nell'implementazione del generatore, sostituiamo ogni chiamata a \texttt{gf2x\_scalarprod} con la corrispondente sequenza di \texttt{gf2x\_add} e \texttt{GF2X\_MUL}, utilizzando un accumulatore, $nr$, per tenere traccia dell'offset da considerare; -inoltre, nel caso i due operandi siano di dimensioni inferiori agli 8 \texttt{DIGIT}, andiamo ad utilizzare direttamente le funzioni specifiche per la dimensione +inoltre, nel caso i due operandi siano di dimensioni inferiori agli 8 \texttt{digit}, andiamo ad utilizzare direttamente le funzioni specifiche per la dimensione desiderata (\texttt{gf2x\_mul\_X\_avx}), evitando le chiamate a \texttt{GF2X\_MUL}. \subsubsection*{Troncamento e shift dei risultati} -In quasi tutti i casi l'output di \text{gf2x\_scalarprod} viene troncato, eliminando sempre una porzione dei coefficienti più significativi; dato che il +In quasi tutti i casi l'output di \texttt{gf2x\_scalarprod} viene troncato, eliminando sempre una porzione dei coefficienti più significativi che eccedono la dimensione necessaria; dato che il metodo di moltiplicazione parte dai coefficienti meno significativi, possiamo bloccarne l'esecuzione prematuramente appena abbiamo tutti i coefficienti necessari, evitando il calcolo di quelli che sarebbero poi tagliati. Ciò viene banalmente implementato nel generatore utilizzando lo stesso accumulatore -$nr$ citato al punto prima, ma sottraendovi il numero di \texttt{DIGIT} che sarebbero eliminati successivamente. +$nr$ citato al punto prima, ma sottraendovi il numero di \texttt{digit} che sarebbero eliminati successivamente. -A questo punto, possiamo quindi evitare di utilizzare un vettore ausiliario per il calcolo dei prodotti (righe 6-8, 10), ma ne abbiamo ancora bisogno -per il calcolo di ${(f^{\prime}}\div{x^{j}})$ e $({g^{\prime}}\div{x^{j}})$: queste divisioni sono infatti ottenute tramite uno shift a sinistra di $j$ bit; per risolvere +A questo punto, possiamo quindi evitare di utilizzare un vettore ausiliario per il calcolo dei prodotti (\texttt{jumpdivstep}, righe 6-8, 10), ma ne abbiamo ancora bisogno +per il calcolo di $\frac{\bar{f(x)}}{x^{j}}$ e $\frac{\bar{g(x)}}{x^{j}}$: queste divisioni sono infatti ottenute tramite uno shift a sinistra di $j$ bit; per risolvere questo problema, dividiamo lo shift in due parti: \begin{itemize} - \item shift di ($\lfloor{j}\div{\texttt{DIGIT\_SIZE\_b}}$\footnote{Dimensione di un \texttt{DIGIT} in bit}$\rfloor$) \texttt{DIGIT} interi; + \item shift di ($\lfloor\frac{j}{\texttt{DIGIT\_SIZE\_b}}$\footnote{Dimensione di un \texttt{digit} in bit}$\rfloor$) \texttt{digit} interi; \item shift di ($j \mod \texttt{DIGIT\_SIZE\_b}$) bit singoli. \end{itemize} -Lo shift dei \texttt{DIGIT} interi può essere ricondotto al problema del troncamento dei coefficienti più significativi, aggiustando opportunamente gli offset; per quanto riguarda -lo shift dei singoli bit (che saranno per costruzione meno di quelli in un \texttt{DIGIT}), abbiamo bisogno di aggiungere un \texttt{DIGIT} in più per ognuno dei polinomi -$f^{\prime}$ e $g^{\prime}$, in modo da poter shiftare i bit del polinomio desiderato senza andare a sovrascrivere il \texttt{DIGIT} meno significativo del polinomio precedente. +Lo shift dei \texttt{digit} interi può essere ricondotto al problema del troncamento dei coefficienti più significativi, aggiustando opportunamente gli offset; per quanto riguarda +lo shift dei singoli bit (che saranno per costruzione meno di quelli in un \texttt{digit}), abbiamo bisogno di aggiungere un \texttt{digit} in più per ognuno dei polinomi +$\bar{f(x)}$ e $\bar{g(x)}$, in modo da poter shiftare i bit del polinomio desiderato senza andare a sovrascrivere il \texttt{digit} meno significativo del polinomio precedente. diff --git a/docs/report/intro.tex b/docs/report/intro.tex index 9c3a266..520fb9d 100644 --- a/docs/report/intro.tex +++ b/docs/report/intro.tex @@ -4,8 +4,14 @@ \section{Introduzione} e standardizzazione di uno o più algoritmi di crittografia asimmetrici resistenti ad attacchi di computer quantistici.\footnote{\href{https://csrc.nist.gov/projects/post-quantum-cryptography}{https://csrc.nist.gov/projects/post-quantum-cryptography}}; tra i candidati troviamo LEDAcrypt\cite{baldi2019ledacrypt, ledaKEM}, basato sul crittosistema McEliece.\\ -I crittosistemi basati sulla teoria dei codici hanno lo svantaggio di usare chiavi pubbliche piuttosto larghe; un modo per ridurre le dimensioni +I crittosistemi basati sulla teoria dei codici, come appunto LEDAcrypt, hanno lo svantaggio di usare chiavi pubbliche piuttosto larghe; un modo per ridurre le dimensioni di queste chiavi è utilizzare famiglie di codici che consentono di essere rappresentati in modo più efficiente per quanto riguarda lo spazio occupato, come ad esempio i codici QC-MDPC (Quasi-cyclic moderate-density parity-check): questi codici sono composti da matrici a blocchi quadrate circolanti, -dove ogni riga è ottenuta dallo shift circolare della precedente. L'aritmetica di queste matrici di dimensioni $p \times p$ è isomorfa a quella dei polinomi modulo -$x^p-1$, per cui possiamo sfruttare questa proprietà per ridurre il tempo di esecuzione del calcolo dell'inverso. +dove ogni riga è ottenuta dallo shift circolare della precedente. L'aritmetica di queste matrici di dimensioni $p \times p$ è isomorfa a quella dei polinomi +a coefficienti binari modulo $x^p-1$, per cui possiamo sfruttare questa proprietà per ridurre il tempo di esecuzione del calcolo dell'inverso. +\paragraph*{Organizzazione.} +Nella sezione~\ref{analisi} analizziamo in breve l'algoritmo di inversione e descriviamo come questo è stato \textit{simulato}. Nella sezione +\ref{impl} descriviamo come i polinomi sono memorizzati e come le relative operazioni aritmetiche sono implementate; passiamo quindi a descrivere +le principali criticità dell'implementazione proposta in~\cite{benchmark} e le relative ottimizzazioni sviluppate. Infine, nella sezione~\ref{risultati} +andiamo a comparare i risultati dei benchmark della nuova implementazione con gli algoritmi proposti in~\cite{barenghi2020comprehensive}, +con particolare attenzione ai tempi d'esecuzione e all'indipendenza di questi dagli input. diff --git a/docs/report/main.pdf b/docs/report/main.pdf index 3983393..549411d 100644 Binary files a/docs/report/main.pdf and b/docs/report/main.pdf differ diff --git a/docs/report/main.tex b/docs/report/main.tex index b7dc269..30affd6 100644 --- a/docs/report/main.tex +++ b/docs/report/main.tex @@ -60,6 +60,15 @@ \usepackage{graphicx} +\usepackage{mathtools} + +\usepackage{booktabs} + +\usepackage{pgfplots} + +\DeclarePairedDelimiter\ceil{\lceil}{\rceil} +\DeclarePairedDelimiter\floor{\lfloor}{\rfloor} + \usepackage[ruled,vlined,linesnumbered]{algorithm2e} %---------------------------------------------------------------------------------------- % TITLE SECTION @@ -69,6 +78,7 @@ \bibliographystyle{ieeetr} + \pretitle{\begin{center}\Huge\bfseries} % Article title formatting \posttitle{\end{center}} % Article title closing formatting \title{Progetto di Ingegneria Informatica \\ Post-Quantum Cryptography} % Article title @@ -79,9 +89,11 @@ \date{} % Leave empty to omit a date \renewcommand{\maketitlehookd}{% \begin{abstract} -In questa relazione analizziamo l'implementazione dell'algoritmo di inversione polinomiale presentato da Bernstein e Yang~\cite{bernstein2019fast}, analizzandone le -caratteristiche e comparando le misurazioni dei tempi di esecuzione tramite un apposito framework~\cite{benchmark, barenghi2020comprehensive}. Da qui, provvederemo -a creare un generatore di codice sorgente per ottimizzare l'implementazione delle operazioni più frequenti nell'algoritmo e ridurne il tempo di esecuzione. +In questa relazione analizziamo l'algoritmo di inversione polinomiale proposto da D.J. Bernstein e B.Y. Yang, focalizzandoci in particolare su una sua implementazione +per polinomi binari intesa per l'utilizzo all'interno di un crittosistema resistente ad attacchi di computer quantistici; passiamo quindi ad analizzare +le criticità dell'implementazione, fornendo alcuni metodi per migliorare questi aspetti. Infine, valutiamo le performance e le proprietà dell'algoritmo comparandole +con altri algoritmi per il medesimo scopo. + \end{abstract} } diff --git a/docs/report/risultati.tex b/docs/report/risultati.tex index 79489b6..bca4d58 100644 --- a/docs/report/risultati.tex +++ b/docs/report/risultati.tex @@ -1,4 +1,4 @@ -\section{Risultati} +\section{Risultati}\label{risultati} Il framework~\cite{benchmark}, oltre a contenere l'implementazione di alcuni algoritmi di inversione polinomiale (tra cui la versione di partenza dell'algoritmo di Bernstein-Yang), fornisce dei tool per testare la performance dei vari algoritmi per poi compararli; sono stati effettuati diversi test durante lo sviluppo, ma per brevità riportiamo solo @@ -15,15 +15,10 @@ \section{Risultati} bloccando la frequenza a 1.9GHz per ottenere risultati consistenti); l'implementazione è stata compilata con GCC 10.2.0, abilitando la generazione di codice specifico per l'architettura utilizzata (\texttt{-march=native}) e abilitando il livello massimo di ottimizzazione (\texttt{-O3}). +\input{images/mean.tex} +\input{images/tstat.tex} +\input{images/memory.tex} -\begin{figure} - \includegraphics[width=\linewidth]{images/mean.png} - \caption{Tempi di esecuzione} -\end{figure} -\begin{figure} - \includegraphics[width=\linewidth]{images/tstat.png} - \caption{Valori della t statistica} -\end{figure} Analizzando i risultati, notiamo che la \textit{nuova} versione dell'algoritmo di Bernstein-Yang ha un miglioramento