Как исправить System.AggregateException при использовании циклов Parallel.For в C # - PullRequest
2 голосов
/ 06 февраля 2012

У меня есть цикл в C #, который выглядит следующим образом:

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);
        }
    }
}

Я хочу распараллелить этот код, используя цикл Parallel.For, что кажется довольно простым, по крайней мере, согласно ответу Рида на предыдущий вопрос, который я задал . Итак, я продолжаю и делаю это:

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);
        }
    }
    });
}

Этот код вызывает исключение System.AggregateException. Внутреннее исключение:

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

Я знаю, что массивы имеют правильный размер, поскольку код работает просто отлично, когда он не параллелен. Что это значит? Как я могу отладить эту проблему? Или я должен делать что-то еще полностью при распараллеливании кода такого рода?

Внутренняя трассировка стека исключений:

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

Перейдя на эту строчку, я связался с ней, чтобы посмотреть, может ли это быть проблемой. Строка была:

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};

И, подумав, что, может быть, это не сработает, я попробовал более явное:

//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);

Так может ли быть проблема, какое-то копирование внутреннего массива? Как обрабатывать это объявление массива, чтобы избежать исключения, если это проблема?

...