Search code examples
drake

Create and Run Multiple Solver Instances in Parallel


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?


Solution

  • 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.