| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
The difference is that func(arg) can now be called with the same arg multiple times in parallel, no? |
Sorry, something went wrong.
Yes, and it behaves the same way as before free-threading - it can get into the same function with the same args multiple times if the calls arrive roughly at the same time. |
Sorry, something went wrong.
+1 in principle. The C version should be at least as good as the pure python version. In practice, this is tricky to get right. @colesbury This PR modifies you previous work. Do you want to take a look at it? @serhiy-storchaka This is mostly your C code. Do you want to look this over? @tom-pytel I suggest looking at the pure python version in /Lib/functools.py to verify that the C version handles all of the cases listed in the comments. In particular, look at the one that starts with "Getting here means that this same key was added to the cache while the lock was released." The wrapped function can reenter the cache, clear the cache, add to the cache, age out old keys, or be recursive. |
Sorry, something went wrong.
There was a problem hiding this comment.
How safe is to execute self->hits++ or self->misses++ without critical section?
Sorry, something went wrong.
In infinite_lru_cache_wrapper you mean, good catch, can change to atomics. |
Sorry, something went wrong.
|
And in uncached_lru_cache_wrapper. |
Sorry, something went wrong.
Also _functools__lru_cache_wrapper_cache_info_impl and _functools__lru_cache_wrapper_cache_clear_impl as they may be called on the uncached or infinite non-critical wrappers. The atomics in bounded_lru_cache_get_lock_held are unnecessary I just realized so will remove. |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM.
Sorry, something went wrong.
|
Also, can you share bench_lrucache.py? |
Sorry, something went wrong.
Its in the header of this PR. |
Sorry, something went wrong.
I double checked all these cases as you suggested and its fine. Which makes sense since all this PR really amounts to is releasing the lock on the call to the function, no other behavior is changed. |
Sorry, something went wrong.
There was a problem hiding this comment.
I'm a little late to the party, but this looks pretty good.
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM as well, thanks for doing this.
Sorry, something went wrong.
There was a problem hiding this comment.
Do not overdo this. If is a simple macro to make the code in that file clearer. We do not need a return value. Other similar macros do not use inline functions. If we need that macro in other places, we can update the implementation.
I suggested to implement a simple increment. value++ returns an old value, if this is important.
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM
Sorry, something went wrong.
|
Merged, thank you for this new optimization. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
This PR changes functools.lru_cache to only hold critical sections when it is performing operations on itself and not when it calls the wrapped function being cached.
Example script timing, current code:
This PR:
Explanation: The script is 16 threads doing a long operation. In the current code they run sequentially because they are serialized by lru_cache. In this PR they are allowed to run concurrently.
Script:
import threading from functools import lru_cache from time import time @lru_cache def func(v): for i in range(100000000): pass return v threads = [threading.Thread(target=func, args=(i,)) for i in range(16)] t0 = time() for thread in threads: thread.start() for thread in threads: thread.join() print(f'Time: {time() - t0:0.1f}s')More detail: There are three caching functions that can be used, currently they all execute locked (and by extension the function being cached):
NOTE: This can be reduced to a single critical section if the locked function is only ever called in its owner thread, but not sure is necessary and wanted to keep things simple for this PR.