diff --git a/content/al/0004-espacos-vetoriais.md b/content/al/0004-espacos-vetoriais.md new file mode 100644 index 000000000..37bcf079a --- /dev/null +++ b/content/al/0004-espacos-vetoriais.md @@ -0,0 +1,352 @@ +--- +title: Espaços Vetoriais +description: >- + Espaço Vetorial - definição, exemplos. + Subespaços Vetoriais. + Interseção, Soma e União de subespaços vetoriais. + Combinação Linear. + Expansão Linear. + Conjuntos Geradores. + (In)dependência Linear. +path: /al/espacos-vetoriais +type: content +--- + +# Espaços Vetoriais + +```toc + +``` + +:::info[Espaço Vetorial] + +Dizemos que um conjunto não vazio $V$ é um [**espaço vetorial**](color:orange) (ou [**linear**](color:orange)) +sobre um conjunto $\mathbb{K}$ (com $\mathbb{K} \in \{ \mathbb{R}, \mathbb{C}, \cdots \}$) se e apenas se +lhe estiverem associadas duas principais operações (sendo que cada uma verifica um dado conjunto +de propriedades): + +- [**Adição**](color:green): $x, y \in V \implies x + y \in V$; note-se que esta + operação deve ser **comutativa** e **associativa**; deve ainda existir um único + elemento neutro, $0 \in V$, tal que $x + \overset{\rightarrow}{0} = x$ e ainda + um único elemento simétrico, $-x \in V$, tal que $x + (-x) = \overset{\rightarrow}{0}$; +- [**Multiplicação por escalar**](color:green): $x \in V, \alpha \in \mathbb{K} \implies \alpha x \in V$; + esta operação deve ser **associativa** e **distributiva**, devendo ainda existir um elemento + neutro (a **identidade**), tal que $1 \cdot x = x$. + +Extrai-se ainda, para a multiplicação por escalar, que $\forall x \in V, 0 \cdot x = \overset{\rightarrow}{0} \wedge -x = -1x$. + +::: + +A título de exemplo, tem-se que qualquer conjunto $\mathbb{R}^n$ é um espaço vetorial sobre $\mathbb{R}$, +já que, considerando $x = (x_1, x_2, \cdots, x_n)$ e $y = (y_1, y_2, \cdots, y_n)$: + +- $x + y = (x_1 + y_1, x_2 + y_2, \cdots, x_n + y_n)$; +- $\alpha x = (\alpha x_1, \alpha x_2, \cdots, \alpha x_n)$. + +Note-se, claro, que para $\mathbb{R}^n$ todas as outras propriedades supra-referidas são também satisfeitas. + +São exemplos, ainda, espaços como $\mathbb{P}_n$, o **conjunto de polinómios de grau $\leq n$**, +$\mathbb{F}$, o conjunto das funções reais de variável real $f: \mathbb{R} \rightarrow \mathbb{R}$, +entre muitos outros. + +## Subespaços Vetoriais + +Tendo abordado acima o conceito de espaço vetorial, podemos agora definir o de [**subespaço vetorial**](color:orange): +tendo $V$ um espaço vetorial sobre $\mathbb{K}$, dizemos que um subconjunto $W \subseteq V$ é um +[subespaço vetorial](color:orange) de $V$ se e apenas se $W$ satisfaz as mesmas propriedades +de $V$ - verificando todos os axiomas e propriedades que $V$ verifica, podemos então +dizer que $W$ é também um espaço vetorial sobre $\mathbb{K}$. + +Podemos, por exemplo, procurar mostrar que $S = \{x_1, x_2 \in \mathbb{R}^2: x_1 + x_2 = 0\}$, +o conjunto de todos os pares de reais que somados dão zero (i.e simétricos), é um subespaço de +$\mathbb{R}^2$: para tal, basta verificar que $S$ satisfaz todas as propriedades de um espaço vetorial: + +- $\overset{\rightarrow}{0} \in S$, já que $0 + 0 = 0$; +- a adição está definida para este conjunto: considerando $x = (x_1, x_2)$ e $y = (y_1, y_2)$, + $x, y \in S: x + y = (x_1 + y_1) + (x_2 + y_2) = 0 + 0 = 0$, pelo que $x + y = (x_1 + y_1, x_2 + y_2) \in S$; +- por fim, a multiplicação por escalar está também definida para $S$: considerando $x = (x_1, x_2)$, + $x \in S$ e $\alpha \in \mathbb{R}$, $\alpha x_1 + \alpha x_2 = \alpha (x_1 + x_2) = \alpha 0 = 0$, + pelo que $\alpha x = (\alpha x_1, \alpha x_2) \in S$. + +Note-se que subespaços de $\mathbb{R}^2$ são o vetor nulo, retas que passem pela origem, +e o próprio $\mathbb{R}^2$, claro. + +É igualmente possível provar, através de um contra-exemplo ou por contradição, +que um conjunto $W \subseteq V$ não é um subespaço vetorial de $V$. Tomemos como +exemplo o conjunto $W = \{x_1, x_2 \in \mathbb{R}^2: x_1 x_2 = 0\}$, o conjunto de todos os pares +de reais que multiplicados dão zero (i.e. ortogonais). Não podemos afirmar que $W$ é um subespaço +vetorial de $\mathbb{R}^2$, pois, por exemplo, $x = (1, 0)$ e $y = (0, 1)$ são elementos de $W$, +mas $x + y = (1, 1) \notin W$. + +## Interseção, Soma e União de Subespaços Vetoriais + +Dado um conjunto de espaços vetoriais $\{V_1, V_2, \cdots, V_n\}$, todos eles subespaços +de um espaço vetorial $V$, podemos definir a [**interseção**](color:orange) +entre estes espaços vetoriais como sendo o conjunto $\bigcap_{i=1}^n V_i$, o conjunto de todos os elementos +comuns a todos os espaços vetoriais do conjunto. Para o provar, consideremos, por exemplo, os conjuntos +arbitrários $S_1, S_2$, tal que ambos são subespaços de um espaço $S$. Como já vimos +anteriormente, o nosso conjunto $S_1 \cap S_2$ terá, por forma a ser um subespaço de $S$, +de satisfazer três principais propriedades: + +- $\overset{\rightarrow}{0} \in S_1 \cap S_2$, já que $\overset{\rightarrow}{0} \in S_1$ e $\overset{\rightarrow}{0} \in S_2$ + obrigatoriamente, sendo ambos subespaços de $S$; +- a adição está definida para este conjunto: considerando $x = (x_1, x_2)$ e $y = (y_1, y_2)$, + $x, y \in S_1 \cap S_2: x, y \in S_1 \wedge x, y \in S_2 \Rightarrow x + y \in S_1 \wedge x + y \in S_2 \Rightarrow x + y \in S_1 \cap S_2$; +- por fim, a multiplicação por escalar está também definida para $S_1 \cap S_2$: considerando $x = (x_1, x_2)$, + $x \in S_1 \cap S_2$ e $\alpha \in \mathbb{K}$, $x \in S_1 \wedge x \in S_2 \Rightarrow \alpha x \in S_1 \wedge \alpha x \in S_2 \Rightarrow \alpha x \in S_1 \cap S_2$. + +Se é verdade que podemos afirmar que a interseção de dois espaços vetoriais é também +um subespaço vetorial, não é igualmente verdade que o possamos afirmar para a +[**união**](color:orange) de dois espaços vetoriais: basta pensar, por exemplo, +num cenário com dois subespaços vetoriais, $S_1$ e $S_2$, tal que +$S_1$ corresponde ao conjunto de todos os pontos no eixo das abscissas e +$S_2$ corresponde ao conjunto de todos os pontos no eixo das ordenadas. +$(3, 0) \in S_1$ e $(0, 3) \in S_2$, mas $(3, 3) \notin S_1 \cup S_2$, +pois $(3, 3)$ não pertence a nenhum dos dois subespaços vetoriais. Assim sendo, +a soma não se diz **fechada** para esta operação, pelo que a união de subespaços não é, +de forma generalizada, um subespaço vetorial. + +Note-se, contudo, que a [**soma**](color:orange) de dois espaços vetoriais é +também um subespaço vetorial! A prova é relativamente simples: consideremos +os espaços vetoriais $S_1$ e $S_2$, tal que ambos são subespaços de um espaço $S$. +Como já vimos anteriormente, o nosso conjunto $S_1 + S_2$ terá, por forma a ser um subespaço de $S$, +de satisfazer três principais propriedades: + +- $\overset{\rightarrow}{0} \in S_1 + S_2$, já que $\overset{\rightarrow}{0} \in S_1$ e $\overset{\rightarrow}{0} \in S_2$ + obrigatoriamente, sendo ambos subespaços de $S$; +- a adição está definida para este conjunto: considerando $x = (x_1, x_2)$ e $y = (y_1, y_2)$, + $x, y \in S_1 + S_2: x \in S_1 \wedge y \in S_2 \Rightarrow x + y \in S_1 \wedge x + y \in S_2 \Rightarrow x + y \in S_1 + S_2$; +- por fim, a multiplicação por escalar está definida para $S_1 + S_2$: considerando $x = (x_1, x_2)$, + $x \in S_1 + S_2$ e $\alpha \in \mathbb{K}$, $x \in S_1 \wedge x \in S_2 \Rightarrow \alpha x \in S_1 \wedge \alpha x \in S_2 \Rightarrow \alpha x \in S_1 + S_2$. + +## Expansão Linear e Conjunto Gerador + +Dado um conjunto de vetores $\{v_1, v_2, \cdots, v_n\}$, elementos de um espaço vetorial $V$ sobre $\mathbb{K}$, +podemos dizer que $w \in V$ se pode escrever como uma [**combinação linear**](color:green) desses vetores +se e só se existir um conjunto de coeficientes $\{c_1, c_2, \cdots, c_n\}$, todos eles +elementos de $\mathbb{K}$, tal que: + +$$ +w = c_1 v_1 + c_2 v_2 + \cdots + c_n v_n +$$ + +Mais ainda, dizemos que o subconjunto de $V$ formado pelos vetores $w$ que podem ser escritos +como uma combinação linear dos vetores $\{v_1, v_2, \cdots, v_n\}$ corresponde à +[**expansão linear**](color:yellow), vulgo [_span_](color:yellow), de $V$ em relação +aos vetores $\{v_1, v_2, \cdots, v_n\}$: + +$$ +L\{v_1, v_2, \cdots, v_n\} = \{w \in V: w = c_1 v_1 + c_2 v_2 + \cdots + c_n v_n, \forall c_1, c_2, \cdots, c_n \in \mathbb{K}\} +$$ + +Um conjunto de vetores $\{v_1, v_2, \cdots, v_n\}$ diz-se [**gerador**](color:orange) +de $V$ se e só se $V = L\{v_1, v_2, \cdots, v_n\}$. + +A título de exemplo temos, claro, que os vetores $\{(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)\}$ +são geradores do espaço vetorial $\mathbb{R}^4$: podemos escrever qualquer vetor +$(x, y, z, w) \in \mathbb{R}^4$ como uma combinação linear dos vetores em questão, através +de um simples produto escalar; $(3, 1, 8, 2)$, por exemplo, pode ser escrito através +da combinação linear: + +$$ +(3, 1, 8, 2) = 3 \cdot (1, 0, 0, 0) + 1 \cdot (0, 1, 0, 0) + 8 \cdot (0, 0, 1, 0) + 2 \cdot (0, 0, 0, 1) +$$ + +:::details[Exemplo] + +Nem sempre é tão fácil determinar se um conjunto de vetores é gerador de um espaço vetorial +como foi acima. Assim sendo, fará sentido considerar casos mais peculiares; +consideremos os seguintes vetores de $\mathbb{R}^3$: + +$$ +v_1 = (1, 2, 1), \quad v_2 = (0, 0, 1), \quad v_3 = (2, 4, 5), \quad v_4 = (3, 6, 0) +$$ + +Procuremos, primeiro, determinar a forma geral da expansão linear de $\{v_1, v_2, v_3, v_4\}$, +e de seguida aferir se os vetores em questão são geradores de $\mathbb{R}^3$. + +Ora, como sabemos, um vetor de $\mathbb{R}^3$ pertence à expansão linear de $\{v_1, v_2, v_3, v_4\}$ +se e só se pode ser escrito como uma combinação linear dos vetores em questão - i.e, +se e só se pode ser escrito como: + +$$ +(y_1, y_2, y_3, y_4) = c_1 \cdot (1, 2, 1) + c_2 \cdot (0, 0, 1) + c_3 \cdot (2, 4, 5) + c_4 \cdot (3, 6, 0) +$$ + +Ora, isto é equivalente a dizer que tal só acontece caso o vetor $(y_1, y_2, y_3, y_4)$ +seja solução do seguinte sistema de equações lineares: + +$$ +\begin{bmatrix} +1 & 0 & 2 & 3 \\ +2 & 0 & 4 & 6 \\ +1 & 1 & 5 & 0 +\end{bmatrix} \begin{bmatrix} c_1 \\ c_2 \\ c_3 \\ c_4 \end{bmatrix} += \begin{bmatrix} y_1 \\ y_2 \\ y_3 \end{bmatrix} +$$ + +Por eliminação de Gauss, teríamos o seguinte: + +$$ +\left[\begin{array}{cccc|c} +1 & 0 & 2 & 3 & y_1 \\ +2 & 0 & 4 & 6 & y_2 \\ +1 & 1 & 5 & 0 & y_3 +\end{array}\right] \overset{\cdots}{\rightarrow} +\left[\begin{array}{cccc|c} +1 & 0 & 2 & 3 & y_1 \\ +0 & 1 & 3 & -3 & y_3 - y_1 \\ +0 & 0 & 0 & 0 & y_2 - 2y_1 +\end{array}\right] +$$ + +Assim sendo, teríamos que $L\{v_1, v_2, v_3, v_4\} = \{(y_1, y_2, y_3) \in \mathbb{R}^3: y_2 = 2y_1\}$. +Note-se, claro, que esta expansão linear não é geradora de $\mathbb{R}^3$, precisamente +porque existem vetores em $\mathbb{R}^3$ que não pertencem a $L\{v_1, v_2, v_3, v_4\}$ +(tal como $(1, 1, 1)$). + +::: + +Neste último exemplo, podíamos ter afirmado que os vetores $\{v_1, v_2, v_3, v_4\}$ +não são geradores de $\mathbb{R}^3$ sem sequer ter de calcular a expansão linear +de $\{v_1, v_2, v_3, v_4\}$; basta, para tal, verificar se o sistema de equações +lineares que define a expansão linear de $\{v_1, v_2, v_3, v_4\}$ tem alguma +linha nula (ou seja, se após transformar o SEL em escada de linhas existe +alguma linha sem pivô) - caso tenha, podemos afirmar que não é gerador. +Por consequência, todo o conjunto gerador de $\mathbb{R}^n$ terá obrigatoriamente +dimensão $\geq n$. + +## Dependência e Independência Linear + +A noção de [**dependência linear**](color:green) está intimamente ligada à de +combinação linear; um conjunto de vetores $\{v_1, v_2, \cdots, v_n\}$ diz-se +[**linearmente dependente**](color:green) caso exista pelo menos um vetor $v_i \in \{v_1, v_2, \cdots, v_n\}$ +tal que a combinação linear dos restantes vetores seja igual a $v_i$. Caso contrário, +o conjunto de vetores é dito [**linearmente independente**](color:green). + +Isto é equivalente, claro, a dizer que para ocorrer dependência linear entre um +conjunto de vetores terá de existir um conjunto de escalares $\{c_1, c_2, \cdots, c_n\}$, +não todos nulos, tal que $\sum_{j=1}^n c_j v_j = \overrightarrow{0}$. + +:::details[Prova] + +A prova é relativamente simples: considerando um conjunto de vetores $\{v_1, v_2, \cdots, v_n\}$ +linearmente dependente, podemos escrever, para pelo menos um vetor $v_i \in \{v_1, v_2, \cdots, v_n\}$: + +$$ +\sum_{j=1, j \neq i}^n c_j v_j = v_i +$$ + +Isto significa, claro, que $c_1 v_1 + \cdots + (-1) v_i + \cdots + c_n v_n = 0$, +pelo que garantidamente teremos escalares $c_1, \cdots, c_n$ não todos nulos (já que $c_i = -1$) +tal que: + +$$ +\sum_{i=1}^n c_i v_i = \overrightarrow{0} +$$ + +Mais ainda, isto corresponderá precisamente a: + +$$ +v_i = \left(-\frac{c_1}{c_i}\right) v_1 + \cdots + \left(-\frac{c_n}{c_i}\right) v_n +$$ + +Ou seja, o vetor $v_i$ é uma combinação linear dos restantes vetores, pelo que +o conjunto de vetores é linearmente dependente. + +::: + +Note-se, claro, que qualquer conjunto de vetores $\{v_1, v_2, \cdots, v_n\}$ +que contenha pelo menos um vetor nulo é linearmente dependente: basta, para tal, +notar que o coeficiente associado ao vetor nulo pode ser qualquer número, e que +mantendo todos os outros coeficientes iguais a zero, $\sum_{i=1}^n c_i v_i = \overrightarrow{0}$ obrigatoriamente. + +Mais ainda, podemos rapidamente notar que a noção de [**colinearidade**](color:yellow) de vetores +é aqui bastante relevante: se $\{v_1, v_2, \cdots, v_n\}$ é um conjunto de vetores +onde pelo menos dois vetores, $v_i$ e $v_j$, são colineares, então $\{v_1, v_2, \cdots, v_n\}$ +é linearmente dependente. Isto porque, se $v_i$ e $v_j$ são colineares, então +podemos escrever $v_i = \alpha v_j$ para algum $\alpha \neq 0$. Assim sendo, temos o seguinte: + +$$ +0v_1 + \cdots + v_i + \cdots + (-\alpha) v_j + \cdots + 0v_n = \overrightarrow{0} +$$ + +Quando não estamos perante um conjunto de vetores onde pelo menos dois vetores +são colineares/não estamos na presença do vetor nulo, podemos ainda assim verificar +se este é linearmente dependente; para tal, recorreremos, mais uma vez, +à representação matricial de um sistema de equações lineares. + +:::details[Exemplo] + +Consideremos o seguinte conjunto de vetores: + +$$ +v_1 = (4, 3), \quad v_2 = (2, 1) +$$ + +Caso este conjunto seja linearmente independente, podemos escrever o seguinte: + +$$ +c_1 v_1 + c_2 v_2 = \overrightarrow{0} \leftrightarrow +c_1 \begin{bmatrix} 4 \\ 3 \end{bmatrix} + c_2 \begin{bmatrix} 2 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} +$$ + +Como sabemos, isto é equivalente à seguinte representação matricial: + +$$ +\begin{bmatrix} 4 & 2 \\ 3 & 1 \end{bmatrix} \begin{bmatrix} c_1 \\ c_2 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} +$$ + +Podemos utilizar eliminação de Gauss para colocar a matriz em escada de linhas, +obtendo: + +$$ +\begin{bmatrix} 4 & 2 \\ 0 & \frac{-1}{2} \end{bmatrix} +$$ + +Visto que todas as colunas do sistema possuem pivô, o sistema é consistente e +tem solução única, pelo que o conjunto de vetores é linearmente independente. +Note-se que, estando na presença de uma matriz quadrada, podíamos ter verificado +se o sistema é consistente e tem solução única através da determinante da matriz - caso seja não nulo, +o sistema é consistente e tem solução única (e estaríamos na presença de um +conjunto linearmente independente). + +::: + +Generalizando o observado no exemplo anterior, podemos verificar o seguinte: + +:::info[Teorema] + +Tendo $n$ vetores $\{v_1, v_2, \cdots, v_n\}$ em $\mathbb{R}^m$, o conjunto diz-se +linearmente independente se e só se a matriz abaixo puder ser transformada +numa matriz em escada de linhas, com um pivô por coluna, utilizando apenas operações elementares de linha: + +$$ +\begin{bmatrix} v_1 & v_2 & \cdots & v_n \end{bmatrix} = +\begin{bmatrix} + v_{11} & v_{12} & \cdots & v_{1n} \\ + v_{21} & v_{22} & \cdots & v_{2n} \\ + \vdots & \vdots & \ddots & \vdots \\ + v_{m1} & v_{m2} & \cdots & v_{mn} +\end{bmatrix} +$$ + +Caso $m=n$, a matriz é dita quadrada, e podemos verificar a (in)dependência linear +através da nulidade do determinante da mesma. + +Como consequência do supra-definido, temos o seguinte: + +- Todo o subconjunto gerador de $\mathbb{R}^m$ tem pelo menos $m$ vetores; +- Todo o subconjunto de vetores de $\mathbb{R}^m$ com dimensão superior a $m$ é linearmente dependente (terá + mais linhas que colunas, pelo que pelo menos uma coluna terá um pivô nulo); +- Todo o subconjunto de $\mathbb{R}^m$ com dimensão $m$ diz-se gerador de $\mathbb{R}^m$ + se e só se for linearmente independente. +- Todo o subconjunto de dimensão $m$ gerador de $\mathbb{R}^m$ é linearmente independente. + +::: + +Note-se, por fim, que dizemos que um conjunto gerador de $\mathbb{R}^m$ linearmente independente +diz-se uma [**base**](color:orange) de $\mathbb{R}^m$. Correspondendo a uma matriz quadrada, +e tendo em conta o que já referimos sobre a nulidade do seu determinante anteriormente, +podemos afirmar que um conjunto de vetores é uma base de $\mathbb{R}^m$ se e só se +a matriz correspondente for invertível! diff --git a/content/al/0005-bases.md b/content/al/0005-bases.md new file mode 100644 index 000000000..5927dda9b --- /dev/null +++ b/content/al/0005-bases.md @@ -0,0 +1,62 @@ +--- +title: Bases de um Espaço Vetorial +description: >- + Base de um espaço vetorial. + Coordenadas de um vetor numa base. + Dimensão de um espaço vetorial. + Matriz de Mudança de Base. +path: /al/bases +type: content +--- + +# Bases de um Espaço Vetorial + +```toc + +``` + +Podemos generalizar o referido no final da última página para espaços vetoriais, definindo o seguinte: + +:::info[Definição] + +Considerando um espaço vetorial $V$ sobre $\mathbb{K}$, um conjunto $\mathcal{B} = \{v_1, v_2, \cdots, v_n\} \subset V$ +diz-se uma [**base**](color:orange) de $V$ se e só se $\mathcal{B}$ é linearmente independente e +gerador de $V$: $L(\mathcal{B}) = V$, portanto. + +Os conjuntos geradores de espaços como $\mathbb{R}^m$ e $\mathbb{M}_{m \times n}(\mathbb{R})$ +são, claro, as respetivas [**bases canónicas**](color:blue): no caso de $\mathbb{R}^m$, por +exemplo, temos $\mathcal{B} = \{e_1, e_2, \cdots, e_m\}$, onde $e_i$ é o vetor unitário +na direção $i$. + +::: + +## Coordenadas de um Vetor numa Base + +Considerando um espaço vetorial $V$ sobre $\mathbb{K}$ e um conjunto $\mathcal{B} = \{v_1, v_2, \cdots, v_n\} \subset V$ +tal que $L(\mathcal{B}) = V$, existirá um conjunto de escalares $\{c_1, c_2, \cdots, c_n\} \subset \mathbb{K}$ +onde, $\forall u \in V$, existe necessariamente um vetor $v' \in \mathbb{K}^n$ (**único**) em que: + +$$ +v' = (c_1, c_2, \cdots, c_n), \quad u = c_1 v_1 + c_2 v_2 + \cdots + c_n v_n = \sum_{i=1}^n v'_i v_i +$$ + +No fundo, significa que podemos representar qualquer vetor $u \in V$ como uma combinação linear +de vetores da base $\mathcal{B}$ - fisicamente, estamos a transformar a representação de um vetor +em coordenadas cartesianas para outro sistema de coordenadas, neste caso, o sistema de coordenadas +definido pelos vetores da base $\mathcal{B}$. + +Dizemos que estes escalares, correspondentes a $v'$, correspondem às [**coordenadas**](color:blue) de $u$ na base $\mathcal{B}$, +representando a posição de $u$ no espaço vetorial $V$. Podemos representar esta informação +da seguinte forma: + +$$ +(u)_{\mathcal{B}} = (c_1, c_2, \cdots, c_n) \in \mathbb{K}^n +$$ + +Note-se que a correspondência $u \mapsto (u)_{\mathcal{B}}$, $V \mapsto \mathbb{K}^n$, +é uma transformação que preserva a adição e a multiplicação por escalares: + +$$ +(u + v)_{\mathcal{B}} = (u)_{\mathcal{B}} + (v)_{\mathcal{B}} \quad \forall u, v \in V \\ +(\lambda u)_{\mathcal{B}} = \lambda (u)_{\mathcal{B}} \quad \forall u \in V, \lambda \in \mathbb{K} +$$ diff --git a/content/es/0002-unit-tests.md b/content/es/0002-unit-tests.md new file mode 100644 index 000000000..e7c43898a --- /dev/null +++ b/content/es/0002-unit-tests.md @@ -0,0 +1,136 @@ +--- +title: Testes e Testes de Unidade +description: >- + Testes. + Testes de Unidade (Unit Tests). + + White Box e Black Box testing strategies. + Partition testing. + Test doubles. +path: /es/unit-tests +type: content +--- + +# Testes e Testes de Unidade + +```toc + +``` + +Os testes automáticos permitem-nos ter confiança de que o nosso código funciona +e que não sofreu regressões (i.e. algo que funcionava deixou de funcionar) devido +a alterações não relacionadas. +No entanto, é importante ter em conta que ter todos os testes a passar +**não significa que o programa está livre de _bugs_**. + +## Fases de Testagem + +Existem 3 grandes fases onde os sistemas são testados: + +- [**_Development Testing_**](color:green): o sistema é testado pelos **_developers_** + durante o desenvolvimento. Pode tomar a forma de _unit testing_, _component testing_ + ou _system testing_. +- [**_Release testing_**](color:yellow): antes de uma nova versão do sistema ser + lançada e disponibilizada aos utilizadores, os **_QA Engineers_**, uma equipa + separada da equipa de desenvolvimento, testam todo o sistema. +- [**_User testing_**](color:red): os **utilizadores** do sistema testam o sistema, + por exemplo, através de uma versão _beta_ ou _alpha_ lançada antes da versão final. + +## Estratégias de Testagem + +- [**_Black box testing_**](color:pink): os testes são feitos a partir de uma **especificação**, + isto é, a descrição que levou à implementação. +- [**_White box testing_**](color:blue): os testes são feitos contra uma **implementação** específica. + +:::info[Exemplo] + +Imaginemos que temos uma estrutura do tipo FIFO implementada e queremos +testar o método `fifo.push()`. + +No caso de não conhecermos a implementação (caso [_black box_](color:pink)), o óbvio +seria testar o caso em que a fifo está vazia, e o caso em que não está. + +No entanto, se soubermos que a estrutura utiliza arrays de 512 elementos na +sua implementação, podemos (e devemos) também testar o caso em que é adicionado +um elemento a uma FIFO com 512 elementos (caso [_white box_](color:blue)). + +::: + +## Testagem de Partições + +Quando estamos a testar um sistema, existem vários inputs (e os respetivos outputs) +que se comportam de forma semelhante. +Podemos, então, agrupar estes inputs quando escrevemos testes, numa técnica chamada +**Testagem de Partições** (ou, em inglês, [_equivalence partitioning testing_](https://en.wikipedia.org/wiki/Equivalence_partitioning)). + +:::tip[Partition Testing] + +Consiste em encontrar grupos de inputs (que não se intercetam) que se espera +que tenham um mesmo comportamento. +De seguida, cria-se testes para cada um destes grupos. + +::: + +Uma técnica usada em conjunto com a testagem de partições é a +análise de valores fronteira ([_boundary-value analysis_](https://en.wikipedia.org/wiki/Boundary-value_analysis)), +isto é, os valores que delimitam as várias partições. + +:::info[Exemplo] + +Vamos imaginar uma função `passOrFail(int grade)` que retorna `"pass"` se a nota +for entre 10 e 20 (inclusive), `"fail"` se a nota for entre 0 e 9 (inclusive) e +lança uma exceção para qualquer outro valor. + +Seguindo a testagem de partições, vamos dividir o nosso espaço em 4 diferentes partições. + +``` +... -1 | 0 ... 9 | 10 ... 20 | 21 ... +------------------------------------------- +exception | fail | pass | exception +``` + +Considerando apenas a testagem de partições, temos de testar um valor +de cada uma das partições, por exemplo, -2, 4, 15 e 22. + +No entanto, geralmente queremos também efetuar _boundary-value analysis_, pelo que +queremos incluir nos nossos testes os valores fronteira, -1, 0, 9, 10, 20 e 21. + +Assim, se seguirmos ambos os métodos, os nossos testes deverão abranger 10 valores +diferentes e 4 partições. + +::: + +## Testes Unitários + +Os Testes Unitários (_Unit Tests_) servem para testar os vários componentes +individualmente, isolados do resto do sistema. + +As várias **unidades** podem ser: + +- Funções ou métodos de um objeto +- Classes de objetos com vários atributos e métodos +- Componentes compostos (_composite components_) com interfaces bem definidas + que permitem aceder à sua funcionalidade. + +Para termos _coverage_ total de uma classe, temos de: + +- Testar todas as operações associadas a um objeto; +- Fazer _set_ e _get_ de todos os atributos do objeto; +- Utilizar o objeto em todos os seus estados possíveis. + +## Test Doubles + +Os _test doubles_ são objetos falsos que são usados no lugar de objetos verdadeiros +em testes. +Estes podem ser: + + + +- Dummy objects +- Fake objects +- Stubs +- Spies +- Mocks + +Estes têm a vantagem de isolar os testes a uma única unidade, de diminuir +as dependências ao efetuar testes e também simular casos difíceis de gerar. diff --git a/content/es/0003-code-coverage.md b/content/es/0003-code-coverage.md new file mode 100644 index 000000000..28f4fe786 --- /dev/null +++ b/content/es/0003-code-coverage.md @@ -0,0 +1,50 @@ +--- +title: Code Coverage +description: >- + Code Coverage: statement, branch, condition e path coverage. +path: /es/code-coverage +type: content +--- + +# Code Coverage + +```toc + +``` + +Em _white-box testing_, podemos definir uma métrica que nos indica a percentagem +do nosso código que é testado, chamada de _code coverage_. + +No entanto, existem diversos critérios que podemos aplicar, cada um com as suas +vantagens e desvantagens: + +- [**_Statement Coverage_**](color:green) +- [**_Branch Coverage_**](color:orange) +- [**_Condition Coverage_**](color:yellow) +- [**_Path Coverage_**](color:blue) + +## Statement Coverage + +:::warning[Secção Incompleta] +Esta secção encontra-se incompleta. Procuram-se contribuidores. +::: + +## Branch Coverage + +:::warning[Secção Incompleta] +Esta secção encontra-se incompleta. Procuram-se contribuidores. +::: + +## Condition Coverage + +:::warning[Secção Incompleta] +Esta secção encontra-se incompleta. Procuram-se contribuidores. +::: + +## Path Coverage + +:::warning[Secção Incompleta] +Esta secção encontra-se incompleta. Procuram-se contribuidores. +::: + + diff --git a/content/oc/0004-memoria-caches.md b/content/oc/0004-memoria-caches.md index 53e477572..e744207f4 100644 --- a/content/oc/0004-memoria-caches.md +++ b/content/oc/0004-memoria-caches.md @@ -89,10 +89,10 @@ pequena de espaço de memória a qualquer momento durante a execução. | mais caro | mais barato | | estático, o conteúdo fica para "sempre" enquanto estiver ligado | dinâmico, precisa de ser "refrescado" regularmente (a cada 8 ms); consome 1% a 2% dos ciclos ativos da DRAM | -Para além disso, os endereços da DRAM são [divídido em 2 metades](color:pink), linha e coluna: +Para além disso, os endereços da DRAM são [dividido em 2 metades](color:pink), linha e coluna: - [RAS (_Row Access Strobe_)](color:orange) que aciona o decodificador de linha; -- [CAS (_Columm Access Strobe_)](color:green) que aciona o selecionador de coluna. +- [CAS (_Column Access Strobe_)](color:green) que aciona o selecionador de coluna. ### Como Funciona a Hierarquia de Memória? @@ -130,7 +130,7 @@ Se tentarmos aceder a dados e estes estiverem disponíveis no nível mais alto d temos um [**_hit_**](color:green), caso contrário teremos um [**_miss_**](color:red) e teremos de ir buscar os dados a um nível inferior. -Podemos ainda calcular o [**_hit rate_**](color:purple) de multiplos acessos através da seguinte fórmula: +Podemos ainda calcular o [**_hit rate_**](color:purple) de múltiplos acessos através da seguinte fórmula: $$ \op{\text{Hit Rate}} @@ -305,6 +305,14 @@ Existem três tipos de [cache misses](color:pink): são mapeados para o mesmo set ou _block frame_, num set de associatividade ou até mesmo em posicionamento de blocos em mapeamento direto. +### Cache Design Trade-offs + +| Alteração | Efeito na _miss rate_ | Efeito negativo de _performance_ | +| :---------------------------------- | :-------------------------------- | :---------------------------------------------------------------------------------------- | +| Aumento do tamanho da cache | Diminuição de _capacity misses_ | Aumento do tempo de acesso | +| Aumento da associatividade da cache | Diminuição de _conflict misses_ | Aumento do tempo de acesso | +| Aumento do _block size_ | Diminuição de _compulsory misses_ | Aumento do _miss penalty_. Para blocos muito grandes, pode aumentar também a _miss rate_. | + ## _Write-Policies_ Uma [_write policy_ da cache](color:pink) refere-se a um comportamento da cache @@ -316,7 +324,7 @@ policies_. ### _Write-through_ Quando nos deparamos com um _data-write hit_ podemos somente atualizar o bloco da -cache, mas isto implicaria que a cache e a memória se tornassem insconsistentes. Temos, +cache, mas isto implicaria que a cache e a memória se tornassem inconsistentes. Temos, por isso, que introduzir a política [_write-through_](color:pink): esta, sendo a mais fácil de implementar, basicamente atualiza os dados tanto em cache como em memória ao mesmo tempo. É usada quando não há escritas muito frequentes na cache e ajuda com a @@ -377,7 +385,7 @@ diferentes: ## Medir a Performance da Cache Para conseguirmos perceber se uma cache está a funcionar bem ou não, temos que saber -os termos involvidos nestes cálculos: +os termos envolvidos nestes cálculos: - [Bloco ou linha](color:yellow): a unidade mínima de informação que está presente, ou não, na cache; @@ -393,7 +401,7 @@ os termos involvidos nestes cálculos: Assim, como já sabíamos, os componentes do tempo do CPU são os [ciclos de execução do programa](color:purple), que includem o tempo de _cache-hit_ e os [ciclos de atraso de memória](color:purple) -que provêm maioritariamente de _cache misses_. Assumindo que o sucesso de cache incui a +que provêm maioritariamente de _cache misses_. Assumindo que o sucesso de cache inclui a parte normal dos ciclos de execução do programa, então podemos calcular o tempo de CPU através da seguinte fórmula: @@ -431,7 +439,7 @@ como um _miss penalty_ de 100 ciclos, uma [base CPI](color:yellow), ou seja, cac ideal, igual a 2, e [loads e stores](color:purple) que ocupam 36% das instruções. A primeira coisa que pretendemos calcular são os _miss cycles_ por instrução, que, como -vimos aicma, são dados pelo _miss rate_ e o _miss penalty_. Temos, por isso: +vimos acima, são dados pelo _miss rate_ e o _miss penalty_. Temos, por isso: $$ \text{miss cycle} = \text{miss rate} \times \text{miss penalty} @@ -456,11 +464,11 @@ Por isso. o CPU ideal é $$5.44/2=2.72$$ vezes mais rápido ### Ideias a Reter -Desta forma, concluimos que quando a performance do CPU aumenta, o _miss penalty_ +Desta forma, concluímos que quando a performance do CPU aumenta, o _miss penalty_ [diminui](color:purple); uma diminuição baseada no CPI implica uma maior [proporção de tempo](color:purple) gasto em atrasos na memória; e, um aumento de _clock rate_ significa que os atrasos de memória contam para mais [ciclos de CPU](color:purple). Não podemos, evidentemente -negligenciar o comportamneto da cache quando estamos a avaliar a perfomance do sistema. +negligenciar o comportamento da cache quando estamos a avaliar a performance do sistema. ## Reduzir os _Miss Rates_ na Cache @@ -472,7 +480,7 @@ um bloco de memória seja mapeado para qualquer bloco de cache numa [cache total Por isso mesmo, o compromisso é dividir a cache em **sets** que contêm _n_ formas ([_n-way set associative_](color:pink)). Os blocos de memória mapeiam um _set_ único, -específicado pelo campo de index, e pode ser posto em qualquer sítio desse _set_, é por +especificado pelo campo de index, e pode ser posto em qualquer sítio desse _set_, é por isso que há _n_ escolhas. | [Totalmente associativo](color:yellow) | [Associatividade com _n_ sets](color:orange) | @@ -494,19 +502,19 @@ encontra presente. Como não se encontra, temos um _miss_ e escrevemos na primei o valor 0. Já tendo o 0 em cache, seguimos para o 4, vamos à primeira linha e vemos se está na cache, contudo na cache só está o 0, logo, há um miss. Como estamos a tratar do número 4, contamos as linhas até chegarmos à linha 4, como só há 4 linhas no total e -começamos a contar do zero, temos que modficar a nossa primeira linha para passar a ter +começamos a contar do zero, temos que modificar a nossa primeira linha para passar a ter a informação relevante ao 0 para ter informação relevante ao 4. Assim, na nossa primeira linha agora temos o 4. Acabando os dois primeiros valores, passamos ao 0, vamos à primeira linha, vemos que já está preenchida, há _miss_ e temos que voltar a preencher com o 0. Reparamos, por isso, que temos o mesmo caso que no início do nosso exercício. Ora, como o resto dos valores -são sempre ou 0 ou 4 intrecalando, vamos sempre ter um _miss_ e vamos sempre ter que +são sempre ou 0 ou 4 intercalando, vamos sempre ter um _miss_ e vamos sempre ter que voltar a preencher a primeira linha com o valor 0 ou 4. ![Exemplo](./assets/0004-exemplo.jpg#dark=3) -Porém, se tivessemos a ver a mesma string mas numa [2 way set associative_cache](color:pink), +Porém, se tivéssemos a ver a mesma string mas numa [2 way set associative_cache](color:pink), só teríamos _miss_ nos primeiros dois acessos, visto que os nossos valores seriam guardados na primeira e segunda via da primeira linha, e a partir daí conseguiríamos aceder aos endereços 0 e 4 com sucesso. @@ -530,7 +538,7 @@ dar acesso a novos? Em [mapeamento direto](color:purple) não temos escolha, con [set de associatividade](color:purple) geralmente vemos primeiro se há alguma [entrada não válida](color:pink), se não escolhemos a entrada que não está a ser usada há mais tempo (LRU- _least-recently used_), o que é simples para uma via de 2, é gerível -com facilidade para 4, mas mais do que isso é demasiado díficil; nesses casos +com facilidade para 4, mas mais do que isso é demasiado difícil; nesses casos funciona mais ou menos da mesma forma mas mais [aleatório](color:pink). :::tip[Exemplos] @@ -652,7 +660,7 @@ Existem várias técnicas para otimização de acesso de dados: Pré-busca, [_prefetching_](color:blue) em inglês, refere-se ao carregamento de um recurso antes que seja necessário de modo a diminuir o tempo de espera para esse recurso. Assim, um [_software prefetching_](color:pink) não pode ser feito nem demasiado cedo, visto que os dados podem ser expulsos antes de serem usados, nem -demasiado tarde pois os dados podem não der trazidos a tempo da sua utilizção. Esta +demasiado tarde pois os dados podem não der trazidos a tempo da sua utilização. Esta técnica é [_greedy_](color:purple). Da mesma forma, o pré-carregamento, ou [_preloading_](color:blue) em inglês funciona como um pseudo prefetching, usando um processamento _hit-under-miss_, isto é o acesso antigo é um _miss_ e, por isso, o @@ -691,7 +699,7 @@ no esquema abaixo. Em 1989, McFarling [reduziu _cache misses_ por 75%](color:pink) em caches de mapeamento direto de 8 kB e blocos de 4 bytes em software. Para tal, foi necessário [reorganizar os procedimentos em memória](color:purple) para reduzir os -_conflict misses_, assim como fazer um [perfil](color:purple) de modo a analizar os +_conflict misses_, assim como fazer um [perfil](color:purple) de modo a analisar os conflitos, usando ferramentas que eles desenvolver. Os dados obtidos foram os seguintes: - [_Merging arrays_](color:yellow): melhoram a localidade espacial através de um único diff --git a/content/oc/0005-memoria-virtual.md b/content/oc/0005-memoria-virtual.md index 3378b3371..9cb7d588d 100644 --- a/content/oc/0005-memoria-virtual.md +++ b/content/oc/0005-memoria-virtual.md @@ -13,15 +13,6 @@ type: content # Memória Virtual -:::danger[Conteúdo Não Revisto] - -O conteúdo abaixo não foi revisto e poderá conter erros. -Agradecem-se [contribuições](https://docs.leic.pt/). - -Apenas foi aqui incluído devido à proximidade do MAP45 dia 2022/10/20. - -::: - ```toc ``` @@ -32,7 +23,7 @@ sistema operativo (OS). Assim, cada programa é compilado para o seu próprio es endereçamento, um [espaço de endereçamento virtual](color:purple). Nos programas que partilham a memória principal, cada um tem direito a um espaço de endereçamento físico privado que é frequentemente usado para código e dados, assim como é protegido dos -outros programas. O CPU e o OS traduzem o endereço virtual para um enderço físico, +outros programas. O CPU traduz o endereço virtual para um enderço físico, tendo, por isso, a VM um "bloco" que se chama [página](color:pink) e em vez de dizermos que houve um _"miss"_ dizemos que houve uma [_page fault_](color:pink). @@ -57,24 +48,21 @@ Sempre que a cache acomoda um subcojunto de posições da memória principal, a principal acomoda um subconjunto de posições da memória virtual. Cada [bloco corresponde a uma página](color:pink). A [dimensão](color:pink) é geralmente bastante elevada de modo a aumentar a eficiência quando o disco é acedido, e também -reduz a dimensão da tabela de tradução; porém, quanto maior for, maior é a potencial -perda de memória (em média, 50% da dimensão da página); valores típicos são entre 4K -e 8K bytes. +reduz a dimensão da tabela de tradução; porém, quanto maior for a página, maior é a potencial +perda de memória (em média, 50% da dimensão da página); valores típicos de página são os 4 +ou 8 Kbytes. -Um bloco pode ser posicionado em qualquer [espaço de memória](color:purple) visto ter -associatividade total. +Uma página pode ser posicionada em qualquer [espaço de memória](color:purple) visto a memória principal ter associatividade total. ![Tradução usando tabela de página](./assets/0005-traducao2.png#dark=3) -## Tabelas de Página +## Tabelas de Páginas -As [tabelas de página](color:pink) guardam o posicionamento da informação num array -te entradas todas indexadas por um número de uma página virtual. A tabela de página -regista os pontos do CPU da tabela de página em [memória física](color:purple). Se -uma página [estiver presente em memória](color:orange), temos o PTE -(_Page Table Entry_) que guarda o número da página física assim como outros bits de -estado (_dirty_, _referenced_, ...); caso contrário, o [PTE](color:pink) pode referir -outra localização em troca de espaço no disco. +As [tabelas de páginas](color:pink) guardam o posicionamento da informação num array +de entradas todas indexadas pelo número da página virtual. A tabela de páginas +regista o endereço de memória física para onde aponta a página do endereço virtual +além de outros bits de estado (_dity_, _referenced_, ...); +caso contrário, o [PTE](color:pink) pode referir outra localização em troca de espaço no disco. ### Trocas e Escritas @@ -94,8 +82,8 @@ quando a página é escrita. Um problema comum na paginação de sistemas é que a dimensão de uma tabela de página não é obrigada a traduzir os endereços: apenas precisa de alocar numa [região contida](color:pink) a memória física. Por exemplo, se temos um espaço virtual -com $2^{32}$ bytes e páginas com 4 bytes, ou seja $2^{12}$, temos uma tabela com -$2^{20}$ entradas visto que $32-12=20$, ou seja temos 4M bytes de entradas! +com $2^{32}$ bytes e páginas com 4 kbytes, ou seja $2^{12}$ bytes, temos uma tabela com +$2^{20}$ entradas visto que $32-12=20$, ou seja temos 1 milhão entradas! ### Hierarquia das Tabelas de Página @@ -108,14 +96,14 @@ hierarquia da tradução das tabelas. :::tip[Exemplos] Para mais exemplos de cálculos com hierarquia de memória é recomendada a -realização da quinta ficha das aulas práticas ou ver a sua resolução. +realização da 5ª ficha das aulas práticas ou ver a sua resolução. ::: ## Tabelas Invertidas A tradução de endereços é baseada em [_hash tables_](color:purple). Uma qualquer -função has H(x) é aplicada ao endereço virtual de modo a encontrar uma fila +função hash H(x) é aplicada ao endereço virtual de modo a encontrar uma fila particular de descriptores composta pelos pares [página virtual - página física](color:pink) , que correspondem a endereços virtuais dando origem ao mesmo valor da função hash H(x) em termos de colisões. Assim, o endereço físico necessário pode, ou não, estar presente @@ -132,26 +120,18 @@ Assim, é necessária [memória extra](color:blue) para aceder a tradução de V Isto faz com que os acessos à memória sejam ainda mais caros, e a maneira de resolver o problema de _hardware_ é através de um [_Translation Lookaside Buffer_](color:pink) isto é, uma **TLB**, que corresponde a uma cache mais pequena que acompanha os endereços -acedidos de modo a evitar ter que fazer uma tabela de página para os encontrar. +acedidos de modo a evitar ter que recorrer à tabela de página para os encontrar. ## _Translation Lookaside Buffer_ ou TLB ![TLB](./assets/0005-TLB.png#dark=3) Tal como em qualquer outra cache, a TLB pode ser organizada de modo a ser totalmente -associativa, ou diretamente mapeada. O tempo de acesso à TLB é tipicamente menor que -o tempo de acesso à cache visto que as TLBs são muito menores! +associativa, ou diretamente mapeada. O tempo de acesso à TLB é extremamente menor que +o tempo de acesso à cache visto que as TLBs são muito menores e são desenhadas para ser rápidas! ![TLB](./assets/0005-TLBmem.png#dark=3) -Se uma página é carregada para a memória principal, então o _miss_ na TLB pode ser -tratado, tanto em _hardware_ como em _software_ se carregarmos a [tradução](color:pink) -da informação da tabela de página para a TLB. Sabendo que demora dezenas de ciclos para -econtrar e carregar a tradução da informação para a TLB, quando a página não se -encontra na memória principal, demora milhares de ciclos, e temos, por isso, uma -_true page fault_. É importante referir que os _misses_ são bastante mais comuns que -as _true page faults_. - Assim, quando ocorre um [TLB _miss_](color:pink), é necessário reconhecer como _miss_ antes que o registo do destino seja sobrescrito, dando origem a uma exceção. Assim o _handler_ copia o PTE da memória para a TLB, reiniciando a instrução e, caso a página @@ -170,7 +150,7 @@ por isso, a instrução que falha é reiniciada. ![Interação](./assets/0005-interaction.png#dark=3) Se a tag da cache usa um endereço de memória, é necessário traduzir antes de ir -procurar a cache. Uma alternatica é usar uma tag de endereço de memória virtual, +procurar a cache. Uma alternativa é usar uma tag de endereço de memória virtual, contudo, tal pode ser complicado graças a _aliasing_, isto é, diferentes endereços virtuais para endereços físicos partilhados. @@ -185,12 +165,12 @@ memória torna-se inconsistente. ### Redução do Tempo de Tradução -Sabendo a interpretação de endereços virtuais pela TLB é representada da seguinte forma: +Sabendo que a interpretação de endereços virtuais pela TLB é representada da seguinte forma: | Virtual page index | Virtual offset | | :----------------: | :------------: | -E a interpretação dos endereços físicos pela cache é representada da seguinte forma: +E que a interpretação dos endereços físicos pela cache é representada da seguinte forma: | Tag | Index | Offset | | :-: | :---: | :----: | @@ -221,11 +201,11 @@ Por isso, um dos seguintes cenários pode ocorrer: ## Proteção de Memória Como é evidente, diferentes tarefas podem partilhar partes dos seus espaços de -endereçamento virtual, mas é necessário [proteger contrar acessos errantes](color:pink). -Para tal, precisamos de ajuda do OS. +endereçamento virtual, mas é necessário [proteger contra acessos errantes](color:pink). +Para tal, precisamos de ajuda do sistema operativo. -Visto que o suporte _hardware_ para porteção do OS, temos um modo supervisor -previlegiado, isto é, o [_kernel mode_](color:purple), instruções previlegiadas, +Existe suporte de _hardware_ para proteção do OS, pelo que temos um modo supervisor +privilegiado, isto é, o [_kernel mode_](color:purple), instruções privilegiadas, tabelas de páginas e outros estados de informação que só podem ser acedidos com o modo supervisor e uma chamada de exceção do sistema. @@ -249,12 +229,10 @@ nível de hierarquia temos: miss que pode ser através da política LRU ou aleatório; em termos de memória virtual o LRU tem uma aproximação com o suporte de _hardware_. -- [_Write Policy_](color:pink): como já tinhamos visto anteriormente, podemos ter - _write-throughs_ que atualizam tanto os níveis superiores como inferiorese - simplificam a troca mas precisam de um _buffer_ de escrita; ou _write-backs_ que apenas atualizam os níveis superior e só atualizam os inferiores quando o bloco é +- [_Write Policy_](color:pink): como já tínhamos visto anteriormente, podemos ter + _write-throughs_ que atualizam tanto os níveis superiores como inferiores e + simplificam a troca mas precisam de um _buffer_ de escrita; ou _write-backs_ + que apenas atualizam os níveis superior e só atualizam os inferiores quando o bloco é resposto, ou seja, é necessário manter mais estado. Assim, em termos de memória virtual, só o _write-back_ é fazível, visto que existe uma latência de escrita no disco. - -[_Cache Design Trade-offs_](color:green) -![_Cache Design Trade-offs_](./assets/0005-design.png#dark=3) diff --git a/content/oc/assets/0005-design.png b/content/oc/assets/0005-design.png deleted file mode 100644 index 6250630eb..000000000 Binary files a/content/oc/assets/0005-design.png and /dev/null differ