├── LICENSE ├── README.md ├── test.lua ├── torch_interface.jl ├── torch_server.lua └── unit_tests.jl /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tejas Kulkarni 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Julia-Torch Summary 2 | Interface between Julia and Torch (Lua) using ZMQ. 3 | 4 | ### Description 5 | This module can be used to call torch functions from Julia. Currently the return values are restricted to be 1-D arrays but this can be easily changed in torch_server. Most importantly, since the torch server loads lua scripts, lua variables are persistent across multiple API calls. This is useful for instance when loading neural network models in torch once and asking it to return feature vectors across multiple batches. 6 | 7 | ### Usage 8 | 1. Start the torch ZMQ server by typing: 9 | ```lua 10 | th torch_server.lua 11 | OR 12 | luajit torch_server.lua 13 | ``` 14 | 2. In your julia script, torch functions can now be accessed by: 15 | ```Julia 16 | include("torch_interface.jl") 17 | using TORCH 18 | ``` 19 | ```Julia 20 | #include all the required torch external scripts needed 21 | script_names = 'test.lua' 22 | TORCH.load_torch_script(script_names) 23 | ``` 24 | ```Julia 25 | #Call any function within scope of torch 26 | func = "get_samples" 27 | args = 1 28 | TORCH.call(func, args) 29 | ``` 30 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | --test script 2 | require('sys') 3 | function testdraw() 4 | sys.tic() 5 | ret = torch.rand(4) 6 | print(sys.toc()) 7 | return ret 8 | end 9 | 10 | samples = testdraw() 11 | 12 | function get_samples(index) 13 | return samples[index] 14 | end -------------------------------------------------------------------------------- /torch_interface.jl: -------------------------------------------------------------------------------- 1 | #Torch interface from Julia 2 | 3 | module TORCH 4 | using JSON 5 | using ZMQ 6 | 7 | ctx=Context(1) 8 | s1=Socket(ctx, REQ) 9 | 10 | export load_torch_script 11 | export call 12 | export close 13 | 14 | PORT = 7000 15 | 16 | function load_torch_script(script_name) 17 | ZMQ.connect(s1, string("tcp://localhost:", PORT)) 18 | CMD = string("{\"cmd\":\"load\", \"name\":\"", script_name ,"\"}") 19 | ZMQ.send(s1,Message(CMD)) 20 | msg = ZMQ.recv(s1) 21 | out=convert(IOStream, msg) 22 | seek(out,0) 23 | msg = takebuf_string(out) 24 | msg = JSON.parse(msg) 25 | return msg 26 | end 27 | 28 | function call(func, args) 29 | # ZMQ.connect(s1, string("tcp://localhost:", PORT)) 30 | CMD = string("{\"cmd\":\"call\",", "\"msg\":{" ,"\"func\":\"", func , "\",\"args\":\"", args, "\"}}") 31 | ZMQ.send(s1,Message(CMD)) 32 | msg = ZMQ.recv(s1) 33 | out=convert(IOStream, msg) 34 | seek(out,0) 35 | msg = takebuf_string(out) 36 | msg = JSON.parse(msg) 37 | return msg 38 | end 39 | 40 | function close() 41 | ZMQ.close(sock) 42 | ZMQ.close(ctx) 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /torch_server.lua: -------------------------------------------------------------------------------- 1 | -- Torch interface to Julia (server) 2 | local json = require ("dkjson") 3 | local zmq = require "lzmq" 4 | local context = zmq.init(1) 5 | 6 | local socket = context:socket(zmq.REP) 7 | socket:bind("tcp://*:7000") 8 | 9 | function serialize(data) 10 | if torch.type(1) == torch.type(data) then 11 | return {data} 12 | end 13 | --for now it assumes data is a 1-D array 14 | local ret = {} 15 | for i=1,data:size(1) do 16 | ret[i] = data[i] 17 | end 18 | return ret 19 | end 20 | 21 | while true do 22 | -- Wait for next request from client 23 | local request = socket:recv() 24 | -- print("Received Hello [" .. request .. "]") 25 | -- print(request) 26 | if request ~= nil then 27 | request = json.decode(request, 1, nil) 28 | -- print('req:',request, ' | cmd:', request.cmd) 29 | if request.cmd == "load" then 30 | require(request.name) 31 | ret = {1} 32 | ret = json.encode (ret, { indent = true }) 33 | socket:send(ret) 34 | elseif request.cmd == "call" then 35 | func_name = request.msg.func 36 | args = request.msg.args 37 | ret = _G[func_name](args) 38 | -- ret = torch.rand(10):float() 39 | ret = serialize(ret) 40 | ret = json.encode (ret,{ indent = true }) 41 | socket:send(ret) 42 | end 43 | end 44 | end 45 | -- We never get here but if we did, this would be how we end 46 | socket:close() 47 | context:term() 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /unit_tests.jl: -------------------------------------------------------------------------------- 1 | #Picture : Unit tests 2 | include("torch_interface.jl") 3 | using TORCH 4 | TORCH.load_torch_script("test.lua") 5 | TORCH.call("get_samples", 1) --------------------------------------------------------------------------------