torch/torch7 — pull request #18 by timharley (2014-03-17 12:01:45+00:00)
Title: Make luaT_classmodulename, THError & THArgCheck threadsafe

These commits, once combined with the THGenerator pull request, make torch threadsafe.

It breaks the luaT API to return a string in a nice manner. I will patch the docs if noone objects to this.

Here is the test I used, using the handy [luall_threads](https://github.com/Neopallium/lua-llthreads):

Without the relevant patches, you get a segfault.
Combing this branch with the THGenerator pull request, it doesn't segfault and gives identical results in all threads.

```
local llthreads = require "llthreads"

function thread_func(...)
-- print thread's parameter.
print("CHILD: received params:", ...)

-- Do the requires here, to check luaT_classmodulename
require 'torch'
require 'nn'

-- Generate a few thousand THErrors.
for i = 1,10000 do
local ok = pcall( function ()
local unused = torch.Tensor(5)[torch.ByteTensor(6)]
end)
end

-- Generate a few thousand THArgErrors.
for i = 1,10000 do
local ok = pcall( function ()
local unused = torch.random(torch.Tensor(5),1,-2)
end)
end

torch.manualSeed(1)

-- Stress the random number generator
local mean = torch.randn(1000000):add(100):mean()
local m

for i=1,1000 do
local x= torch.rand(1000)
local go = torch.rand(10)
m = nn.Sequential():add(nn.Linear(1000,100)):add(nn.Tanh()):add(nn.Linear(100,10))
m:forward(x)
m:backward(x,go)
collectgarbage()
end
return {mean,m.gradInput:abs():sum()}
end

local main_thread_results = thread_func()
local expectedMean, expectedGradInputSum = main_thread_results[1], main_thread_results[2]

local nChildren = 12
local children = {}
for i = 1, nChildren do
local child = llthreads.new(string.dump(thread_func), "number:", 1234, "nil:", nil, "bool:", true)
assert(child:start())
children[i] = child
end

local results = {}
for i, child in ipairs(children) do
local result = {child:join()}
results[i] = result
print("PARENT: child returned: ", result[1],unpack(result[2]))
end

for i, result in ipairs(results) do
assert(results[i][1] == true, "expecting success")
assert(results[i][2][1] == expectedMean,
string.format("wrong result: %s ~= %s", results[i][2][1], expectedMean))
assert(results[i][2][2] == expectedGradInputSum,
string.format("wrong result: %s ~= %s", results[i][2][2], expectedGradInputSum))
end
```