# Raport do zadania `matmult`
### Autor: Wiktoria Kuna
### Numer indeksu: 316418
Konfiguracja
---
Informacje o systemie:
* Dystrybucja: Pop!_OS 19.10
* Jądro systemu: Linux 5.3.0-7625-generic
* Kompilator: GCC 9.2.1
* Procesor: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
* Liczba rdzeni: 4
Pamięć podręczna:
* L1d: 32 KiB, 8-drożny (per rdzeń), rozmiar linii 64B
* L2: 256 KiB, 4-drożny (per rdzeń), rozmiar linii 64B
* L3: 8 MiB , 16-drożny (współdzielony), rozmiar linii 64B
Pamięć TLB:
* L1d: 4KiB strony, 4-drożny, 64 wpisy
* L2: 4 KiB + 2 MiB strony, 12-drożny, 1536 wpisów
Informacje o pamięciach podręcznych uzyskano na podstawie wydruku programu
`x86info` oraz [wikichip](https://en.wikichip.org/wiki/intel/microarchitectures/coffee_lake).
Wyniki eksperymentów
---
### Powtórzenie eksperymentu z wykładu
Wykres przedstawiający ilość cykli na wewnętrzną iterację pętli (analogiczny do tego z wykładu ze slajdu 48):

### Pomiary dla różnych wartości parametru `BLOCK`
Doświadczenie wykonane dla parametrów:
```
T long;
#define A_OFFSET NITEMS(BLOCK_SIZE * 2, T);
#define B_OFFSET NITEMS(BLOCK_SIZE * 1, T);
#define C_OFFSET NITEMS(BLOCK_SIZE * 0, T);
```
Rozmiar bloku `s` w zależności od typu `T` i parametru `BLOCK`
```
s = BLOCK * BLOCK * sizeof(T);
```
W zależności od parametru `BLOCK` w pliku `matmult.h` otrzymujemy następujące uśrednione wyniki dla współczynnika chybienia:
| | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 |
|:---:|:------:|:------:|:-----:|:-----:|:-----:|:-----:|:------:| ------ |
| L1 | 49.91% | 12.24% | 4.85% | 1.89% | 2.69% | 6.59% | 32.18% | 50.52% |
| L2 | 50.26% | 19.30% | 9.64% | 3.15% | 2.43% | 2.02% | 11.09% | 19.61% |
| L3 | 3.05% | 1.28% | 1.20% | 0.52% | 0.32% | 0.21% | 0.17% | 0.24% |
| TLB | 3.26% | 0.47% | 0.17% | 0.12% | 0.03% | 0.02% | 0.01% | 0.01% |
Wykres zależności wielkości bloku od czasu:

Wykres dla offsetów 0-0-0:

Wykres dla offsetów 2-1-0

Wnioski
---
### Powtórzenie eksperymentu z wykładu
Na pierwszy rzut oka, wykres może w żadnym stopniu nie przypominać tego z wykładu. Dzieje się tak ze względu na niemożliwe do przeoczenia uskoki (szczególnie dla mutmult2).
Pomijając błędy pomiarowe, obserwujemy względnie podobne różnice w wydajności funkcji.
Na slajdach z wykładu dla n = 700 matmult0(jki) bliski jest osiągnięcia 80 cykli na iteracje, gdzie dla mojego komputera jest to około 10. Zjawisko to możnaby było wytłumaczyć różnicą procesorów. Do wygenerowania wykresu z wykładu użyty został 2 rdzeniowy procesor o częstotliwości 2GHz. Dla porównania - mój jest 4 rdzeniowy 4GHz.
### Pomiary dla różnych wartości parametru `BLOCK`
Obserwujemy znaczną różnicę dla użycia bloków o parametrze `BLOCK` $\in \{4,6,8\}$, do tych o `BLOCK` $\in \{2,32\}$, a w szczególności dla tych o `BLOCK` $\in \{1,64,128\}$.
Optypamizacja z podziałem na bloki (kafelkowanie) ma na celu dostosować dane na których operujemy do parametrów naszej pamięci podręcznej - im mniej długich wędrówek w coraz niższe poziomy pamięci - tym lepiej.
W wypadku doświadczenia najlepiej wypadło kafelkowanie dla `BLOCK = 8`, czyli dla bloków 512 B, co dobrze współgra w organizacją 8-drożną sekcyjno-skojarzeniową. Wybieranie parametrów `BLOCK` $\in \{1, 2, 64, 128\}$ sprawia, że nie jesteśmy lokalni w dysponowaniu pamięcią i skutkuje częstszą wymianą linii w poziomach L1, L2.
### Podsumowanie
Powyższe eksperymenty pozwoliły pokazać, że korzystanie z parametrów sprzętowych może znacznie wpłynąć na wydajność napisanych programów. Warto zatem (przy odpowiedniej wielkości danych) zadbać o lokalność używanej pamięci.
#### AD offset
Wykonując testy dla różnych kombinacji parametrów offset nie spostrzegłam istonego wpływu na wydajność.
###### tags: `ask`