Commit df1b4f64 by Tianqi Chen Committed by GitHub

[IOS] Improve the iOS RPC with exclusive filesys lock (#981)

parent 91515322
...@@ -139,6 +139,7 @@ xcuserdata/ ...@@ -139,6 +139,7 @@ xcuserdata/
.DS_Store .DS_Store
tags tags
cscope* cscope*
*.lock
# vim temporary files # vim temporary files
*.swp *.swp
......
...@@ -59,7 +59,6 @@ def test_rpc_module(): ...@@ -59,7 +59,6 @@ def test_rpc_module():
# Start RPC test server that contains the compiled library. # Start RPC test server that contains the compiled library.
server = xcode.popen_test_rpc(proxy_host, proxy_port, key, server = xcode.popen_test_rpc(proxy_host, proxy_port, key,
destination=destination, destination=destination,
options=['-quiet'],
libs=[path_dso1, path_dso2]) libs=[path_dso1, path_dso2])
# connect to the proxy # connect to the proxy
......
...@@ -320,7 +320,7 @@ typedef void (*TVMPackedCFuncFinalizer)(void* resource_handle); ...@@ -320,7 +320,7 @@ typedef void (*TVMPackedCFuncFinalizer)(void* resource_handle);
* TVM call this function to get the extension functions * TVM call this function to get the extension functions
* The declarer will call register_func to register function and their name. * The declarer will call register_func to register function and their name.
* *
* \param resource_func_handle The register function * \param register_func_handle The register function
* \return 0 if success, -1 if failure happens * \return 0 if success, -1 if failure happens
*/ */
typedef int (*TVMExtensionFuncDeclarer)(TVMFunctionHandle register_func_handle); typedef int (*TVMExtensionFuncDeclarer)(TVMFunctionHandle register_func_handle);
......
...@@ -688,11 +688,10 @@ inline TVMType String2TVMType(std::string s) { ...@@ -688,11 +688,10 @@ inline TVMType String2TVMType(std::string s) {
LOG(FATAL) << "unknown type " << s; LOG(FATAL) << "unknown type " << s;
} }
char* xdelim; // emulate sscanf("%ux%u", bits, lanes) char* xdelim; // emulate sscanf("%ux%u", bits, lanes)
unsigned bits = strtoul(scan, &xdelim, 10); uint8_t bits = static_cast<uint8_t>(strtoul(scan, &xdelim, 10));
if (bits != 0) t.bits = static_cast<uint8_t>(bits); if (bits != 0) t.bits = bits;
if (*xdelim == 'x') { if (*xdelim == 'x') {
unsigned lanes = strtoul(xdelim + 1, nullptr, 10); t.lanes = static_cast<uint16_t>(strtoul(xdelim + 1, nullptr, 10));
t.lanes = static_cast<uint16_t>(lanes);
} }
return t; return t;
} }
......
...@@ -392,7 +392,7 @@ class Proxy(object): ...@@ -392,7 +392,7 @@ class Proxy(object):
port=9091, port=9091,
port_end=9199, port_end=9199,
web_port=0, web_port=0,
timeout_client=240, timeout_client=600,
timeout_server=600, timeout_server=600,
index_page=None, index_page=None,
resource_files=None): resource_files=None):
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from __future__ import absolute_import as _abs from __future__ import absolute_import as _abs
import os import os
import tempfile import tempfile
import fcntl
import shutil import shutil
class TempDirectory(object): class TempDirectory(object):
...@@ -38,7 +39,7 @@ class TempDirectory(object): ...@@ -38,7 +39,7 @@ class TempDirectory(object):
return os.path.join(self.temp_dir, name) return os.path.join(self.temp_dir, name)
def listdir(self): def listdir(self):
""""List contents in the dir. """List contents in the dir.
Returns Returns
------- -------
...@@ -47,6 +48,7 @@ class TempDirectory(object): ...@@ -47,6 +48,7 @@ class TempDirectory(object):
""" """
return os.listdir(self.temp_dir) return os.listdir(self.temp_dir)
def tempdir(): def tempdir():
"""Create temp dir which deletes the contents when exit. """Create temp dir which deletes the contents when exit.
...@@ -56,3 +58,38 @@ def tempdir(): ...@@ -56,3 +58,38 @@ def tempdir():
The temp directory object The temp directory object
""" """
return TempDirectory() return TempDirectory()
class FileLock(object):
"""File lock object
Parameters
----------
path : str
The path to the lock
"""
def __init__(self, path):
self.lock_file = open(path, "w")
fcntl.lockf(self.lock_file, fcntl.LOCK_EX)
def release(self):
"""Release the lock"""
if self.lock_file:
fcntl.lockf(self.lock_file, fcntl.LOCK_UN)
self.lock_file.close()
self.lock_file = None
def filelock(path):
"""Create a file lock which locks on path
Parameters
----------
path : str
The path to the lock
Returns
-------
lock : File lock object
"""
return FileLock(path)
...@@ -146,6 +146,28 @@ def compile_metal(code, path_target=None, sdk="macosx"): ...@@ -146,6 +146,28 @@ def compile_metal(code, path_target=None, sdk="macosx"):
return libbin return libbin
class XCodeRPCServer(object):
"""Wrapper for RPC server
Parameters
----------
cmd : list of str
The command to run
lock: FileLock
Lock on the path
"""
def __init__(self, cmd, lock):
self.proc = subprocess.Popen(cmd)
self.lock = lock
def join(self):
"""Wait server to finish and release its resource
"""
self.proc.wait()
self.lock.release()
def popen_test_rpc(host, def popen_test_rpc(host,
port, port,
key, key,
...@@ -190,6 +212,10 @@ def popen_test_rpc(host, ...@@ -190,6 +212,10 @@ def popen_test_rpc(host,
if not os.path.exists(proj_path): if not os.path.exists(proj_path):
raise RuntimeError("Cannot find tvmrpc.xcodeproj in %s," + raise RuntimeError("Cannot find tvmrpc.xcodeproj in %s," +
(" please set env TVM_IOS_RPC_ROOT correctly" % rpc_root)) (" please set env TVM_IOS_RPC_ROOT correctly" % rpc_root))
# Lock the path so only one file can run
lock = util.filelock(os.path.join(rpc_root, "ios_rpc.lock"))
with open(os.path.join(rpc_root, "rpc_config.txt"), "w") as fo: with open(os.path.join(rpc_root, "rpc_config.txt"), "w") as fo:
fo.write("%s %d %s\n" % (host, port, key)) fo.write("%s %d %s\n" % (host, port, key))
libs = libs if libs else [] libs = libs if libs else []
...@@ -203,11 +229,5 @@ def popen_test_rpc(host, ...@@ -203,11 +229,5 @@ def popen_test_rpc(host,
if options: if options:
cmd += options cmd += options
cmd += ["test"] cmd += ["test"]
if "-quiet" in options:
with open(os.devnull, 'w') as devnull: return XCodeRPCServer(cmd, lock)
proc = subprocess.Popen(cmd,
stderr=subprocess.STDOUT,
stdout=devnull)
else:
proc = subprocess.Popen(cmd)
return proc
...@@ -57,7 +57,7 @@ class GraphRuntime : public ModuleNode { ...@@ -57,7 +57,7 @@ class GraphRuntime : public ModuleNode {
} }
/*! /*!
* \brief Initialize the graph executor with graph and context. * \brief Initialize the graph executor with graph and context.
* \param graph The execution graph. * \param graph_json The execution graph.
* \param module The module containing the compiled functions. * \param module The module containing the compiled functions.
* \param ctx The context where the graph should sit on * \param ctx The context where the graph should sit on
*/ */
...@@ -94,7 +94,7 @@ class GraphRuntime : public ModuleNode { ...@@ -94,7 +94,7 @@ class GraphRuntime : public ModuleNode {
/*! /*!
* \brief set index-th input to the graph. * \brief set index-th input to the graph.
* \param index The input index. * \param index The input index.
* \param data The input data. * \param data_in The input data.
*/ */
void SetInput(int index, DLTensor* data_in) { void SetInput(int index, DLTensor* data_in) {
CHECK_LT(static_cast<size_t>(index), input_nodes_.size()); CHECK_LT(static_cast<size_t>(index), input_nodes_.size());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment