I am a newbie in C# and while translating my old DSP, VB6 code I would like to take advantage of the possibilities offered by this language. Specifically I am trying to use parallel processing to speed up time expensive calculations.
Here is the (simplified) code that I am currently testing.
The "1° parallel code OK" section works fine, no problems;
the "2° parallel code WRONG results" section that, to me, should be equivalent to the "Sequential code OK" section is a lot faster than the sequential version but doesn't return the expected results.
Why? Where am I wrong?
double[] Omega = new double[NFreq + 1];
double[,] SinOmT = new double[NFreq + 1, NVAL];
double[,] CosOmT = new double[NFreq + 1, NVAL];
double OmT;
// 1° Parallel code OK:
Parallel.For(0, NFreq + 1, JF =>
{
Omega[JF] = PI2 * Freq[JF] / Fs;
});
// Sequential code OK:
for (int JF = 1; JF <= NFreq; JF++)
{
for (int JD = 0; JD < NVAL; JD++)
{
OmT = Omega[JF] * (double)(JD);
SinOmT[JF, JD] = Math.Sin(OmT);
CosOmT[JF, JD] = Math.Cos(OmT);
}
}
// 2° Parallel code WRONG results:
for (int JF = 1; JF <= NFreq; JF++)
{
Parallel.For(0, NVAL, JD =>
{
OmT = Omega[JF] * (double)(JD);
SinOmT[JF, JD] = Math.Sin(OmT);
CosOmT[JF, JD] = Math.Cos(OmT);
});
}
Ciao and thanks for the attention.
Franco
It's wrong to declare the variable OmT outside of the loops, because then the parallel iterations contest for it and overwrite its value unpredictably.
In C#, you should always declare variables in the tightest scope that makes sense. This is true for all scenarios, not just parallel code.
var OmT = Omega[JF] * (double)(JD);
SinOmT[JF, JD] = Math.Sin(OmT);
CosOmT[JF, JD] = Math.Cos(OmT);
The variable JF gets captured by the lambda expression; this means that it will always have the same value. See here for a better explaination.
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