├── .gitignore
├── FFI-Tensor
├── README.md
└── src
│ ├── Makefile
│ ├── main.lua
│ └── size.c
├── FFI-so
├── README.md
└── src
│ ├── Makefile
│ ├── asdf.c
│ └── run.lua
├── GDB
├── README.md
└── src
│ ├── Makefile
│ ├── run.lua
│ └── segfault.c
├── MobDebug
├── README.md
└── src
│ └── test.lua
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Files
2 | *.sw*
3 | .DS_Store
4 | *.so*
5 |
--------------------------------------------------------------------------------
/FFI-Tensor/README.md:
--------------------------------------------------------------------------------
1 | # `Tensor`s through *FFI*
2 |
3 | In the first tutorial we saw how to edit the values of the array associated with the underlying `Storage` of a `Tensor`.
4 | Here we'll see how to send the whole `Tensor` to *C* and access its internals.
5 |
6 | ## *C* source code
7 |
8 | The main difference is that we need to `#include
` in our [`src/size.c`](src/size.c)
9 |
10 | ```c
11 | #include |
12 |
13 | void printSize(THFloatTensor* src) {
14 | ...
15 | }
16 | ```
17 |
18 | in order to be able to use `THFloatTensor` and other *Torch* releated stuff.
19 |
20 | ## Compilation details
21 |
22 | Moreover, we need to tell `gcc` where to find libraries and shared objects.
23 | We can do this by adding some options to our [`src/Makefile`](src/Makefile)
24 |
25 | ```makefile
26 | LIBOPTS = -I$(HOME)/torch/install/include -L$(HOME)/torch/install/lib -lTH
27 | ```
28 |
29 | where `$(HOME)` points to your home `~`, `-I` provide the location of the *header* file, `-L` specify where to find the shared object which is located with the `-l` (lowercase *L*) argument, and which name here is `libTH.so` or `libTH.dylib`.
30 |
31 | ## Scripting in *Lua*
32 |
33 | Finally, from *Lua* [`src/main.lua`](src/main.lua) will send the whole `Tensor`'s `struct`
34 |
35 | ```lua
36 | -- Main program ----------------------------------------------------------------
37 | -- Define a random sized Tensor
38 | math.randomseed(os.time())
39 | x = torch.FloatTensor(unpack(torch.Tensor(math.random(10)):random(10):totable()))
40 | -- Send it to C
41 | C.printSize2D(x:cdata())
42 | ```
43 |
44 |
--------------------------------------------------------------------------------
/FFI-Tensor/src/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Make file for building the shared library
3 | ################################################################################
4 | # Alfredo Canziani, Sep 16
5 | ################################################################################
6 |
7 | LIBOPTS = -I$(HOME)/torch/install/include -L$(HOME)/torch/install/lib -lTH
8 | CFLAGS = -fPIC -shared
9 | CC = gcc
10 |
11 | libsize.so : size.c
12 | $(CC) $< $(LIBOPTS) $(CFLAGS) -o $@
13 |
14 | clean :
15 | rm *.so
16 |
--------------------------------------------------------------------------------
/FFI-Tensor/src/main.lua:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | -- Tensors through FFI
3 | --------------------------------------------------------------------------------
4 | -- Alfredo Canziani, Sep 16
5 | --------------------------------------------------------------------------------
6 |
7 | -- FFI stuff -------------------------------------------------------------------
8 | -- Require ffi
9 | local ffi = require 'ffi'
10 | -- Load myLib
11 | local C = ffi.load('libsize.so')
12 | -- Function prototypes definition
13 | ffi.cdef[[
14 | void printSize(THFloatTensor* src);
15 | ]]
16 |
17 | -- Main program ----------------------------------------------------------------
18 | -- Define a random sized Tensor
19 | math.randomseed(os.time())
20 | x = torch.FloatTensor(unpack(torch.Tensor(math.random(10)):random(10):totable()))
21 | -- Send it to C
22 | C.printSize(x:cdata())
23 |
24 | -- Lua printing functions
25 | print('Lua says:')
26 | print(' + Dimension: ' .. x:dim())
27 | io.write(' + Size: ' .. x:size(1))
28 | for d = 2, x:dim() do io.write(' x ' .. x:size(d)) end
29 | io.write('\n')
30 |
--------------------------------------------------------------------------------
/FFI-Tensor/src/size.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | Size library
3 | ********************************************************************************
4 | Alfredo Canziani, Sep 16
5 | *******************************************************************************/
6 |
7 | // Include TH library and printf
8 | #include |
9 | #include
10 |
11 | // Prints all sized of a given Tensor
12 | void printSize(THFloatTensor* src) {
13 | printf("C says:\n");
14 | printf(" + Dimension: %d\n", src->nDimension);
15 | printf(" + Size: %ld", src->size[0]);
16 | for (int d = 1; d < src->nDimension; d++)
17 | printf(" x %ld", src->size[d]);
18 | printf("\n");
19 | }
20 |
--------------------------------------------------------------------------------
/FFI-so/README.md:
--------------------------------------------------------------------------------
1 | # *FFI* and `.so` library
2 |
3 | Everything starts from the will of running a super awesome *C* library from within *Torch*.
4 | So, let's start step by step, with the writing of the *C* source code.
5 |
6 | ## *C* source code
7 |
8 | So, for this super mega project we would like to fill an `int` *array* of length `size` with the index of each of its elements starting from `1`.
9 |
10 | ```c
11 | void dummy(int* ptrFromLua, int size) {
12 |
13 | for (int i = 0; i < size; i++)
14 | ptrFromLua[i] = i + 1;
15 |
16 | return;
17 |
18 | }
19 | ```
20 |
21 | What this code does is simply *defining* a *routine* (or `void` *function*) called `dummy`, which expects a *pointer* to a `int` *array* of `size` elements. Once it is called, it iterates over all the *array* by filling its elements with their *C* index `+ 1`. Then it `return` a `void`.
22 | The source code is available at [`src/asdf.c`](src/asdf.c).
23 |
24 | ## *make* and `.so` compilation
25 |
26 | Now we need to build our *shared library* from the *C* source file. As for convention, the library name will be `lib` + *name* + `.so`, so in this case we'll end up with a file called `libasdf.so`.
27 |
28 | For compiling the source code shown above into a *shared library* we need to use *gcc* with several arguments.
29 | In order to simplify this procedure, a [`src/Makefile`](src/Makefile) can be created instead, where all this information can be directly executed by typing the command `make` from within the [`src`](src) directory.
30 |
31 | ### Compilation details
32 |
33 | For the more curious of the readers, I'm going to briefly explain how the [`src/Makefile`](src/Makefile) has been written.
34 |
35 | ```makefile
36 | LIBOPTS = -shared
37 | CFLAGS = -fPIC -std=gnu99
38 | CC = gcc
39 |
40 | libasdf.so : asdf.c
41 | $(CC) $< $(LIBOPTS) $(CFLAGS) -o $@
42 |
43 | clean :
44 | rm *.so
45 | ```
46 |
47 | `CC` specifies the *compiler* that is going to be used; `-shared` means we are going to create a *shared library* from a `-fPIC` *Position Independent Code* (there is no `main()` function) which has a variable definition within a `for` definition, and therefore, requires `-std=gnu99`.
48 | Hence, typing `make` will build an `-o` output `libasdf.so` from the source code `asdf.c`.
49 | If we would like to remove every file generated by *make*, we can simply issue `make clean` and it will do the trick.
50 |
51 | ## Scripting in *Lua*
52 |
53 | And now we are almost at the end! From *Lua* we need to *expose* the *pointer* of a `IntTensor` of dimension `length` and send both *pointer* and *size* to the *C* function that is ready to be used in our *shared library* `libasdf.so`.
54 |
55 | ```lua
56 | -- FFI stuff -------------------------------------------------------------------
57 | -- Require ffi
58 | ffi = require("ffi")
59 | -- Load myLib
60 | myLib = ffi.load(paths.cwd() .. '/libasdf.so')
61 | -- Function prototypes definition
62 | ffi.cdef [[
63 | void dummy(int* ptr_form_lua, int size)
64 | ]]
65 |
66 | -- Main program ----------------------------------------------------------------
67 | length = 5
68 | a = torch.IntTensor(length):random()
69 | myLib.dummy(torch.data(a), length)
70 | ```
71 |
72 | Some comments about the "*FFI* stuff". We need first to `require` the `ffi` *Lua* package, then we can `ffi.load` the shared library we have built with *make* and lastly we need to tell *LuaJIT* what is the *prototype* of our *routine*.
73 | In the "Main program", we have simply to create a random `IntTensor`, expose its *C* pointer with `torch.data()` and send it, along with its `length` to the *C* `dummy()` routine which is now available as a *Lua* function in the `myLib` table.
74 |
75 | ## Motivations
76 |
77 | Why is this stuff cool? Run the source code [`src/run.lua`](src/run.lua) and you'll understand it. Bare in mind that **you have to actually read the instructions** at the begining of the code and experiment with different combination of options by commenting some lines of code.
78 |
79 | For the more lazy ones, I'll write here some conclusions myself.
80 | By setting `length` to `1e7`, i.e. 10 millions, and disabling the `print()` of the array on screen, I get the following output:
81 |
82 | ```
83 | C function computation time 31.98 ms
84 | Lua loop computation time 2890.92 ms
85 | ```
86 |
87 | Which means, *C* completed the task in `1/30` of a second, whereas *Lua* takes almost `3` seconds for finishing its `for` loop. We can make *Lua* perform better, and we'll do it in the next tutorial session.
88 |
89 | Another reason about *why* you are loving this tutorial is that now you can use whatever compiled library — like some cool stuff from [*OpenCV*](http://opencv.org/), [*FFmpeg*](https://www.ffmpeg.org/) or even from your own *shared library* you just compiled with a `Makefile` — and interface it with *Torch*. This means your horizons have never been so wide! Go, and start interfacing a new library!
90 |
--------------------------------------------------------------------------------
/FFI-so/src/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Make file for building the shared library
3 | ################################################################################
4 | # Alfredo Canziani, Nov 14
5 | ################################################################################
6 |
7 | LIBOPTS = -shared
8 | CFLAGS = -fPIC -std=gnu99
9 | CC = gcc
10 |
11 | libasdf.so : asdf.c
12 | $(CC) $< $(LIBOPTS) $(CFLAGS) -o $@
13 |
14 | clean :
15 | rm *.so
16 |
--------------------------------------------------------------------------------
/FFI-so/src/asdf.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | Dummy library
3 | ********************************************************************************
4 | Alfredo Canziani, Nov 14
5 | *******************************************************************************/
6 |
7 | // Dummy function definition
8 | void dummy(int* ptrFromLua, int size) {
9 |
10 | for (int i = 0; i < size; i++)
11 | ptrFromLua[i] = i + 1;
12 |
13 | return;
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/FFI-so/src/run.lua:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | -- FFI and .so library
3 | --------------------------------------------------------------------------------
4 | -- Alfredo Canziani, Nov 14
5 | --------------------------------------------------------------------------------
6 |
7 | -- Instructions ----------------------------------------------------------------
8 | -- You can run this code and see the results of the operation (1st option) or
9 | -- you can increase the lenght of the tensor and turn off the printing
10 |
11 | -- Choose a combination (comment the other)
12 | --<<<
13 | length = 5; display = true
14 | --<<<>>>
15 | --length = 1e7; display = false
16 | -->>>
17 |
18 | -- FFI stuff -------------------------------------------------------------------
19 | -- Require ffi
20 | ffi = require("ffi")
21 | -- Load myLib
22 | myLib = ffi.load(paths.cwd() .. '/libasdf.so')
23 | -- Function prototypes definition
24 | ffi.cdef [[
25 | void dummy(int* ptr_form_lua, int size)
26 | ]]
27 |
28 | -- Shortcuts -------------------------------------------------------------------
29 | -- printf
30 | pf = function(...) print(string.format(...)) end
31 |
32 | -- Main program ----------------------------------------------------------------
33 | a = torch.IntTensor(length):random()
34 | b = a:clone()
35 | if display then
36 | print('Random vector')
37 | print(a)
38 | end
39 |
40 | timer = torch.Timer()
41 | myLib.dummy(torch.data(a), length)
42 | pf('C function computation time %.2f ms', timer:time().real*1e3)
43 | if display then print(a) end
44 |
45 | timer = torch.Timer()
46 | for i = 1, length do b[i] = i end
47 | pf('Lua loop computation time %.2f ms', timer:time().real*1e3)
48 | if display then print(b) end
49 |
--------------------------------------------------------------------------------
/GDB/README.md:
--------------------------------------------------------------------------------
1 | # *FFI* / `.so` debugging with *ADB*
2 |
3 | Let's say you've made your pretty nice *Lua* script that interfaces to a shared object which, after executing some instructions, miserably dies with a `Segmentation fault`.
4 |
5 | To let you feel the thrill youself, `cd` into [`src`](src), `make` the project and then run `th run.lua`.
6 | If you're on *Mac*, you'll get something like
7 |
8 | ```
9 | $ th run.lua
10 | Running a function from a shared object
11 | Segmentation fault: 11
12 | ```
13 |
14 | and if you're on *Ubuntu*, you'll see
15 |
16 | ```
17 | $ th run.lua
18 | Running a function from a shared object
19 | Segmentation fault (core dumped)
20 | ```
21 |
22 | In both cases, you'll see **only one** line of red text and the very little informative message regarding something that went wrong.
23 |
24 | Our poor little *Lua* script actually wanted to print one more red line...
25 |
26 | ```lua
27 | -- Main program ----------------------------------------------------------------
28 | local red = require('trepl.colorize').red
29 | print(red 'Running a function from a shared object')
30 | myLib.A()
31 | print(red 'Never here')
32 | ```
33 |
34 | but the bad and evil `.so` library ruined it all.
35 | How to move forward?
36 |
37 | ## GDB
38 |
39 | [GDB](https://www.gnu.org/software/gdb/), *the GNU Project debugger, allows you to see [...] what another program was doing at the moment it crashed.*
40 | Pretty sweet, uh?
41 | Since we're using `gdb`, I've included the flag `-ggdb` in the [`Makefile`](src/Makefile), which provides us with even more sweet treats, but it is not strictly required (so, this works even with `.so` compiled by someone else).
42 |
43 | > If you're on *Ubuntu*, `gdb` should be already there, ready to use.
44 | > Simply check whether `man gdb` returns anything.
45 | > On *Mac* things are a little more tedious, but not that bad, overall.
46 | > To install it we'll use brew, of course.
47 | >
48 | > ```
49 | > brew update
50 | > brew insatll gdb
51 | > ```
52 | >
53 | > Then we will need to *codesign* the `gdb` executable in order to allow the debugger to control other processes (on the *Darwin Kernel*) on your *Mac*.
54 | > To do so, follow the instructions [here](https://gcc.gnu.org/onlinedocs/gnat_ugn/Codesigning-the-Debugger.html) untill rebooting.
55 | > Then, type this in your terminal
56 | >
57 | > ```bash
58 | > sudo codesign -f -s "gdb-cert" $(which gdb)
59 | > ```
60 |
61 | Let's run *Torch* with `gdb` monitoring what's happening.
62 |
63 | ```bash
64 | gdb --args bash $(which th) run.lua
65 | ```
66 |
67 | You'll see something like this
68 |
69 | ```gdb
70 | $ gdb --args bash $(which th) run.lua
71 | GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
72 | Copyright (C) 2016 Free Software Foundation, Inc.
73 | License GPLv3+: GNU GPL version 3 or later
74 | This is free software: you are free to change and redistribute it.
75 | There is NO WARRANTY, to the extent permitted by law. Type "show copying"
76 | and "show warranty" for details.
77 | This GDB was configured as "x86_64-linux-gnu".
78 | Type "show configuration" for configuration details.
79 | For bug reporting instructions, please see:
80 | .
81 | Find the GDB manual and other documentation resources online at:
82 | .
83 | For help, type "help".
84 | Type "apropos word" to search for commands related to "word"...
85 | Reading symbols from bash...(no debugging symbols found)...done.
86 | ```
87 |
88 | Type `run`, and you'll get `th` execute the script
89 |
90 | ```gdb
91 | (gdb) run
92 | Starting program: /bin/bash /home/atcold/torch/install/bin/th run.lua
93 | process 16671 is executing new program: /home/atcold/torch/install/bin/luajit
94 | [Thread debugging using libthread_db enabled]
95 | Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
96 | Running a function from a shared object
97 |
98 | Program received signal SIGSEGV, Segmentation fault.
99 | 0x00007fffdbbe0729 in D () at segfault.c:8
100 | 8 *(int*)0 = 0;
101 | ```
102 |
103 | > On *Mac* it's likely you will also have to type `continue`
104 | >
105 | > ```gdb
106 | > (gdb) run
107 | > Starting program: /bin/bash /Users/atcold/torch/install/bin/th run.lua
108 | >
109 | > Program received signal SIGTRAP, Trace/breakpoint trap.
110 | > 0x00007fff5fc01000 in ?? ()
111 | > (gdb) continue
112 | > Continuing.
113 | > Running a function from a shared object
114 | >
115 | > Program received signal SIGSEGV, Segmentation fault.
116 | > D () at segfault.c:8
117 | > 8 *(int*)0 = 0;
118 | > ```
119 |
120 | So, here we have already a great deal of information.
121 | We know that the killing function is `D()`.
122 | Even if we would have not use the `-ggdb` flag we would have known this, given that the output would have looked like this
123 |
124 | ```gdb
125 | Running a function from a shared object
126 |
127 | Program received signal SIGSEGV, Segmentation fault.
128 | 0x00007fffdbbe0729 in D () from /home/atcold/Work/GitHub/torch-Developer-Guide/GDB/src/libsegfault.so
129 | ```
130 |
131 | But here, since we could, we run `-ggdb` as an option of `gcc`, which gives us the name of the incriminated source code (`segfault.c`) and its breaking line (`8`) and instruction (`*(int*)0 = 0;`).
132 | Otherwise, all we would have got would have been the name of the `.so` (`[...]/libsegfault.so`) and the breaking function name (`D()`).
133 |
134 | Finally, we can go back to how we eneded up calling `D()` by printing the whole *stack traceback* by typing `backtrace`.
135 |
136 | ```gdb
137 | (gdb) backtrace
138 | #0 0x00007fffdbbe0729 in D () at segfault.c:8
139 | #1 0x00007fffdbbe0740 in C () at segfault.c:13
140 | #2 0x00007fffdbbe0751 in B () at segfault.c:18
141 | #3 0x00007fffdbbe0762 in A () at segfault.c:23
142 | #4 0x000000000047fb79 in lj_vm_ffi_call ()
143 | #5 0x00000000004508e1 in lj_ccall_func ()
144 | #6 0x0000000000452d86 in lj_cf_ffi_meta___call ()
145 | #7 0x000000000047dbba in lj_BC_FUNCC ()
146 | #8 0x000000000046e842 in lj_cf_dofile ()
147 | #9 0x000000000047dbba in lj_BC_FUNCC ()
148 | #10 0x000000000046d15d in lua_pcall ()
149 | #11 0x0000000000406eaf in pmain ()
150 | #12 0x000000000047dbba in lj_BC_FUNCC ()
151 | #13 0x000000000046d1d7 in lua_cpcall ()
152 | #14 0x0000000000404e54 in main ()
153 | ```
154 |
155 | And the `in D () at segfault.c:8` and the following 3 lines would have become something like `in D () from /home/atcold/Work/GitHub/torch-Developer-Guide/GDB/src/libsegfault.so` if the `-ggdb` would have been missing.
156 |
157 | And this is the end.I wrote this because I was getting a `Segentation fault` and I had no clue what was going on.
158 | Now I feel I'm armed with a very powerful tool, that allows me to dig deeper and deeper into my compiled objects which I'm calling from *Torch* via the *FFI*.
159 |
160 | You can find a nice cheat sheet for *GDB* [here](http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf).
161 |
--------------------------------------------------------------------------------
/GDB/src/Makefile:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Make file for building the shared library + GDB debugging option
3 | ################################################################################
4 | # Alfredo Canziani, Sep 16
5 | ################################################################################
6 |
7 | LIBOPTS = -shared
8 | CFLAGS = -fPIC -std=gnu99 -ggdb
9 | CC = gcc
10 |
11 | libsegfault.so : segfault.c
12 | $(CC) $< $(LIBOPTS) $(CFLAGS) -o $@
13 |
14 | clean :
15 | rm -rf *.so*
16 |
--------------------------------------------------------------------------------
/GDB/src/run.lua:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------------------
2 | -- FFI / .so debugging with ADB
3 | --------------------------------------------------------------------------------
4 | -- Alfredo Canziani, Sep 16
5 | --------------------------------------------------------------------------------
6 |
7 | -- FFI stuff -------------------------------------------------------------------
8 | -- Require ffi
9 | ffi = require("ffi")
10 | -- Load myLib
11 | myLib = ffi.load(paths.cwd() .. '/libsegfault.so')
12 | -- Function prototypes definition
13 | ffi.cdef [[
14 | void A();
15 | ]]
16 |
17 | -- Main program ----------------------------------------------------------------
18 | local red = require('trepl.colorize').red
19 | print(red 'Running a function from a shared object')
20 | myLib.A()
21 | print(red 'Never here')
22 |
--------------------------------------------------------------------------------
/GDB/src/segfault.c:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | A segmentation fault program
3 | ********************************************************************************
4 | Alfredo Canziani, Sep 16
5 | *******************************************************************************/
6 |
7 | void D() {
8 | *(int*)0 = 0;
9 | return;
10 | }
11 |
12 | void C() {
13 | D();
14 | return;
15 | }
16 |
17 | void B() {
18 | C();
19 | return;
20 | }
21 |
22 | void A() {
23 | B();
24 | return;
25 | }
26 |
--------------------------------------------------------------------------------
/MobDebug/README.md:
--------------------------------------------------------------------------------
1 | # MobDebug
2 |
3 | Alright, if you got to this point it is likely that something doesn't quite work as expected in your script, or you're simply curious and want to learn new stuff.
4 | Either ways, let's get ahead, and see what's this about.
5 |
6 | ## What and why?
7 |
8 | On *Wikipedia* there is a whole [*category* about debugging](http://en.wikipedia.org/wiki/Debugging), so perhaps it's worth using some tools developed for aiding with this process rather then using `print()` and `io.read()` statements scattered all around the code.
9 |
10 | ## Installation
11 |
12 | First thing first. We need to install our debugger, otherwise you won't be able to experiment alongside.
13 | All you need to do is type
14 |
15 | ```bash
16 | luarocks install mobdebug
17 | ```
18 |
19 | ## Run the debugger
20 |
21 | ```lua
22 | th -e "require('mobdebug').listen()"
23 | ```
24 |
25 | ## Let's debug!
26 |
27 | In order to understand the different functionalities that *MobDebug* offers, we're going to debug, step by step, a simple *Lua* script.
28 | (The script itself can be found at [`src/test.lua`](src/test.lua), and it has been borrowed from [*remdebug*](https://github.com/LuaDist/remdebug)'s [testing script](https://github.com/LuaDist/remdebug/blob/master/tests/test.lua).)
29 |
30 | ```lua
31 | 1 require('mobdebug').start()
32 | 2
33 | 3 local tab = {
34 | 4 foo = 1,
35 | 5 bar = 2
36 | 6 }
37 | 7
38 | 8 print("Start")
39 | 9
40 | 10 function bar()
41 | 11 print("In bar 1")
42 | 12 print("In bar 2")
43 | 13 end
44 | 14
45 | 15 for i = 1, 10 do
46 | 16 print("Loop")
47 | 17 bar()
48 | 18 tab.foo = tab.foo * 2
49 | 19 end
50 | 20
51 | 21 print("End")
52 | ```
53 |
54 | > Generally speaking, all we need to do is add
55 | >
56 | > ```lua
57 | > require('mobdebug').start()
58 | > ```
59 | >
60 | > at the beginning of the script we want to debug.
61 |
62 | So, let's `cd` into [`src`](src) and `th` `test.lua`.
63 |
64 | ### `run`, `step`, `over` and `out`
65 |
66 | `run`, `step`, `over` and `out` are the four commands that allow us to proceed with the execution of the code, tackling line after line. By typing `help` withing the debugger session, we can see what their functions are.
67 |
68 | ```lua
69 | run -- runs until next breakpoint
70 | step -- runs until next line, stepping into function calls
71 | over -- runs until next line, stepping over function calls
72 | out -- runs until line after returning from current function
73 | ```
74 |
75 | ---
76 |
77 | We can start with `over`, `step`, `step`.
78 |
79 | ```lua
80 | > over
81 | Paused at file test.lua line 13
82 | > step
83 | Paused at file test.lua line 10
84 | > step
85 | Paused at file test.lua line 15
86 | ```
87 |
88 | The first `over` gets the program to print `Start`.
89 | The other two `step`s don't have any corresponding output.
90 |
91 | Our debugger is waiting for us at the beginning of the `for` loop.
92 | Let's skip to line `17` by setting a *breakpoint* and using `run`.
93 |
94 | ### Playing with *breakpoints*
95 |
96 | To execute the code up to *a specific line* of *a specific file* we can use the breackpoint / run combination.
97 | The instruction to set a breakpoint works as follow
98 |
99 | ```lua
100 | setb -- sets a breakpoint
101 | ```
102 |
103 | To list all available breakpoints, we can write
104 |
105 | ```lua
106 | listb -- lists breakpoints
107 | ```
108 | To remove a breakpoint or all breakpoints
109 |
110 | ```lua
111 | delb -- removes a breakpoint
112 | delallb -- removes all breakpoints
113 | ```
114 |
115 | ---
116 |
117 | Now we are at line `15` and, say, we'd like to skip to line `17`.
118 |
119 | ```lua
120 | > 15 for i = 1, 10 do
121 | 16 print("Loop")
122 | ↳ 17 bar()
123 | ```
124 |
125 | We are going to type `setb test.lua 17`, or, since we don't link to other scripts, we can type `steb - 17`.
126 |
127 | ```lua
128 | > setb - 17
129 | > run
130 | Paused at file test.lua line 17
131 | > listb
132 | -: 17
133 | ```
134 |
135 | `run` makes the script print `Loop` on screen.
136 |
137 | ### Evaluate and print variables & execute snippets
138 |
139 | Let's check now the value of some variables (**even local ones**!).
140 | We can do this with
141 |
142 | ```lua
143 | eval -- evaluates expression on the current context and returns its value
144 | ```
145 |
146 | or combining `print()` with
147 |
148 | ```lua
149 | exec -- executes statement on the current context
150 | ```
151 |
152 | > `exec` is really very powerful; I'll explain you why.
153 | >
154 | > Basically, it allows you to change the code **live**.
155 | > You are allowed to put your hands inside the warm heart of the script that is currently running with all its local variables.
156 | > This allows you to implement new functions (in someone's else code) way more easily (*i.e.* you don't have to read all the source code your collegue developed), since you'll find yourself in the exact same situation your new function will find itself when everything will be done.
157 |
158 | ---
159 |
160 | For example, let's check the *table* `tab`.
161 |
162 | ```lua
163 | > eval tab
164 | {bar = 2, foo = 1} --[[table: 0x06dfb9d0]]
165 | ```
166 |
167 | If we would like to rely on *Torch*'s pretty output format (which is advisable if you'd like visualise *Tensor*s nicely), we type
168 |
169 | ```lua
170 | > exec print(tab)
171 | ```
172 |
173 | ```lua
174 | {
175 | foo : 1
176 | bar : 2
177 | }
178 | ```
179 |
180 | which is outputed on the terminal where the program is running (and not on the debugger interface).
181 |
182 | Let's `run` again a couple of times and see what's changes!
183 |
184 | ```lua
185 | > run
186 | Paused at file test.lua line 17
187 | > eval tab
188 | {bar = 2, foo = 2} --[[table: 0x06dfb9d0]]
189 | > run
190 | Paused at file test.lua line 17
191 | > eval tab
192 | {bar = 2, foo = 4} --[[table: 0x06dfb9d0]]
193 | ```
194 |
195 | where `run` gets the script to output `In bar 1`, `In bar 2` and `Loop` twice.
196 | As we can see, line `18`
197 |
198 | ```lua
199 | 17 bar()
200 | 18 tab.foo = tab.foo * 2
201 | 19 end
202 | ```
203 |
204 | doubles `tab.foo`, which goes from `1` to `2` to `4`.
205 |
206 | As mentioned before, the real power of `exec` is the ability of changing the code that is running live.
207 | For example, let's set `tab.bar` to `5`.
208 |
209 | ```lua
210 | > exec tab.bar = 5
211 | > eval tab
212 | {bar = 5, foo = 4} --[[table: 0x06dcb8d8]]
213 | ```
214 |
215 | and **boom**, the variable has got a new value. So, this is fabulous is you have the need to update some hard-coded parameter variables.
216 |
217 | Now we can kill our breakpoint with
218 |
219 | ```lua
220 | > delb - 17
221 | > listb
222 | >
223 | ```
224 |
225 | and now run our code until `tab.foo` reaches the value `32` by setting a *watch expression*.
226 |
227 | ## *Watch expressions*
228 |
229 | A *watch-expression* allows you to run your code until a specific condition becomes valid.
230 | The syntax is the following:
231 |
232 | ```lua
233 | setw -- adds a new watch expression
234 | ```
235 |
236 | To list all available watch-expressions, we can write
237 |
238 | ```lua
239 | listw -- lists watch expressions
240 | ```
241 | To remove a watch-expressions or all watch-expressions
242 |
243 | ```lua
244 | delw -- removes the watch expression at index
245 | delallw -- removes all watch expressions
246 | ```
247 |
248 | ---
249 |
250 | Currently, `tab.foo == 4`. Let `run` the script until it reaches `32`.
251 |
252 | ```lua
253 | > setw tab.foo == 32
254 | Inserted watch exp no. 1
255 | > listw
256 | Watch exp. 1: tab.foo == 32
257 | > run
258 | Paused at file src/test.lua line 15 (watch expression 1: [tab.foo == 32])
259 | ```
260 |
261 | where `run` gets the script to output `In bar 1`, `In bar 2` and `Loop` twice plus an additional `In bar 1` and `In bar 2`.
262 |
263 | Now that we got to this point, let's check what's in `tab` (and remove the watch-expression, so that we don't get stuck)!
264 |
265 | ```lua
266 | > eval tab
267 | {bar = 5, foo = 32} --[[table: 0x06dcb8d8]]
268 | > delallw
269 | ```
270 |
271 | Let's end the execution of the program with `run`.
272 |
273 | ## Exit
274 |
275 | If we are done debugging, and we wish not to continue the execution of our scirpt, we can simply issue the `exit` command, which will terminate the debugging session and the script execution with it.
276 |
277 | ```lua
278 | exit -- exits debugger
279 | ```
280 |
--------------------------------------------------------------------------------
/MobDebug/src/test.lua:
--------------------------------------------------------------------------------
1 | require('mobdebug').start()
2 |
3 | local tab = {
4 | foo = 1,
5 | bar = 2
6 | }
7 |
8 | print("Start")
9 |
10 | function bar()
11 | print("In bar 1")
12 | print("In bar 2")
13 | end
14 |
15 | for i = 1, 10 do
16 | print("Loop")
17 | bar()
18 | tab.foo = tab.foo * 2
19 | end
20 |
21 | print("End")
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Torch Developer Guide
2 |
3 | [](https://gitter.im/Atcold/Torch-Developer-Guide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 |
5 | This repository tries to provide some advanced tricks with [Torch7](http://torch.ch/) explained easily
6 |
7 | ## *FFI* series
8 |
9 | [*LuaJIT*](http://luajit.org/) [*FFI library*](http://luajit.org/ext_ffi.html) provides an incredible easy way to call external *C* functions and use *C* data structures from pure Lua code.
10 | The *FFI series* will provide several working examples of playing with *C* from within *Torch*, taking for granted no prior knowledge of building `.so` libraries, using `Makefile` or tackling *Tensors* pointers.
11 |
12 | 1. [*FFI* and `.so` library](FFI-so/README.md)
13 | 2. [`Tensor`s through *FFI*](FFI-Tensor/README.md)
14 |
15 | ## Debugging
16 |
17 | If you found yourself using several `print()` and `io.read()` around the code with the purpose of finding out what's going on, well… there's a better and more efficient way: using a *debugger*.
18 | There are few alternatives, but we'll start with the easiest one: a command-line debugger.
19 |
20 | 1. [MobDebug](MobDebug/README.md) (command-line)
21 | 2. [GDB](GDB/README.md) (shared objects)
22 |
--------------------------------------------------------------------------------
|