:class: tip
This lecture will cover contents from Chapter 12 of the book.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## Debugging
- A systematic approach to debugging.
- The programmer creates a defect
- The defect causes an infection
- The infection propagates
- The infection causes a failure
- Not every defect causes a failure!
- Testing can only show the presence of errors - not their absence.
- In other words, if you pass every tests, it means that your program has yet to fail.
It does not mean that your program is correct.
- Stating the problem
- Describe the problem aloud or in writing
- A.k.a. `Rubber duck` or `teddy bear` method
- Often a comprehensive problem description is sufficient to solve the failure
:::::{tab-set}
::::{tab-item} Bad Fib
- A bad implementation of Fibonacci sequence
<script src="https://gist.github.com/linhbngo/d1e9336a82632c528ea797210ed0f553.js?file=bad_fib.c"></script>
- Specification defined the first Fibonacci number as 1.
- Compile and run the following `bad_fib.c` program:
- `fib(1)` returns an incorrect result. Why?
```bash
$ gcc -o bad_fib bad_fib.c
$ ./bad_fib
:::: ::::{tab-item} Scientific debugging
Ockham’s Razor: given several hypotheses, pick the simplest/closest to current work
while (n 1): did we mess up the loop in fib?int f: did we forget to initialize f?n >= 1: ???int f = 1: Works. Sometimes a prediction can be a fix. :::: ::::{tab-item} Brute force-Wall, -Werror.-O3 or -O0.
1
$ gcc -Wall -Werror -O3 -o bad_fib bad_fib.c
valgrind, memory analyzer.
1
2
$ gcc -Wall -Werror -o bad_fib bad_fib.c
$ valgrind ./bad_fib
:::: ::::{tab-item} Observation
Calling fib(1) will return 1. printf() can interfereDo NOT ever proceed past first bug. :::: :::::
matrix_mult.c and block_matrix_mult.c :::::{tab-set} ::::{tab-item} matrix_mult.c
:::: ::::{tab-item} block_matrix_mult.c
:::: :::::
matrix_mult.c and block_matrix_mult.clays with how the loops are broken up to align with cache size.:::::{tab-set} ::::{tab-item} Cache blocks
1
$ getconf -a | grep CACHE
8 * 8 = 64 fits in cache line).3 * 8 * 8 < 32768. :::: ::::{tab-item} Without cache
matrix_mult.c.
1
2
3
4
$ gcc -o mm matrix_mult.c
$ ./mm 512
$ ./mm 1024
$ ./mm 2048
:::: ::::{tab-item} With cache
block_matrix_mult.c.
1
2
3
4
$ gcc -o bmm block_matrix_mult.c
$ ./bmm 512
$ ./bmm 1024
$ ./bmm 2048
:::: :::::
:::::{tab-set} ::::{tab-item} Reduce code motion
:::: ::::{tab-item} Reduction in strength
:::: ::::{tab-item} Scripting
1
2
3
4
$ chmod 755 eval.sh
$ ./eval.sh block_matrix_mult
$ ./eval.sh block_matrix_mult_2
$ ./eval.sh block_matrix_mult_3
:::: ::::{tab-item} Outcome
:::: :::::
:::::{tab-set} ::::{tab-item} Example: AVX/AVX2
:::: ::::{tab-item} Intrinsic Code
1
2
3
4
5
6
7
8
$ gcc -mavx2 -o imm intrinsic_sum.c
$ ./imm 1024
$ ./imm 2048
$ ./imm 4096
$ ./imm 8192
$ ./imm 16384
$ ./imm 32678
$ ./imm 33554432
:::: ::::{tab-item} Outcome
:::: :::::
```