2

I have a loop in C# that looks like this:

for (int level = 0; level < numLevels; level++){
    for (int y = 0; y < ysize; y++){
        for (int x = 0; x < xsize; x++){
            outArray[y*xsize + x] = SomeMathWasDone(level);
        }
    }
}

I want to parallelize this code using a Parallel.For loop, something that seems pretty straightforward, at least according to Reed's answer to an earlier question I asked. So I go ahead and do this:

for (int level = 0; level < numLevels; level++){
    Parallel.ForEach(Partitioner.Create(0, ysize),
                (range) => {
    for (int y = range.Item1; y < range.Item2; y++){
        for (int x = 0; x < xsize; x++){
            outArray[y*xsize + x] = SomeMathWasDone(level);
        }
    }
    });
}

This code throws a System.AggregateException. The inner exception is:

    InnerException  {"Destination array was not long enough. Check destIndex and length, and the array's lower bounds."}    System.Exception {System.ArgumentException}

I know that the arrays are the right size, since the code works just fine when it's not parallel. What does this mean? How can I debug this problem? Or should I be doing something else entirely when parallelizing code of this nature?

The inner exception stack trace is:

at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length)
at System.Array.CopyTo(Array array, Int32 index)
at MyFunction(Single[] inImage, Int32 inXSize, Int32 inYSize, Int32 inLevels) ... line 100

After going to that line, I messed with it to see if that could be the issue. The line was:

float[] theKernel = 
        {1.0f, 4.0f, 6.0f, 4.0f, 1.0f,
        4.0f, 16.0f, 24.0f, 16.0f, 4.0f,
        6.0f, 24.0f, 36.0f, 24.0f, 6.0f,
        4.0f, 16.0f, 24.0f, 16.0f, 4.0f,
        1.0f, 4.0f, 6.0f, 4.0f, 1.0f};

And thinking that maybe that wouldn't work, I then tried the more explicit:

//outside the function, now a member of the class
float[] downsizeKernel= 
        {1.0f, 4.0f, 6.0f, 4.0f, 1.0f,
        4.0f, 16.0f, 24.0f, 16.0f, 4.0f,
        6.0f, 24.0f, 36.0f, 24.0f, 6.0f,
        4.0f, 16.0f, 24.0f, 16.0f, 4.0f,
        1.0f, 4.0f, 6.0f, 4.0f, 1.0f};

//now inside the function
float[] theKernel = new float[25];
downsizeKernel.CopyTo(theKernel, 0);

So could that be the problem, some kind of internal array copying? How should this array declaration be handled to avoid the exception, if that's the problem?

Community
  • 1
  • 1
mmr
  • 14,781
  • 29
  • 95
  • 145
  • @SLaks-- It ends at that exception. Above it are functions that are pretty irrelevant. – mmr Feb 05 '12 at 23:37
  • 2
    Huh? What's the stack trace of the inner exception? – SLaks Feb 05 '12 at 23:37
  • @SLaks-- is this what you're looking for? I'm not sure what kind of information can be gotten from this trace, but I definitely need to learn. It looks like it's expecting code to execute faster than it is, but that shouldn't really cause this kind of failure, right? – mmr Feb 05 '12 at 23:47
  • 1
    That's the _outer_ exception stack trace. The stack trace tells you where the error actually happened. The top line threw the exception; the second line called the first line, etc. – SLaks Feb 05 '12 at 23:48
  • The inner exception stack trace will most likely contain `Array.Copy()`, or similar method. Can you post that, as SLaks requested? – svick Feb 05 '12 at 23:50
  • @svick-- it does indeed. Is this a common enough issue that I should have found it via google-fu? Because I found nothing on this one. – mmr Feb 06 '12 at 00:00
  • The line numbers may sometimes be slightly off. I doubt the line that initializes `theKernel` is the problem. Do you have some calls to `Array.CopyTo()` close by? That's probably where the problem is. – svick Feb 06 '12 at 01:56
  • @svick-- There is a copyto near there; is copyto not threadsafe? – mmr Feb 06 '12 at 02:52

0 Answers0