I am new in the parallel computing and I'm with some problems running a Parallel.For in C#.
I'm trying visit multiple Web Sites in simultaneous, get the HTML and register them in multiple SQLite Database.
Everything seems work fine until I check the results more precisely.
I noticed that in one loop for 0 to 20, the code entered 20 times in the shared part of loop and only 16 times in local part. So, was missing 4 results.
To understand the problem I made a experience where I only put two counters. One in the global part and another in the local. The output of global count was 20 and in the local part 1! After that I put a 2 seconds sleep before the returning of global part to the local part. In this case the output of global count was 20 and in the local part was 13! Can you explain me what I'm doing wrong?
static void ParalellCalc()
{
var tm = new Stopwatch();
tm.Start();
int count = 0;
int count2 = 0;
var parl = Parallel.For<int>(0, 20,
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount},
() => 0, (i, state, Enrada) =>
{
count++;
Thread.Sleep(2000);
return Enrada;
},
(x) =>
{
count2++;
});
tm.Stop();
Console.WriteLine(tm.Elapsed);
Console.WriteLine("Global: " + count.ToString());
Console.WriteLine("Local: " + count2.ToString());
Console.WriteLine(tm.Elapsed);
tm.Reset();
}
EDIT:
I go into your suggestions and I made the same example with the Interlocked.Increment to increment the counters. The produced results are exactly the same. If I remove the Thread.Sleep(2000) the second counter produce the result of 1!? If I don't remove produce the result of 16. The first counter display in all the cases the value of 20 as should be. Anyone can explain that?
static void ParalellCalc()
{
var tm = new Stopwatch();
tm.Start();
int count = 0;
int count2 = 0;
var parl = Parallel.For<int>(0, 20,
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount},
() => 0, (i, state, Enrada) =>
{
Interlocked.Increment(ref count);
return Enrada;
},
(x) =>
{
Interlocked.Increment(ref count2);
});
tm.Stop();
Console.WriteLine(tm.Elapsed);
Console.WriteLine("Global: " + count.ToString());
Console.WriteLine("Local: " + count2.ToString());
Console.WriteLine(tm.Elapsed);
tm.Reset();
}
++ operator is not thread safe, because it's not atomic. Interlocked.Increment is thread safe. Interlocked.Increment(ref count) instead of count++ and the same for count2 would probably fix the counting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With