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
Memory leaks with LP Solvers are back #17320
Comments
comment:3
When I try to replicate Simon's memory object analysis, I do not find a significant leak:
As you can see, the garbage collector does not get triggered during the loop (indicating that reference counting is sufficient to keep the number of python objects bounded in memory during the loop). Also, after the loop there are no alarming objects in "post". I can confirm that memory usage explodes, but I think this indicates the memory leak is outside of python managed memory. [The problem with Simon's code might be that he doesn't update the set |
comment:4
The following is fishy in
If deleting Indeed, I've tried and simply inserting
makes memory consumption constant with the given test. I haven't tested if it affects operations otherwise. Responsible ticket seems to be #12220, where
which seems to suggest that unceremoniously deleting a model is just fine. Incidentally, that routine can leak too, because there are a whole bunch of "raise" statements in (*) that can lead to This suggests that the whole statement here should be guarded by some |
Commit: |
comment:6
something like this should do the trick. Feel free to amend as needed. New commits:
|
comment:7
Hello ! I do not understand why you put all this in a "try" block. Wouldn't it be easier to just set Nathann |
comment:8
Replying to @nathanncohen:
Quite possibly, but that's not how that code was written and I wasn't planning on delving into the program logic. There's a "new ..." there and there are uncontrolled exits via explicit raises and quite possibly by other code that can generate errors. If the new model gets inserted into self.model there's no leak because the old value of self.model gets properly deleted, but all the error condition exits would lead to an allocated "model" that simply falls out of scope, i.e., a memory leak (unless cython generates an implicit try/finally to cleanly delete any local variables that point to C++ objects--it doesn't, otherwise the original code wouldn't have worked properly). I just expressed it as a try/finally to ensure we always have a chance to see if "model" needs to be deleted. I'm sure there are other solutions. |
comment:9
Hello ! It seems that only moving the "del" above was sufficient. I created a branch at public/17320 that does that, tell me what you think ! Nathann |
comment:10
Dear Nathann, ok, seems to fix the leak issue. Is there a similar easy fix for the gurobi backend? Best wishes, Peter |
comment:11
Helloooooooo !
No idea, I don't have a gurobi license anymore. Their making them computer-dependent complicates stuff a lot. Nathann |
comment:12
Nathann, what do you mean? On whichever machine I use gurobi, it is a matter of a few seconds to receive the free academic license. -- Peter |
comment:13
Hello !
Oh ? Well, last time I tried I had to setup a weird proxy and start the authentication software in that proxy jail. Because my lab was not recognised as 'research institution' and stuff. And right now I am in India for two months. Well, I will give it a try tomorrow but I am sure that I will lose at least one hour on that Nathann |
comment:14
Replying to @nathanncohen:
It seems to me that only committing to the new model by assigning it to With your change, the model that just experienced an error is now stored in Furthermore, there is still this code between
which looks like it's quite nontrivial and hence could raise errors by itself. You'd still have a leak then. So either guard that with a |
comment:15
Hello,
I wrote this file myself, and I do not think that this had the slightest importance to me at that time.
When an exception is raised in that code, it is almost always because the problem is infeasible. This is not a "failure", it is the actual answer the user is looking for.
If your worry is that in a multithread Python program with a MixedIntegerLinearProgram instance
Well, again what you call an 'error' is just a certificate of infeasibiity, and this is definitely good to have around. But the fact that all doctests pass (even in the graph/ folder) indicates that this change brings no real problem.
Please move that line higher if you care. I believe that you are being worried unnecessarily. Nathann |
comment:16
I just tried it, but here we have no direct connection to internet: everything has to go through a http proxy that obviously will not handle their grbgetkey utility. I will try again tonight from another connection, but then I will not be on a university network anymore.... >_< Nathann |
Changed branch from u/nbruin/memory_leaks_with_lp_solvers_are_back to public/17320 |
comment:17
Hello again ! Turns out that their license thing was greatly simplified since (or that I was lucky). Either way it went smoothly after I got a real internet connection. I did the fix for Gubori, though for some reason I don't quite get why it works... I actually removed a call to GRBfreeenv and the memory leak seems to have disappeared. While debugging I noticed that GRBmodel returned an error code. Well, here it is Nathann New commits:
|
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:19
Replying to @nathanncohen:
OK, done. If it's possible the obviously avoid memory leaks at virtually no cost then we should, particularly because sage library code often is used as template for new contributions. Also, ensured that CoinBackend.solve has a return statement: In C, falling out of a function with a defined return type without executing an explicit return causes undefined behaviour, which could include returning -1 by accident (the one value that indicates erroneous behaviour). It seems cython does set the return value to 0 in absence of a return statement, but I wasn't able to find that stated explicitly in cython's documentation. Being explicit about it is safer. (certainly, if you say in the function signature that returning -1 means an exception has occurred, then it is instructive to explicitly not do that when no exception has occurred) |
comment:20
Hellooooooo !!
Okayokay. Well, there is obviously nothing wrong with what you did ! Right now I am on a very bad internet connection. It goes through a weird proxy and I can't use git nor ssh and I get disconnected from trac so I have to re-send every comment 10 times. I will be able to test and review your commit tonight. Do you have anything against the previous changes ? If not I will set this ticket to Thanks, Nathann |
comment:21
Hello ! I was finally able to test your latest commit and Sage reported nothing wrong. You can set this ticket to Thanks, Nathann |
Author: Nils Bruin, Nathann Cohen |
Reviewer: Nils Bruin, Nathann Cohen |
comment:22
Replying to @nathanncohen:
No objections here. However, someone who uses gurobi should probably check&sign off on that change: especially because it's optional, the buildbot won't have anything useful to say about it either. |
comment:23
Okay... Perhaps Peter then, since he raised the problem ? Nathann |
comment:24
Replying to @nathanncohen:
Well, I tried the patch in version 6.4.rc2. My original program now runs fine. There, however, all MIPs are feasible. So I tried a silly test code where every other MIP is infeasible. Again, memory usage is constant. So the Coin and gurobi backends now seem to work fine. (By the way, MIPSolverException cannot be used in a try/except environment. Not sure if this is a bug. Anyway, this was the same in the unpatched version.) |
comment:26
Replying to @ypfmde:
Why not? Did you perhaps not import the error first?
|
comment:27
Replying to @simon-king-jena:
Indeed, I didn't know that one has to import this error. Hmm, still doesn't look user-friendly to me that the class |
comment:28
Replying to @ypfmde:
I'd say that having And |
Changed branch from public/17320 to |
3 years ago a memory leak in lp solvers was fixed in ticket 11917. It seems that the problems are back in Sage 6.3. The code
consumes several GB of memory within a few seconds! The same happens with solver="gurobi", but not with solver="glpk".
Simon King confirmed the leak at sage-support, including some analysis and details.
CC: @simon-king-jena @nathanncohen
Component: linear programming
Author: Nils Bruin, Nathann Cohen
Branch/Commit:
5480f4e
Reviewer: Nils Bruin, Nathann Cohen
Issue created by migration from https://trac.sagemath.org/ticket/17320
The text was updated successfully, but these errors were encountered: