What is level of parallelism in the Java ForkJoinPool?
Asked Answered
H

2

18

I was studying the oracle docs about the Fork/Join framework when i came across this constructor of ForkJoinPool : ForkJoinPool(int parallelism). The docs said that this was the level of parallelism, which is by default equal to the number of processors available. Can anyone tell me how I can use it to increase the speed and efficiency of my program?

Howbeit answered 13/1, 2013 at 8:15 Comment(0)
T
8

Essentially, the parallelism setting tells the ForkJoinPool how many worker threads to use.

The default setting is typically optimal, however let's say you have a worker thread separate from the ForkJoinPool, then you might find setting the number of worker threads to number of processors - 1 is better than using all of the processors. In general, the only way to increase the speed and efficiency in a specific program is to profile with different settings.

Telespectroscope answered 13/1, 2013 at 8:36 Comment(2)
How is it different from thread pool size? When I set the parallelism level to 32 then ForkJoinPool.commonPool().getPoolSize() returns me 0.Armenta
@Armenta ForkJoinPool.commonPool().getPoolSize() = 0 if you haven't submitted any runnable/callable/task - only after you submit you'll be able to see actual poolSizeWennerholn
S
0

The answer is, that it is used for "Sizing Thread Pools". So let's see what Java platform creators are saying.

Citing Brian Goetz's book "Concurrency in Practice", chapter 8, 8.2. Sizing Thread Pools

"The ideal size for a thread pool depends on the types of tasks that will be submitted and the characteristics of the deployment system. Thread pool sizes should rarely be hard-coded; instead, pool sizes should be provided by a configuration mechanism or computed dynamically by consulting Runtime.availableProcessors.

Sizing thread pools is not an exact science, but fortunately you need only avoid the extremes of “too big” and “too small”. If a thread pool is too big, then threads compete for scarce CPU and memory resources, resulting in higher memory usage and possible resource exhaustion. If it is too small, throughput suffers as processors go unused despite available work.

To size a thread pool properly, you need to understand your computing environment, your resource budget, and the nature of your tasks. How many processors does the deployment system have? How much memory? Do tasks perform mostly computation, I/O, or some combination? Do they require a scarce resource, such as a JDBC connection? If you have different categories of tasks with very different behaviors, consider using multiple thread pools so each can be tuned according to its workload.

For compute-intensive tasks, an Ncpu-processor system usually achieves optimum utilization with a thread pool of Ncpu +1 threads. (Even compute-intensive threads occasionally take a page fault or pause for some other reason, so an “extra” runnable thread prevents CPU cycles from going unused when this happens.) For tasks that also include I/O or other blocking operations, you want a larger pool, since not all of the threads will be schedulable at all times. In order to size the pool properly, you must estimate the ratio of waiting time to compute time for your tasks; this estimate need not be precise and can be obtained through pro-filing or instrumentation. Alternatively, the size of the thread pool can be tuned by running the application using several different pool sizes under a benchmark load and observing the level of CPU utilization.

Given these definitions:

image

The optimal pool size for keeping the processors at the desired utilization is:

image

You can determine the number of CPUs using Runtime:

int N_CPUS = Runtime.getRuntime().availableProcessors();

Of course, CPU cycles are not the only resource you might want to manage using thread pools. Other resources that can contribute to sizing constraints are memory, file handles, socket handles, and database connections. Calculating pool size constraints for these types of resources is easier: just add up how much of that resource each task requires and divide that into the total quantity available. The result will be an upper bound on the pool size.

When tasks require a pooled resource such as database connections, thread pool size and resource pool size affect each other. If each task requires a connection, the effective size of the thread pool is limited by the connection pool size. Similarly, when the only consumers of connections are pool tasks, the effective size of the connection pool is limited by the thread pool size."

Summary

  1. so as you know from the documentation the default value of it is Runtime.availableProcessors()
  2. I am not agree with Alex's answer saying that "you have a worker thread separate from the ForkJoinPool, then you might find setting the number of worker threads to number of processors - 1 is better than using all of the processors", in the book Brian Goetz says opposite.
  3. as you see from the book content it is necessary to not jump in too small or too large values and keep it somewhere near of the available processors
  4. another important aspect is to understand the nature of your tasks to use that value effectively
Strategic answered 6/11, 2023 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.