Parallel.for循环中的超出范围

时间:2014-01-28 07:55:10

标签: c# indexoutofboundsexception

我正在尝试使用Parallel.for循环来加速我的进程。我无法完成这项工作,因为我使用的索引超出了界限。在研究了网站之后,我想我知道自己是什么doing wrong,我认为我也是以临时变量的形式找到了解决方案,它在输入代码中的动作之前存储了循环变量。然而,这在我的例子中不起作用。我找到了有人提供给System.Collections.Concurrent的链接,据说可以为这些情况提供安全的线程,但我不知道如何使用该集合。我该怎么做?

我试图创建一个复制粘贴代码供你们运行,但我做错了,这可能表明我的经验不足:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Text;

    namespace empty
    {
        class Program
        {
            double[, , ,] info = new double[100, 100, 10, 5];

            void calculate()
            {
                int row;
                int layer, tex_class;
                double result;
                try
                {
                    for (row = 0; row < 100; row++)
                    {
                        Parallel.For(0, 99, col =>
                        {
                            int tempcol = col;
                            for (layer = 0; layer < 10; layer++)
                            {
                                int templayer = layer;
                                for (tex_class = 0; tex_class < 5; tex_class++)
                                {
                                    int tempclass = tex_class;
                                    result = info[row, tempcol, templayer, tempclass];
                                }
                                //other code
                            }
                        });
                    }
                }
                catch { }
            }

            static void Main(string[] args)
            {
                calculate();
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

因为循环并行运行,变量layer和tex_class将在不同的线程中增加。这将导致最终超过in指数的值。确保这些变量的范围仅在使用变量的循环内。尽可能减小范围以避免其他线程增加相同的变量。这段代码对我有用:

class Program
{
    double[, , ,] info = new double[100, 100, 10, 5];

    public void calculate()
    {
        int row;
        double result;
        try
        {
            for (row = 0; row < 100; row++)
            {
                Parallel.For(0, 99, col =>
                {
                    for (int layer = 0; layer < 10; layer++)
                    {
                        for (int tex_class = 0; tex_class < 5; tex_class++)
                        {
                            result = info[row, col, layer, tex_class];
                        }
                        //other code
                    }
                });
            }
        }
        catch { }
    }
}

除此之外,我建议在最外层循环上使用parallel for以尽可能多地平行工作。初始化并行会产生开销,这可能会降低您的性能而不是增加它。这就是我在这里做的事情:

   class Program
    {
        double[, , ,] info = new double[100, 100, 10, 5];

        public void calculate()
        {
            double result;
            try
            {
                Parallel.For(0, 100, row =>
                {
                    for (int col = 0; col < 100; col++)
                    {
                        for (int layer = 0; layer < 10; layer++)
                        {
                            for (int tex_class = 0; tex_class < 5; tex_class++)
                            {
                                result = info[row, col, layer, tex_class];
                            }
                            //other code
                        }
                    }
                });
            }
            catch { }
        }
    } 

答案 1 :(得分:0)

我认为,您应该使用本地循环变量,因为您的全局图层变量在所有并行线程中都会增加,就像您的tex_class变量一样。

类似的东西:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text;

namespace empty 
{
    class Program
    {
        double[, , ,] info = new double[100, 100, 10, 5];

        void calculate()
        {
            try
            {
                for (int row = 0; row < 100; row++)
                {
                    Parallel.For(0, 99, col =>
                    {
                        double result;
                        int tempcol = col;
                        for (int layer = 0; layer < 10; layer++)
                        {
                            int templayer = layer;
                            for (int tex_class = 0; tex_class < 5; tex_class++)
                            {
                                int tempclass = tex_class;
                                result = info[row, tempcol, templayer, tempclass];
                            }
                            //other code
                        }
                    });
                }
            }
            catch { }
        }

        static void Main(string[] args)
        {
            calculate();
        }
    }
}

拇指规则应该是,你的局部变量应该是并行的范围内的本地变量,或者受到某种同步的保护,或者它们将被多个线程同时访问,从而导致不可预测的行为。