News for hackers. Stuff that matters.
Re:Speeding up function calls with lru_cache in Python by Denvercoder9 on Sunday June 28, 2020 @11:04AM (#23669191)
Caching the result is not speeding up function calls.
Re:Speeding up function calls with lru_cache in Python by adrianmonk on Sunday June 28, 2020 @11:28AM (#23669394)
One way to optimize performance is to change program text from one thing into something else. In this case, "function calls" refers to the text before the transformation is applied.

It seems reasonable to me to describe an optimization by identifying where it can be applied. If someone wrote a blog post titled "optimizing multiplication by 2" and went on to describe changing "x * 2" into "x + x", there would be nothing unusual about that. It would no longer be multiplication, but we wouldn't necessarily expect it to be.

I agree it can be interpreted another way in this case, though. So while I maintain it is not wrong, I admit it is ambiguous. Someone could have used the same title had they written about a one-line optimization to the Python interpreter.

Re:Speeding up function calls with lru_cache in Python by jhrmnn on Sunday June 28, 2020 @11:18AM (#23669300)
It is, though. It doesn’t speed up function execution, but it literally speeds up the function call.
Re:Speeding up function calls with lru_cache in Python by Denvercoder9 on Sunday June 28, 2020 @11:33AM (#23669447)
It only speeds up calls to pure (side-effect free) functions, that have been executed before with these exact parameters and where the result is still cached. All other calls get slower.

Also, there's an argument to be made that "function call" is the overhead involved in moving control from the call site to the callee (which can be significant in interpreted languages such as Python). That's at least how I interpreted it at first.

Re:Speeding up function calls with lru_cache in Python by empath75 on Sunday June 28, 2020 @12:25PM (#23669873)
It speeds up recursive functions that haven’t been called before with the same arguments. In this case, it caches all the intermediate results that would otherwise have to be recalculated.
Re:Speeding up function calls with lru_cache in Python by OskarS on Sunday June 28, 2020 @02:31PM (#23670947)
No, you have to be more specific than "recursive functions", many recursive functions will see no such benefit. A simple example is factorial function: adding @lru_cache to that will only slow it down.

This technique ("memoization") is a technique from dynamic programming, and it only works on very particular types of functions. The two criteria are:

* Optimal substructure: the function has to be a recursive function that can be solved by solving "smaller" versions of the same function (this is roughly what people mean when they say a function can be solved "recursively")

* Overlapping subproblems: the smaller sub-problems have to overlap, so that memoizing them actually introduces a benefit. For instance, in order to calculate F(10) (F(n) being the Fibonacci sequence), you have to calculate F(9) and F(8), and in order to calculate F(9), you have to calculate F(8) and F(7). That means that F(10)'s subproblems overlap with F(9)'s (both require F(8)).

For the factorial function, the first is true, the second is not. There are no overlapping subproblems for calculating the factorial, so memoizing the function in order to speed it up is pointless.

This is a very particular kind of problem. It's a type of problem you learn about in computer science class, have to face in terrible developer job interviews, and find all over the place on Project Euler. It's is very rare that you actually encounter it in the wild. Giving the advice "@lru_cache speeds up functions!" is misguided: it only speeds up a very particular kind of function. It slows down basically all other pure functions. Also: if you've identified a problem of this kind, memoization is not the fastest way to solve it: turning the recursion upside-down and iterating usually is.

The real use-case for @lru_cache, IMHO, is to use it as an actual cache: like, caching database entries or other data you'd need to do I/O to fetch. That is a much more reasonable use case.

Re:Speeding up function calls with lru_cache in Python by gtm1260 on Sunday June 28, 2020 @01:46PM (#23670556)
I agree, I think of function call as the time it takes to copy the stack frame, setup variables, and move the program counter. I'm not sure that adding a decorator slows this down, but I suspect it does. A better title would just be 'add memoization in one line in python' or something.
Re:Speeding up function calls with lru_cache in Python by kevin_thibedeau on Sunday June 28, 2020 @11:29AM (#23669405)
It speeds up algorithms that are amenable to memoization.
Re:Speeding up function calls with lru_cache in Python by Immortal333 on Sunday June 28, 2020 @11:14AM (#23669271)
Author here. Sorry, If it feels misleading. I have no intention to mislead anybody. If you can suggest alternative title, I am happy to change title.
Re:Speeding up function calls with lru_cache in Python by shankysingh on Sunday June 28, 2020 @11:18AM (#23669301)
Thanks for article

Just a side note: with Fibonacci + caching it solidly become Dynamic programming problem so Time complexity reduces from quadratic to o(n), IIRC .

There is a whole class of problems where recursion + memoization(caching) = Top Down Dynamic programming , The other way to Increase performance and actually reduce call stack in these class of problems including Fibonacci would be Bottom Up Dynamic Programming

Some gists I found on it https://gist.github.com/trtg/4662449

Re:Speeding up function calls with lru_cache in Python by akdas on Sunday June 28, 2020 @02:56PM (#23671131)
Plugging my own writing, but I did a deep dive on top-down vs. bottom-up dynamic programming on my blog: https://avikdas.com/2019/04/15/a-graphical-introduction-to-d...

The follow-up posts go into even more detail on individual problems that can be solved using either form of dynamic programming, including some real-world problems like content-aware image resizing.

Re:Speeding up function calls with lru_cache in Python by eindiran on Sunday June 28, 2020 @06:47PM (#23672676)
Thank you for the link, I enjoyed the post a lot. The drawings you've done add a lot to the explanation. Do you have any other deep dives you've done in the same style that you'd recommend?
Re:Speeding up function calls with lru_cache in Python by akdas on Monday June 29, 2020 @12:48AM (#23674438)
Thanks! I'm glad the drawings were helpful.

Most of my writing can be found at my blog (https://avikdas.com/), but here are some from the same dynamic programming series:

- Deep-dive into the Chain Matrix Multiplication Problem - https://avikdas.com/2019/04/25/dynamic-programming-deep-dive... - Real-world applications of DP: https://avikdas.com/2019/05/14/real-world-dynamic-programmin... and https://avikdas.com/2019/07/29/improved-seam-carving-with-fo... - Another real-world application, this time in machine learning - https://avikdas.com/2019/06/24/dynamic-programming-for-machi...

If you look on my blog, you'll also see my recent series is on scalability, things like read-after-write consistency and queues for reliability.

Re:Speeding up function calls with lru_cache in Python by Immortal333 on Sunday June 28, 2020 @11:23AM (#23669343)
Yes, I have mentioned DP in my article as just reference. The Purpose of article was to show that how easy it is to implement caching in python using lru_cache decorator which is in std lib. So, We don't have to install any 3rd party lib.
Re:Speeding up function calls with lru_cache in Python by shankysingh on Sunday June 28, 2020 @11:26AM (#23669376)
oh sorry , somehow I missed it :)
Re:Speeding up function calls with lru_cache in Python by anandoza on Sunday June 28, 2020 @12:18PM (#23669808)
the simple recursive solution is actually O(fib(n)), which is exponential
Re:Speeding up function calls with lru_cache in Python by Denvercoder9 on Sunday June 28, 2020 @11:36AM (#23669475)
I'd suggest something along the lines of "Speeding up functions [in Python] by caching results" :)
Re:Speeding up function calls with lru_cache in Python by fwip on Sunday June 28, 2020 @12:31PM (#23669920)
"python memoization in one line"

Edit: I don't actually have much of a problem with the article headline as it is now. It depends a lot on your target audience! For Hacker News, yeah, we know what memoization is because we learned it in CS 102, right after we learned about recursion.

But for a lot of people who would get the most value from the article, the word "memoization" isn't going to mean much, and wouldn't read the article.

Maybe something like: "Memoization in Python, or how I learned to speed up function calls in just one line"