Execute the goals in Goals concurrently/in parallel. Succeed once all goals have succeeded. Only the first solution for each goal is computed. Fail (or throw) as soon as one of the goals is found to fail (or throw).
Operationally, a copy of each goal is executed in an engine. Once all goals have succeeded, all goals are simultaneously instantiated to their first solutions. The equivalent sequential operation could be written as:
concurrent(1, Goals, _) :- ( foreach(Goal,Goals), foreach(Copy,Copies) do copy_term(Goal, Copy), once(Copy) ), Goals = Copies.A maximum of MaxThreads engines is used to work in parallel. If there are more goals than engines, engines are reused as they become available. Use get_flag(cpu_count,N) to obtain the number of processors on the machine, which might be a good value for MaxThreads. If some goals are expected to fail, a higher number of threads can be advantageous for finding failures earlier.
The Options argument can be used to pass extra options for the creation of the worker engines. In particular, the stack size options local(KBytes) and global(KBytes) can be used to limit their memory consumption.
Due to the overheads of engine creation and destruction, this predicate is only useful for sufficiently long-running goals.