Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Latest commit

 

History

History
55 lines (44 loc) · 2.3 KB

map.md

File metadata and controls

55 lines (44 loc) · 2.3 KB

ipc.map

local map = ipc.map(nThread, threadFunc, [...])

Maps a Lua function onto a set of nThread threads. The threadFunc function is run in an entirely new and clean Lua environment. The optional variable length arguments ... are passed to the function: threadFunc(...).

No upvalues of the function are marshaled into the thread. Torch Tensor and Storage objects are shared across the thread boundary, no copies are made. That said, we also do not provide thread safe access to those Tensors. It is up to the programmer to implement their own lockless system.

You can pass as many arguments as you wish to the function and the function can return as many values as it wants.

local ipc = require 'libipc'
local m = ipc.map(2, function(a, b, c, threadId)
   -- the last argument passed to the function is the ID of the thread
   assert((threadId == 1) or (threadId == 2))
   return math.sqrt(a*a + b*b + c*c), "hi"
end, 1, 2, 3)
local p1,s1,p2,s2 = m:join()
print(p1) -- will print 3.7416573867739
print(s1) -- will print "hi"
print(p2) -- will print 3.7416573867739
print(s2) -- will print "hi"

Note how an additional hidden argument is passed to the mapped function: threadId. This threadId is a number identifying the thread (from 1 to nThread). It is always passed as the last argument to the function.

Similar to posix threads, when you want to wait for all the child threads to end and get their return values you must call :join(). If any child threads had errors these will bubble up via a call to :join(). You can wrap this in a pcall if you think the error is recoverable (generally, it is not).

At any point the parent thread can check if any of the child threads have died. The :checkErrors() function will bubble up an errors. You can wrap this in a pcall if you think the error is recoverable (generally, it is not).

Note that ipc.map() will throw an error when attempting to serialize closures/upvalues. However ipc.workqueue provides :writeup() for serializing closures/upvalues.

Most often ipc.map is combined with an ipc.workqueue in order to distribute work across the threads. A more concrete example of combining ipc.map and ipc.workqueue can be found in ipc.BackgroundTask