I'd like to run multiple solvers in multiple threads and eventually processes. I'm currently running a for-loop and creating threads like the following:
for (...) {
pthread_t pid;
Args args;
args.solver = solver???
pthread_create(&pid, NULL, &func, (void*)&args);
}
When defining solver
, I've tried several options, though none have worked.
First, I tried calling const auto solver = drake::solvers::MakeSolver(solver_id);
, then passing solver.get()
into each thread's args. This successfully compiles and runs, but I get some obscure failure terminate called recursively
in drake::solvers::SnoptSolver::DoSolve
. I saw that MakeSolver seems to return a unique ptr around a single solver instance defined in kKnownSolvers
, so possibly the threads are calling DoSolve
on the same solver instance, causing this issue.
I then tried creating multiple instances of the solver. Calling StaticSolverInterface::Make<SnoptSolver>()
didn't work since that is defined in an unnamed namespace and thus is only accessible in that file. Calling const auto solver = drake::solvers::MakeSolver(solver_id);
and copying the SolverInterface
pointed to by solver
isn't possible because SolverInterface
is not movable or copyable.
Is what I'm doing possible? If so, how can I achieve this?
Calling drake::solvers::MakeSolver(solver_id)
multiple times and giving each one to a different thread should work fine. It returns distinct objects each time, nothing is shared.
Similarly, repeated calls to make_unique<SnoptSolver>
or the like should also work, if you can hard-code which solver you'd like instead of going by the id
.
The terminate
error message is probably an unhandled exception. Generally when you make a thread you'll want to put a try { } catch () {}
within the immediate entry point; you don't want exceptions to leave the thread.
Also I strongly suggest std::thread
if you're in C++; the pthread API is old and stinky.