-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(utility): add lock for cached file between processes #1151
fix(utility): add lock for cached file between processes #1151
Conversation
Pull Request Test Coverage Report for Build 1627169800
💛 - Coveralls |
tensorbay/utility/common.py
Outdated
def wrapper(self: Any, *arg: Any, **kwargs: Any) -> None: | ||
key = getattr(self, attr_name) if attr_name else id(self) | ||
# https://github.com/PyCQA/pylint/issues/3313 | ||
lock = process_locks.setdefault(key, manager.Lock()) # pylint: disable=no-member |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get item from a Manager.dict() seems a copy behavior, which means the gotten lock is a copy of the lock in the dict. That means the operation in the outside lock will not affect the inside lock?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shared objects are capable of being nested. The manager.Lock()
is also a shared object, thus the change will be synced to the dict.
https://docs.python.org/3.8/library/multiprocessing.html#multiprocessing.managers.SyncManager
3d38af0
to
2490402
Compare
2490402
to
b50bae0
Compare
1858cae
to
3a07341
Compare
1a95b3f
to
ba54946
Compare
tensorbay/utility/common.py
Outdated
def wrapper(func_self: Any, *arg: Any, **kwargs: Any) -> None: | ||
key = getattr(func_self, self._attr_name) | ||
lock_exists = False | ||
if key in self.process_locks: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will it possible that two processes go into this if
statement at the same time, and two processes both return false, which makes them both create their own locks?
ba54946
to
8fb8259
Compare
tensorbay/utility/common.py
Outdated
# https://github.com/PyCQA/pylint/issues/3313 | ||
self.process_locks[key] = self._manager.Lock() # pylint: disable=no-member | ||
with _acquire(self.process_locks[key]) as success: | ||
self._lock.release() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there are something wrong happens before releasing the self._lock
, will it cause self._lock
never release?
self._lock.release() | ||
if success and not lock_exists: | ||
func(func_self, *arg, **kwargs) | ||
del self.process_locks[key] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It that possible one process is deleting the lock from self.process_locks
, and at the same time another process is checking whether the key in the self.process_locks
?
8fb8259
to
12a54d7
Compare
12a54d7
to
a7b26ef
Compare
a7b26ef
to
7797a2d
Compare
When using PyTorch dataloader with multiple workers, the cache file will be accessed by different processes. And the cache file can be written and read at the same time, which would lead to the read content being empty. Thus, use a temp filename while writing the cache file and then change it to the cache path. And add a lock to avoid repeatedly writing cache. PR Closed: Graviti-AI#1151
7797a2d
to
abb7b9c
Compare
When using PyTorch dataloader with multiple workers, the cache file will
be accessed by different processes. And the cache file can be written
and read at the same time, which would lead to the read content being
empty.
Thus, use a temp filename while writing the cache file and then change
it to the cache path. And add a lock to avoid repeatedly writing cache.