Spread 10 infinite jobs across 4 threads in load balanced (Java)

I have 10 calculation tasks that take (nearby) infinite time . For example: calculate the next PI, solve the problem with limiting NP-rigidity, etc.

I have 4 threads (so there is a thread pool with 4 threads on a machine with 8 cores , so I have several cores left to avoid the real-time blocking of the machine and the process).

Using Java 8, how to distribute these 10 jobs in these four threads?

It is a bad idea:

ExecutorService es = Executors.newFixedThreadPool(4); for (Job j : jobs) { es.submit(j); } 

because 4 tasks will start, but no one will finish so that work 5-10 will never start.

If I look, for example, for 10 minutes, I would expect that each work will work for about 4 minutes. After 20 minutes, each work lasts about 8 minutes, etc. What are typical patterns to solve this problem? (If necessary, I can implement a method for calculating the calculation after a given period of time.)

+6
source share
4 answers

The task of distributing ten tasks between four threads and the task of using only four processors (I use the CPU here as a synonym for the kernel for simplicity) with your ten tasks are slightly different.

Four threads

Limiting the thread number to four does not guarantee that they will adhere to four processors and will not use others. OS allows you to shuffle your threads between all available processors as you wish. The only thing you can guarantee is that your program will not be able to use more than 50% of all CPU resources (given that you have eight processors).

But you are unlikely to be able to use these 50%. Despite the fact that your jobs are mainly processor-oriented, it is likely that they still need to read and write to memory from time to time. When a thread skips the cache on such reads / letters and expects the data to be delivered to the processor, this processor puts the thread on hold and can do some work on another thread. In your case, he has nothing to do and just sit idle until the data arrives. Thus, your processors are likely to be underused.

If you decide to go with this approach, you need to break your assignments into small tasks and hand them over to the performers, as @James Large said. You can use the WorkStealingPool with four threads (as suggested by @Alexey Soshin) or create a ten-thread pool and use Semaphore with four permissions and fairness set to true . In the latter case, your threads should use loops, get permissions at the beginning of each iteration, and release them at the end. Each iteration will be a small piece of work.

Four processors

There are mechanisms for assigning specific processors to work with your tasks.

At the process level on Linux, you can use special commands to bind the process to specific processors. This will allow you to create ten threads and allow the OS to perform all balancing on four processors.

At the thread level, you can try the Java Affinity library from OpenHFT. It allows you to associate threads with processors directly in your Java code. The problem is that ten threads cannot be shared between the four processors without a reminder, so it will be difficult to balance them.

+6
source

I think you are looking for WorkStealingPool:

 static ExecutorService executor = Executors.newWorkStealingPool(4); private static Map<Integer, AtomicInteger> map = new ConcurrentHashMap<>(); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 10; i++) { executor.submit(new Worker(i)) ; } Thread.sleep(10000); System.out.println(map); } private static class Worker implements Runnable { private final int k; public Worker(int k) { this.k = k; } @Override public void run() { map.putIfAbsent(k, new AtomicInteger(0)); map.get(k).getAndIncrement(); executor.submit(new Worker(this.k)); // Also possible to resubmit current job //executor.submit(this); } } 
+2
source

If you need to complete 10 tasks in parallel - just start 10 threads.

Change Executors.newFixedThreadPool(4) to Executors.newFixedThreadPool(10) .

+1
source

I'm somewhat worried about the idea of ​​"Work that never ends." I would call it something else, such as "long-term computing" or ...

If you have ten of them, and you can afford only four threads to work on them, then your only choice is to break them into finite β€œtasks” that end, and then write a scheduler that saves the subheadings in four available threads.

But this will replicate much of what your streaming system should do.

I would just do ten threads. If you work on a machine with four available cores to run ten threads, the OS automatically breaks your lengthy work tasks into β€œsub-tasks” (that is, time slices) and correctly distributes them across four cores.

+1
source

All Articles