Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Parallel.For unexpected results

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

like image 275
Franco Languasco Avatar asked Nov 25 '25 20:11

Franco Languasco


2 Answers

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);
like image 198
Theodoros Chatzigiannakis Avatar answered Nov 28 '25 09:11

Theodoros Chatzigiannakis


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.

like image 44
BlackBear Avatar answered Nov 28 '25 09:11

BlackBear



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!