Skip to content

Latest commit

 

History

History
89 lines (61 loc) · 4.46 KB

README.md

File metadata and controls

89 lines (61 loc) · 4.46 KB

FFI and .so library

Everything starts from the will of running a super awesome C library from within Torch. So, let's start step by step, with the writing of the C source code.

C source code

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.

void dummy(int* ptrFromLua, int size) {

  for (int i = 0; i < size; i++)
    ptrFromLua[i] = i + 1;

  return;

}

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. The source code is available at src/asdf.c.

make and .so compilation

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.

For compiling the source code shown above into a shared library we need to use gcc with several arguments. In order to simplify this procedure, a src/Makefile can be created instead, where all this information can be directly executed by typing the command make from within the src directory.

Compilation details

For the more curious of the readers, I'm going to briefly explain how the src/Makefile has been written.

LIBOPTS = -shared
CFLAGS = -fPIC -std=gnu99
CC = gcc

libasdf.so : asdf.c
	$(CC) $< $(LIBOPTS) $(CFLAGS) -o $@

clean :
	rm *.so

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.
Hence, typing make will build an -o output libasdf.so from the source code asdf.c.
If we would like to remove every file generated by make, we can simply issue make clean and it will do the trick.

Scripting in Lua

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.

-- FFI stuff -------------------------------------------------------------------
-- Require ffi
ffi = require("ffi")
-- Load myLib
myLib = ffi.load(paths.cwd() .. '/libasdf.so')
-- Function prototypes definition
ffi.cdef [[
   void dummy(int* ptr_form_lua, int size)
]]

-- Main program ----------------------------------------------------------------
length = 5
a = torch.IntTensor(length):random()
myLib.dummy(torch.data(a), length)

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.
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.

Motivations

Why is this stuff cool? Run the source code 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.

For the more lazy ones, I'll write here some conclusions myself.
By setting length to 1e7, i.e. 10 millions, and disabling the print() of the array on screen, I get the following output:

C function computation time 31.98 ms
Lua loop computation time 2890.92 ms

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.

Another reason about why you are loving this tutorial is that now you can use whatever compiled library — like some cool stuff from OpenCV, FFmpeg 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!