Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么我的代码不能使用多线程并行.For循环加速?_C#_Multithreading_Parallel Processing_Thread Safety_Thread Local - Fatal编程技术网

C# 为什么我的代码不能使用多线程并行.For循环加速?

C# 为什么我的代码不能使用多线程并行.For循环加速?,c#,multithreading,parallel-processing,thread-safety,thread-local,C#,Multithreading,Parallel Processing,Thread Safety,Thread Local,我尝试使用System.Threading.Tasks库将简单的顺序循环转换为并行计算循环。 代码进行编译,返回正确的结果,但它不会节省任何计算成本,否则需要更长的时间 编辑:对不起,伙计们,我可能把这个问题简化了,并且犯了一些错误。 为了附加额外的信息,我正在i7-4700QM上运行代码,它在脚本中被引用。 这是实际的代码。我还切换到非线程局部变量 public static class LineNet { public static List<Ray>

我尝试使用
System.Threading.Tasks
库将简单的顺序循环转换为并行计算循环。 代码进行编译,返回正确的结果,但它不会节省任何计算成本,否则需要更长的时间


编辑:对不起,伙计们,我可能把这个问题简化了,并且犯了一些错误。 为了附加额外的信息,我正在i7-4700QM上运行代码,它在脚本中被引用。 这是实际的代码。我还切换到非线程局部变量

public static class LineNet
{        
    public static List<Ray> SolveCpu(List<Speaker> sources, List<Receiver> targets, List<Panel> surfaces)
    {
        ConcurrentBag<Ray> rays = new ConcurrentBag<Ray>();
        for (int i = 0; i < sources.Count; i++)
        {
            Parallel.For(
                0,
                targets.Count,
                j =>
                {
                    Line path = new Line(sources[i].Position, targets[j].Position);
                    Ray ray = new Ray(path, i, j);
                    if (Utils.CheckObstacles(ray,surfaces))
                    {
                        rays.Add(ray);
                    }

                }
                );
        }
    }
}
公共静态类线网
{        
公共静态列表(列表源、列表目标、列表曲面)
{
ConcurrentBag射线=新ConcurrentBag();
for(int i=0;i
{
线路路径=新线(源[i]。位置,目标[j]。位置);
射线=新射线(路径i,j);
如果(使用检查障碍物(光线、表面))
{
射线。添加(射线);
}
}
);
}
}
}
蚱蜢实现只收集
sources
targets
surfaces
,调用方法
solution
并返回
ray
。 我知道向线程发送工作负载是很昂贵的,但是它是不是太贵了? 还是
ConcurrentBag
只是阻止并行计算

另外,我的类是不可变的(?),但是如果我使用一个公共的
列表
内核中止操作并抛出异常,有人能告诉我原因吗?

如果没有可靠地重现问题的好方法,就不可能提供明确的答案。您发布的代码看起来甚至不是真实代码的摘录,因为声明为方法返回类型的类型与
return
语句实际返回的值不同

但是,您发布的代码显然没有很好地使用
Parallel.For()
。您的
构造函数将花费相当高的成本来证明并行化创建项的任务的合理性。要清楚的是,这是这里唯一可能的胜利

最后,您仍然需要将您创建的所有
实例聚合到一个列表中,因此为
Parallel.for()
任务创建的所有中间列表都是纯开销。聚合必须序列化(即,一次只能有一个线程向
结果
集合添加一个项),并且以最糟糕的方式(每个线程在放弃锁之前只能添加一个项,而另一个线程有机会获得它)

坦率地说,您最好将每个本地
列表存储在一个集合中,然后在
Parallel.For()
返回后在主线程中一次性聚合它们。这并不意味着代码的性能会比直接的非并行实现更好。但至少情况不会更糟。:)

底线是,您似乎没有一个可以从并行化中获益的工作负载。如果你不这么认为,你需要以更清晰、更详细的方式解释这种想法的基础

如果我使用一个公共列表,内核会中止操作并抛出异常,有人能告诉我为什么吗

您已经在使用(看起来)
List
作为每个任务的本地数据,事实上这应该没问题,因为任务不共享本地数据


但是,如果您询问,如果您尝试使用
List
而不是
ConcurrentBag
作为
result
变量,为什么会出现异常,那么这完全是意料之中的。
List
类不是线程安全的,但是
Parallel.For()
将允许它运行的每个任务与所有其他任务同时执行
localFinally
委托。因此,您有多个线程都试图同时修改同一个非线程安全集合。这是灾难的秘诀。幸运的是你得到了例外;实际行为是未定义的,并且很可能会破坏数据结构,导致运行时异常。

如果使方法运行速度减慢的是处理器,则并行循环通常只会使方法运行速度加快(也就是说,在四核计算机中,整个方法运行期间,CPU使用率保持在25%,因为处理器在整个时间内都在尽可能地工作。)如果这是真的,那么将其分散到多个线程上会有所帮助。如果您的方法在硬盘驱动器或网络资源或其他地方等待,则可能没有帮助。如果不了解有关如何生成
行或程序正在执行的操作的更多详细信息,很难说为什么这样做很慢……有多少行我们在您的测试中讨论的是什么?会有一些初始开销,因此好处可能不会立即被注意到。另一件事是
result.Add(line)
将阻止任何想要调用与您正在使用的
ConcurrentBag相同的行的线程。
可能是信息性的。@ElementalPete I更新了问题以更好地解释问题。@TyCobb数十万行。
源中有200点
目标中有200点
,它配置了3.2s In并行模式,以及顺序计算中的2.9。@DourHighArch一个有助于调查问题的非常机智的答案我更新了这个问题。为了更好地解释我为什么要研究并行计算:我有两个列表,都有数百个点;我想将
List1
中的每个点与
List2
中的每个点连接起来。因为这会产生