Reputation: 23
Hi I am working on the following code:
Parallel.For(1, residRanges.Count, i =>
{
int count = 0;
List<double> colAList = new List<double>();
List<double> colBList = new List<double>();
for (int x = 0; x < residErrorData.Count; x++)
{
foreach (pricateConnection in residErrorData[x].connList)
{
if (residRanges[i].connection == nc.connection)
{
colAList.Add(residErrorData[x].residualError);
colBList.Add(nc.freq);
count = count + 1;
}
}
}
colA = new double[count];
colB = new double[count];
for (int j = 0; j < count; j++)
{
colA[j] = colAList[j];
colB[j] = colBList[j];
}
residRangeError tempresid = residRanges[i];
tempresid = fitResid(tempresid, colA, colB);
residRanges[i] = tempresid;
residRanges[i].n = count;
}
});
If I don't use the parallel class my values seem to be accurate however when i use the parallel class for some reason it mixes up the values for the colA and colB. It's mixing them between the threads. I'm fairly new to parallel processing but I've been looking around, and can't seem to find any solutions. Does anyone know why the program seems to be sharing variables between threads?
I know the code isn't ideal I've been trying different things to figure out what was going wrong. I'm not trying to necessarily optimize it at the moment so much as understand why the variables in the different loops aren't staying separate.
residRanges[] is a list of class items. The for loops using it seems to get the right values they just begin to mix up which values go where when run in Parallel.For.
Thanks for any help! I could really use it!
Upvotes: 2
Views: 488
Reputation: 155443
(Reposting as an answer for sweet, sweet karma)
Your code looks as though colA
and colB
are declared outside the lambda's scope, which means the variable references could refer to different array objects as different threads run simultaneously (e.g. Thread 0 would change colA
while Thread 1 is inside the for j < count
loop.
Move the declarations of colA
and colB
to inside the lambda:
...
Double[] colA = new double[count];
Double[] colB = new double[count];
for (int j = 0; j < count; j++)
...
However I see that you don't actually do anything useful with colA
and colB
other than using them as a value holder for your fitResid
function, you can simplify this by:
fitResid
function signature to accept IList<Double>
instead of Double[]
Change your fitResid
function call to pass in colAList
and colBList
in respectively, which will speed up your code by eliminating the unnecessary copying and memory allocation:
...
residRanges[i] = fitResid( residRanges[i], colAList, colBList );
residRanges[i].n = count;
...
Upvotes: 3