locked
inconsistency with unmanged call inside parallel.foreach RRS feed

  • Question

  • I'm working with a larger data and using Parallel.Foreach for a while, I ran into issues and noticed the result of a call to an unmanaged dll is not consistent.

    to figure out I've used a var to get the max value of all the result and the max value differs for each invocations. ?!!?

                int max = 0;
                Parallel.ForEach(dItems, w =>
                {
                    // ....
    
                    var wb = NativeMethods.ComputeSomething(p1,p2,p3);
    
                    if (max < wb)
                        max = wb; // <- max is not always same for the same inputs!!!
                });

    Am I missing anything with the parallel execution?! Any suggestion would be appreciated.

    Thanks


    Regards Vallarasu S. FSharpMe.blogspot.com

    Tuesday, June 26, 2012 7:47 AM

Answers

  • Actuallly I meant precisely that it's better to not share that, as the idea is rather to have nothing that is not directly related to the issue. You could try some whatever dummy calculation you want and either it will produce the same wrong behavior (in which case you could show something) or it won't and then NaviteMethods.Compute does perhaps something wrong ?

    Still not sure what is p1, p2, p3 but if they are arrays whose address is "cached" somewhere globally inside the method (??!!), calling it multiple times from distinct threads could perhaps just mess the whole calculation and in this case you wouldn't necessarily see the same behavior with another computation function...


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".


    Tuesday, June 26, 2012 2:16 PM

All replies

  • Hello,

    Request you to look the below link for more clarity.

    http://stackoverflow.com/questions/4574735/net-app-crashes-when-parallelizing-a-sequential-operation-how-is-this-possibl


    Regards, Tushar Capoor \n "Success is not permanent. The same is also true of failure." \n\n Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.\n\n\n I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.

    Tuesday, June 26, 2012 8:05 AM
  • Capoor,Tushar am not finding anything relevant to my situation in the link, Did I miss anything specific from the link?

    Thanks,


    Regards Vallarasu S. FSharpMe.blogspot.com

    Tuesday, June 26, 2012 8:44 AM
  • Can you more elaborate the issue you are facing

    Regards, Tushar Capoor \n "Success is not permanent. The same is also true of failure." \n\n Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.\n\n\n I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.

    Tuesday, June 26, 2012 8:47 AM
  • It just simple, when executed sequentially the result of max value is always same for any number of invocations. say 172.

    But when the code is executed in parallel the max value differs for each invocations for the same input.


    Regards Vallarasu S. FSharpMe.blogspot.com

    Tuesday, June 26, 2012 9:18 AM
  • Hi,

    Not a parallelization expert, but it seems expected as here the result of one loop depends on the result computed in other loops so they are not really parallelizable. But you could likely use the library to use a parallel version of the Max method : http://msdn.microsoft.com/en-us/library/dd383851.aspx


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".



    Tuesday, June 26, 2012 10:50 AM
  • Sorry Max value is not my concerns I've just meant to show the results are different! Here is the actual code where the contents of the 3D array is not the same when the inputs are same.

               Parallel.ForEach(dItems, w =>
               {
                    int m = w.Month;
                    int d = w.Day;
                    int h = w.Hour;
    
                    Wb[m, d, h] = NativeMethods.Compute(p1, p2, p3);
                });
    
               foreach (var w in dItems)
               {
                   int m = w.Month;
                   int d = w.Day;
                   int h = w.Hour;
    
                   Wb[m, d, h] = NativeMethods.Compute(p1, p2, p3);
               }

    Thanks


    Regards Vallarasu S. FSharpMe.blogspot.com

    Tuesday, June 26, 2012 11:24 AM
  • Request you to please provide the sample input and output which you are getting

    Regards, Tushar Capoor \n "Success is not permanent. The same is also true of failure." \n\n Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.\n\n\n I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.

    Tuesday, June 26, 2012 11:51 AM
  • One more thing.

    Parallel.Foreach and Foreach will never generate the same output as parallel.foreach will be executing parrallely. Please see the below output

    ParallelLoopState: Breaking early out of loops

    Because the loop body in a parallel For or ForEach is a delegate, you can’t exit the loop early with a breakstatement. Instead, you must call Break or Stop on a ParallelLoopState object:

    public class ParallelLoopState
    {
      public void Break();
      public void Stop();
     
      public bool IsExceptional { get; }
      public bool IsStopped { get; }
      public long? LowestBreakIteration { get; }
      public bool ShouldExitCurrentIteration { get; }
    }
    

    Obtaining a ParallelLoopState is easy: all versions of For and ForEach are overloaded to accept loop bodies of typeAction<TSource,ParallelLoopState>. So, to parallelize this:

    foreach (char c in "Hello, world")
      if (c == ',')
        break;
      else
        Console.Write (c);
    

    do this:

    Parallel.ForEach ("Hello, world", (c, loopState) =>
    {
      if (c == ',')
        loopState.Break();
      else
        Console.Write (c);
    });
    
    Hlloe
    

    You can see from the output that loop bodies may complete in a random order. Aside from this difference, callingBreak yields at least the same elements as executing the loop sequentially: this example will always output at leastthe letters Hell, and o in some order. In contrast, calling Stop instead of Break forces all threads to finish right after their current iteration. In our example, calling Stop could give us a subset of the letters Hell, and o if another thread was lagging behind. Calling Stop is useful when you’ve found something that you’re looking for — or when something has gone wrong and you won’t be looking at the results.

    The Parallel.For and Parallel.ForEach methods return a ParallelLoopResult object that exposes properties called IsCompleted and LowestBreakIteration. These tell you whether the loop ran to completion, and if not, at what cycle the loop was broken.

    If LowestBreakIteration returns null, it means that you called Stop (rather than Break) on the loop.

    If your loop body is long, you might want other threads to break partway through the method body in case of an early Break or Stop. You can do this by polling the ShouldExitCurrentIteration property at various places in your code; this property becomes true immediately after a Stop — or soon after a Break.


    Regards, Tushar Capoor \n "Success is not permanent. The same is also true of failure." \n\n Don't forget to click [Vote] / [Good Answer] on the post(s) that helped you.\n\n\n I will not say I have failed 1000 times; I will say that I have discovered 1000 ways that can cause failure – Thomas Edison.

    Tuesday, June 26, 2012 11:55 AM
  • What is p1, p2, p3 ? Is it altered somewhere ?

    Are you sure m,d,h is always different for each w value ? If not you could end up in updating the same cell multiple time and the final result could perhaps depend on the order in which the Compute method is performed. It's hard to guess from this code.

    Have you tried to see if it happens only with NativeMethods.Compute ? Usually an approach is to try to write the shortest possible code compilable code sample that shows the issue. It allows to play with this and perhaps to fix the problem. Else you have some code to show that doesn't contains anything unrelated to your issue (which is better if you want others to give this a look).

    For now I would say the same cell is perhaps updated multiple time with distinct results. So the sequential version will always give the latest result while the parallel version could give one of the values computed for single cell ?


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    Tuesday, June 26, 2012 12:48 PM
  • Thanks Patrice Scribe, that makes sense,

    I agree that a single cell may be overwritten with the latest value, but I can confirm the cell indexes are different. however there is a Big difference in the results, sequential execution results in values < 20 but parallel execution results in > 100000 

    I'm sorry the data and dll is proprietary and I cant share them 


    Regards Vallarasu S. FSharpMe.blogspot.com

    Tuesday, June 26, 2012 1:01 PM
  • You can have multiple threads updating 'max' at the same time, so you need to protect it with a lock or some other synch mechanism.

    e.g.

    int max = 0;
    object locker = new object();
    
    Parallel.ForEach(dItems, w =>
    {
        // ....
    
        var wb = NativeMethods.ComputeSomething(p1,p2,p3);
    
        lock (locker)
        {
            if (max < wb)
                max = wb; // <- max is not always same for the same inputs!!!
        }
    });


    Tuesday, June 26, 2012 1:56 PM
  • What are p1, p2, p3?  Are they changed at all over the course of the loop?

    Does the 'Compute' method have any state, or is it's output entirely dependent on it's inputs?  If there are static variables being manipulated, for example, or if it is modifying any the p1, p2, or p3 objects passed in, then the code will perform differently in parallel vs in serial.

    Tuesday, June 26, 2012 2:08 PM
  • Actuallly I meant precisely that it's better to not share that, as the idea is rather to have nothing that is not directly related to the issue. You could try some whatever dummy calculation you want and either it will produce the same wrong behavior (in which case you could show something) or it won't and then NaviteMethods.Compute does perhaps something wrong ?

    Still not sure what is p1, p2, p3 but if they are arrays whose address is "cached" somewhere globally inside the method (??!!), calling it multiple times from distinct threads could perhaps just mess the whole calculation and in this case you wouldn't necessarily see the same behavior with another computation function...


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".


    Tuesday, June 26, 2012 2:16 PM
  • I'm not sure of what happens with in the compute method, however it looks like it has state variables causing this issue. I have no other go but to process it sequentially.

    Thanks every one for your time and support.


    Regards Vallarasu S. FSharpMe.blogspot.com

    Wednesday, June 27, 2012 3:43 AM