Question

What I want to achieve:

Using Parallel.For (anything else would be appreciated, but found out that this one is the easiest) I want to increase a variable named max so that it gets to 100,000,000, using threads, but the program should use only X number of threads at the same time.

Code snippet:

using System;
using System.Threading;
using System.Linq;
using System.Threading.Tasks;

using System.Diagnostics;

namespace pool_threading
{
    class MainClass
    {
        static int max=0;
            static int current_max_thread=0;
        public static void Main (string[] args)
        {

            Parallel.For(0, 100000000, new ParallelOptions { MaxDegreeOfParallelism = 50 },
            i =>
            {
                            max++;
                if(Thread.CurrentThread.ManagedThreadId>current_max_thread)
                               current_max_thread=Thread.CurrentThread.ManagedThreadId;
            });

            Console.WriteLine ("I got to this number {0} using most {1} threads",max,current_max_tread);
        }
        public static void GetPage(int i)
        {
        }

    }
}

Result:

I got this number 38,786,886 using most 11 threads

Now ... I don't know why I get the number 38,786,886 which is less than 38,786,886, but I guess it's because multiple threads are trying to increase it at the exact same time, so if 10 are trying at the same time, only the first one will get the chance. Please correct me if I'm wrong.

The biggest "problem" is that I get 11 threads all the time, even with the maximum set to 50 (scroll the code to see the maximum), if I set it to maximum 1 thread, I get always 4 (maybe 4 is the minimum in this situation, but it still doesn't explain why I get maximum only 11 at the same time).

Était-ce utile?

La solution 2

There are two things going on here, as far as I can see:

First, you are hammering away on max from multiple threads. You probably have a multicore machine. Those operations are probably overlapping with each other. To perform your incrementing in a thread safe way you need

   Interlocked.Increment(ref max);

not

   max++;   /* not thread safe */

Second, you don't always get the number of threads you asked for in MaxDegreeOfParallelism. You'll never get more, but you might get less.

If you're going to use parallelism please pay close attention to the thread-safety of the code you'll run in the threads.

Autres conseils

This is trivial, just use i inside of the loop instead of trying to increment and use max. You're not incrementing it safely, but there's not reason for you to try. The whole point of Parallel.For is that it gives you the loop index, and ensures that each loop index is hit exactly once, no more, no less.

I believe you are not getting 50 threads for 2 main reasons:

  1. Hardware. There is a point at which a processor can do more with fewer threads because the time it takes to switch threads is more than just running a thread more often. This leads to

  2. Managed code. C#.NET is a managed code system. The programmers of .Net know the above and probably set some limits and checks to prevent too many threads from running. What you are setting in the code might be above some internal limit, so it is effectively ignored. Also, you are setting a maximum, so the Parallel.For() can use anywhere from 1 to X number of threads, whatever it thinks is most efficient.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top