How can I achieve maximum parallelism and use maximum processor with Parallel.ForEach?

There is a C # A(arg1, arg2) function A(arg1, arg2) that needs to be called many times. To do this the fastest, I use parallel programming.

Take an example of the following code:

 long totalCalls = 2000000; int threads = Environment.ProcessorCount; ParallelOptions options = new ParallelOptions(); options.MaxDegreeOfParallelism = threads; Parallel.ForEach(Enumerable.Range(1, threads), options, range => { for (int i = 0; i < total / threads; i++) { // init arg1 and arg2 var value = A(arg1, agr2); // do something with value } }); 

Now the problem is that this does not increase the number of cores; for example, on 8 cores it uses 80% of the processor, and on 16 cores it uses 40-50% of the CPU. I want to use the processor to the maximum extent.

You can assume that A(arg1, arg2) internally contains complex calculations, but it does not have I / O or network operations, and there is no thread blocking. What are other options to figure out which part of the code is making it non-executing 100% parallel?

I also tried to increase the degree of parallelism, for example

 int threads = Environment.ProcessorCount * 2; // AND int threads = Environment.ProcessorCount * 4; // etc. 

But it did not help.

Update 1 - if I run the same code, replacing A() with a simple function that calculates a prime number, then it uses 100 CPUs and scales well. Thus, this proves the correctness of the other part of the code. Now the problem may be in the original function A() . I need a way to detect this problem that causes some sequence of sequencing.

+7
c # task-parallel-library cpu-usage parallel.foreach
source share
1 answer

You have determined that the code in A is a problem.

There is one very common problem: garbage collection. Configure the application in app.config to use the parallel server GC. Workstation GC tends to serialize execution. The effect is heavy.

If this is not a problem, try pausing the debugger several times and look at the Debug -> Parallel Stacks window. There you can see what your threads are doing. Look for shared resources and debate. For example, if you find many threads waiting to be blocked, that is your problem.

Another good debugging technology is code commenting. As soon as the scalability limit disappears, you know which code caused it.

+5
source share

All Articles