提交 acf5e176 authored 作者: Arnaud Bergeron's avatar Arnaud Bergeron

Add configuration variables for the compile lock times.

上级 cc703505
...@@ -9,6 +9,7 @@ import time ...@@ -9,6 +9,7 @@ import time
import logging import logging
from theano import config from theano import config
from theano.configparser import AddConfigVar, IntParam
_logger = logging.getLogger("theano.gof.compilelock") _logger = logging.getLogger("theano.gof.compilelock")
# If the user provided a logging level, we don't want to override it. # If the user provided a logging level, we don't want to override it.
...@@ -16,31 +17,28 @@ if _logger.level == logging.NOTSET: ...@@ -16,31 +17,28 @@ if _logger.level == logging.NOTSET:
# INFO will show the the messages "Refreshing lock" message # INFO will show the the messages "Refreshing lock" message
_logger.setLevel(logging.INFO) _logger.setLevel(logging.INFO)
# In seconds, time that a process will wait before deciding to override an AddConfigVar('compile.wait',
# existing lock. An override only happens when the existing lock is held by """Time to wait before retrying to aquire the compile lock. If you
# the same owner *and* has not been 'refreshed' by this owner for more than raise this be sure to also raise 'compile.timeout' by a proportionate
# 'timeout_before_override' seconds. amount.""",
timeout_before_override = 120 IntParam(5, lambda i: i > 0, allow_override=False),
in_c_key=False)
# In seconds, duration before a lock is refreshed. More precisely, the lock is AddConfigVar('compile.timeout',
# refreshed each time 'get_lock()' is called (typically for each file being """In seconds, time that a process will wait before deciding to
# compiled) and the existing lock has not been refreshed in the past override an existing lock. An override only happens when the existing
# 'refresh_every' seconds. lock is held by the same owner *and* has not been 'refreshed' by this
refresh_every = 60 owner for more than this period.""",
IntParam(120, lambda i: i >= 0, allow_override=False),
in_c_key=False)
def force_unlock(): def force_unlock():
""" """
Delete the compilation lock if someone else has it. Delete the compilation lock if someone else has it.
""" """
global timeout_before_override get_lock(min_wait=0, max_wait=0.001, timeout=0)
timeout_backup = timeout_before_override
timeout_before_override = 0
try:
get_lock(min_wait=0, max_wait=0.001)
release_lock() release_lock()
finally:
timeout_before_override = timeout_backup
def get_lock(lock_dir=None, **kw): def get_lock(lock_dir=None, **kw):
...@@ -74,16 +72,17 @@ def get_lock(lock_dir=None, **kw): ...@@ -74,16 +72,17 @@ def get_lock(lock_dir=None, **kw):
if get_lock.lock_is_enabled: if get_lock.lock_is_enabled:
# Only really try to acquire the lock if we do not have it already. # Only really try to acquire the lock if we do not have it already.
if get_lock.n_lock == 0: if get_lock.n_lock == 0:
lock(get_lock.lock_dir, timeout=timeout_before_override, **kw) lock(get_lock.lock_dir, **kw)
atexit.register(Unlocker.unlock, get_lock.unlocker) atexit.register(Unlocker.unlock, get_lock.unlocker)
# Store time at which the lock was set. # Store time at which the lock was set.
get_lock.start_time = time.time() get_lock.start_time = time.time()
else: else:
# Check whether we need to 'refresh' the lock. We do this every # Check whether we need to 'refresh' the lock. We do this
# 'refresh_every' seconds to ensure noone else tries to override # every 'config.compile.timeout / 2' seconds to ensure
# our lock after their 'timeout_before_override' timeout period. # noone else tries to override our lock after their
# 'config.compile.timeout' timeout period.
now = time.time() now = time.time()
if now - get_lock.start_time > refresh_every: if now - get_lock.start_time > config.compile.timeout/2:
lockpath = os.path.join(get_lock.lock_dir, 'lock') lockpath = os.path.join(get_lock.lock_dir, 'lock')
_logger.info('Refreshing lock %s', str(lockpath)) _logger.info('Refreshing lock %s', str(lockpath))
refresh_lock(lockpath) refresh_lock(lockpath)
...@@ -114,8 +113,10 @@ def set_lock_status(use_lock): ...@@ -114,8 +113,10 @@ def set_lock_status(use_lock):
""" """
get_lock.lock_is_enabled = use_lock get_lock.lock_is_enabled = use_lock
# This is because None is a valid input for timeout
notset = object()
def lock(tmp_dir, timeout=120, min_wait=5, max_wait=10, verbosity=1): def lock(tmp_dir, timeout=notset, min_wait=None, max_wait=None, verbosity=1):
""" """
Obtain lock access by creating a given temporary directory (whose base will Obtain lock access by creating a given temporary directory (whose base will
be created if needed, but will not be deleted after the lock is removed). be created if needed, but will not be deleted after the lock is removed).
...@@ -149,6 +150,12 @@ def lock(tmp_dir, timeout=120, min_wait=5, max_wait=10, verbosity=1): ...@@ -149,6 +150,12 @@ def lock(tmp_dir, timeout=120, min_wait=5, max_wait=10, verbosity=1):
@param verbosity: amount of feedback displayed to screen @param verbosity: amount of feedback displayed to screen
@type verbosity: int @type verbosity: int
""" """
if min_wait is None:
min_wait = config.compile.wait
if max_wait is None:
max_wait = min_wait * 2
if timeout is notset:
timeout = config.compile.timeout
# Create base of lock directory if required. # Create base of lock directory if required.
base_lock = os.path.dirname(tmp_dir) base_lock = os.path.dirname(tmp_dir)
if not os.path.isdir(base_lock): if not os.path.isdir(base_lock):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论