-
Notifications
You must be signed in to change notification settings - Fork 519
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
Can't run solve() inside a ThreadPool with GLPK #2475
Comments
After some investigation, I found out that the problem is related to the fact that each solve() call uses the same variable to store the log file name, because there is only one singleton TempFileManager instance. This issue could be solved by avoiding using one singleton for all the temporary files, allowing to pass a tempfilemanager instance either to solve or solverfactory, making them efectively independent (i.e. thread safe). |
Thanks for the bug report and the follow-up. The root of this is that the TempfileManager was originally written to be used as a stack (which is inherently not thread safe in the way you want to use it). We have updated it so that it can be used in threaded environments. Unfortunately, the "stack" usage is hard coded into the older solver interfaces, and a design decision from the very beginning of Pyomo (2008) makes it very difficult to replace the "stack" usage of the TempfileManager with the thread-safe explicit management of the temp file context. This is on the radar to fix, but it will take some time. An alternative (more expedient) solution may be to extend the APPSI interface to support GLPK. @michaelbynum? |
I thought it would just be a matter of removing the global instance (the singleton) and replacing broken references with new references to a local instance, optionally passed to the constructor of the solver factory maybe |
Each factory would then use its own stack I think. Maybe I didn't understand something. If that's the case, I'm sorry |
The problem is that for the older solver interfaces the Solver doesn't directly create / manage the problem writer (there is a sort of "meet in the middle" infrastructure - dating back to the Coopr project when the solver interfaces were not explicitly tied to the Pyomo modeling environment). This makes it very challenging for the solver to inform the writer of which TempfileManager instance / context that it should use. Newer solvers (e.g., APPSI) explicitly handle the problem writers, so things could work closer to what you suggest. |
Another problem would be that there is no APPSI for GLPK |
There will be, but it will take some time. |
Alright, thanks. |
Today I came up with a monkeypatch idea for the problem. from threading import get_ident
class MultiThreadTempFileManager():
def __init__(self):
self.tfm_dict = {}
def __getattr__(self, attr):
id = get_ident()
if id not in self.tfm_dict:
self.tfm_dict[id] = self.__new_manager(id)
return getattr(self.tfm_dict[id], attr)
def __new_manager(self, id):
t = TempfileManagerClass()
t.tempdir = os.path.join(tempfile.gettempdir(), 'pyomo_' + str(id))
if os.path.isdir(t.tempdir):
shutil.rmtree(t.tempdir)
elif os.path.isfile(t.tempdir):
os.remove(t.tempdir)
os.makedirs(t.tempdir, exist_ok=False)
return t
# The global Pyomo TempfileManager instance
TempfileManager = MultiThreadTempFileManager() If you approve, I can open a PR. [Edit] |
@ldeluigi: Thank you! I think this approach has promise, and a PR would be great. Some immediate thoughts:
|
I'll work on this in the future, thanks for the feedback! |
Yeah, PauseGC is the source of similar errors. Are there any other examples of global stacks that need work for thread safety? |
Good question. The short answer is "yes". The longer answer is "but I don't have a definitive list." We would have to go and look for module-scope variables and singleton-like things. I know that there is one in the new NLwriter. There are likely more. |
Unfortunately I have to leave those one out because of time availability. I'm focusing on PauseGC and TempFileManager. I'll open a PR shortly so that you can review my code and help improve it. I'll link it to this issue. |
Fix #2475 - Implement "thread safe" proxies for singleton instances (PauseGC, TempFileManager)
Summary
From https://stackoverflow.com/questions/73064859/pyomo-how-do-i-run-multiple-solve-concurrently-in-parallel-on-the-same-model:
Steps to reproduce the issue
or:
Error Message
Information on your system
Pyomo version: 6.4.1
Python version: 3.10.5
Operating system: Windows
How Pyomo was installed (PyPI, conda, source): PyPI
Solver (if applicable): GLPK
Additional information
I posted on the forum too, but none responded:
https://groups.google.com/g/pyomo-forum/c/CovfenBC0wg
The text was updated successfully, but these errors were encountered: