├── .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 | [![Join the chat at https://gitter.im/Atcold/Torch-Developer-Guide](https://badges.gitter.im/Join%20Chat.svg)](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 | --------------------------------------------------------------------------------