Re: Annotating pure functions to improve inline caching/optimization
"Eric V. Smith via Python-Dev" <[email protected]> Wed, 14 Sep 2022 17:59:02 -0400
| Newsgroups | gmane.comp.python.devel |
|---|---|
| Message-ID | <[email protected]> |
You should bring this up on discuss.python.org. It's not going to see much if any discussion here. Eric On 9/14/2022 10:05 AM, Philipp Burch wrote: > Hello everyone, > > the docs on the upcoming 3.11 release state > > > This [specializing adaptive interpreter] also brings in another > concept called inline caching, where Python caches the results of > expensive operations directly in the bytecode. > > I wonder how this caching works, given that the dynamic nature means > that virtually every operation could have side effects, causing wrong > behaviour when cached. The only mitigation for this that I can imagine > is that caching just occurs for basic operations defined in the > standard library, where it is known that they are free of side effects > or "pure". > > A web search did reveal some discussions[1,2] and a module related to > dealing with pure functions, but, as far as I see, not related to > optimization. > > As an example, consider a code like this: > > ```py > @pure > def rot_factor(angle_deg: float) -> complex: > # This could also be a much more expensive calculation. > return cmath.exp(angle_deg / 180 * cmath.pi * 1j) > > # ... > > res: List[Tuple(complex, complex, complex, float)] = [] > for x in many: > res.append(( > x * rot_factor(90), > x * rot_factor(45), > x * rot_factor(-45), > x * math.sin(math.pi/8), > )) > ``` > > The problem with this code is obvious, every loop iteration calls > `rot_factor()` with 90, 45 and -45 and will get exactly the same set > of results. The last factor might already be inline cached by the > interpreter, since it probably knows that `math.pi` is a constant and > `math.sin()` is a pure function. Optimizing this by hand (not > considering a list comprehension or other more sophisticated > improvements) is easy, but not very pretty: > > ```py > f_p90 = rot_factor(90) > f_p45 = rot_factor(45) > f_m45 = rot_factor(-45) > f_sin = math.sin(math.pi / 8) > res: List[Tuple(complex, complex, complex, float)] = [] > for x in many: > res.append(( > x * f_p90, > x * f_p45, > x * f_m45, > x * f_sin, > )) > ``` > > I actually find myself often factoring such data out of loops in > Python, whereas in C I would just leave that to the optimizer/compiler. > > An available option would be to use `@lru_cache` for `rot_factor()`, > but this will still cause the same dictionary lookups in every > iteration and it may not work at all in case the function argument(s) > is/are not hashable. > > Now, if the interpreter understood the `@pure` decorator for > `rot_factor()` indicated above would give it the same opportunity to > cache the three results throughout the loop, basically creating the > manually-optimized code above. For these completely static values, it > could even precompute the results and integrate them into the bytecode. > > > Has anything like this been considered already, or is the interpreter > itself capable to perform such optimizations? > > > Thanks and best regards, > Philipp > > > > [1] 'pure' type annotation for mypy: > https://github.com/python/mypy/issues/4468 > > [2] pure-func module: https://pypi.org/project/pure-func/ > _______________________________________________ > Python-Dev mailing list -- [email protected] > To unsubscribe send an email to [email protected] > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/[email protected]/message/XDYZRC6L7LBPE3T6RO6S5IVY3J6IMRSJ/ > Code of Conduct: http://python.org/psf/codeofconduct/ _______________________________________________ Python-Dev mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/[email protected]/message/A5CATJEKKNZN4XOWXVJ2ICK2Z4A3WFYU/ Code of Conduct: http://python.org/psf/codeofconduct/