docs: public static void run(DBIDs ids, Processor... procs) {
      ParallelCore core = ParallelCore.getCore();
      core.connect();
      try {
        // TODO: try different strategies anyway!
        ArrayDBIDs aids = DBIDUtil.ensureArray(ids);
        final int size = aids.size();
        int numparts = core.getParallelism();
        // TODO: are there better heuristics for choosing this?
        numparts = (size > numparts * numparts * 16) ? numparts * Math.max(1, numparts - 1) : numparts;
  
        final int blocksize = (size + (numparts - 1)) / numparts;
        List<Future<ArrayDBIDs>> parts = new ArrayList<>(numparts);
        for(int i = 0; i < numparts; i++) {
          final int start = i * blocksize;
          final int end = Math.min(start + blocksize, size);
          Callable<ArrayDBIDs> run = new BlockArrayRunner(aids, start, end, procs);
          parts.add(core.submit(run));
        }
  
        for(Future<ArrayDBIDs> fut : parts) {
          fut.get();
        }
      }
      catch(ExecutionException e) {
        throw new RuntimeException("Processor execution failed.", e);
      }
      catch(InterruptedException e) {
        throw new RuntimeException("Parallel execution interrupted.");
      }
      finally {
        core.disconnect();
      }
    }