Search
Na začátku cvičení se vrátíme k verzovacímu systému Git a vyzkoušíme si vytváření a spojování větví. Potřebné příkazy najdete třeba na stránce GIT (2/2) - přehled základních příkazů
Pro analýzu volání funkcí použijeme následující kód:
#include <valgrind/callgrind.h> int add() { int val = 0; for(int i = 0; i < 800; ++i) val += i; return val; } int mult() { int val = 1; for(int i = 0; i < 800; ++i) val *= i; return val; } int foo() { return add() + add() + mult(); } int main(void) { int dum = 0; CALLGRIND_START_INSTRUMENTATION; for(int i = 0; i < 80000; ++i) dum += foo(); CALLGRIND_STOP_INSTRUMENTATION; return 0; }
Jednoduchý nástroj na analýzu volání funkcí se jmenuje gprof a je součástí balíčku binutils. Aby bylo možné nástroj využít, je třeba kompilovat zdrojový kód s volbou -pg. Po spuštění takto kompilovaného prorgramu se vytvoří soubor gmon.out, který obsahuje informace pro gprof.
gprof
binutils
-pg
gmon.out
gcc -Wall -pg call.c -o call ./call gprof call gmon.out > gpref_res
Druhým nástrojem je callgrind, součást valgrindu.
callgrind
valgrindu
valgrind --tool=callgrind --dump-instr=yes --instr-atstart=no ./call
Při volání vznikne log, který je možné analyzovat vhodným nástrojem, např. qcachegrind.
Moderní procesory nepřistupují do operační paměti přímo, ale přes dočasné paměti (cache), díky kterým lze za příznivých podmínek významně urychlit získání dat.
Pro testy budeme používat program, který náhodně vybírá prvky předdefinovaného pole
#include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 10485763 #define NBR 10000 int main() { srand(time(NULL)); // array of data int* a = malloc(SIZE*sizeof(int)); for (int i = 0; i < SIZE; i++) a[i] = i; // array of random index int* index = malloc(NBR*sizeof(int)); for (int k = 0; k < NBR; ++k) index[k] = rand() % SIZE; int d = 0; for (int k = 0; k < 1000; ++k) { int c = 0; // random fashion access for (int n = 0; n < NBR; ++n) c += a[index[n]]; d += c; } printf("%i\n", d); free(a); free(index); return 0; }
V Linuxu se tradičně používá nástroj perf, který je součástí balíčku linux-tools. Pokud používáte WSL, je třeba zkompilovat nástroj ze zdrojového kódu upraveného jádra Linuxu:
perf
linux-tools
sudo apt install build-essential flex bison libssl-dev libelf-dev git clone --depth=1 https://github.com/microsoft/WSL2-Linux-Kernel.git cd WSL2-Linux-Kernel/tools/perf make
V prostředí WSL ale zdá se není analýza plně podporována
Proto vyzkoušíme nástroj cachegrind, který je opět integrován ve valgrindu.
cachegrind
valgrind --tool=cachegrind --cache-sim=yes ./cache
Pro urychlení práce můžete využít třeba následující makefile:
call: call.c $(CC) -g call.c -o call cache: cache.c $(CC) -g cache.c -o cache callgrind: valgrind --tool=callgrind --dump-instr=yes --instr-atstart=no ./call cachegrind: valgrind --tool=cachegrind --cache-sim=yes ./cache perf: perf stat -ddd ./cache clean: rm -f call cache *grind.out.*