在c#中的Parallel.for不起作用

时间:2012-04-04 06:31:53

标签: c# parallel-processing

我编写了Wpf代码,使用随机变量生成正态分布。

using System.Threading.Tasks;
using System.Threading;


private void Button_Click(object sender, RoutedEventArgs e)
        {            .....


for (int t = 0; t < normalx.Count; t++)
            {
                normaly.Insert(t, (2 / ((Math.Pow(2 * Math.PI, 0.5)) * rmsnormalvalue)) * Math.Exp(-0.5 * Math.Pow(standardnormalx.ElementAt(t), 2)));
            }

...


}

这是sequantial代码。

要作为并行线程运行,我将其更改为

Parallel.For(0, normalx.Count, t =>
            {
                normaly.Insert(t, (2 / ((Math.Pow(2 * Math.PI, 0.5)) * rmsnormalvalue)) * Math.Exp(-0.5 * Math.Pow(standardnormalx.ElementAt(t), 2)));
            });

但是构建没问题,但在运行时只有一个线程区域(normalx.Count/8&lt; - 我的电脑是i7)

工作和计算。

有什么不对?

2 个答案:

答案 0 :(得分:1)

TPL不保证它将使用给定数量的线程进行并行循环。它是可行的,但它可能会确定启动额外线程的开销太大,因为在循环中要完成的工作量并且只是在单个线程上运行。

http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.for.aspx

  

执行一个for循环,其中迭代可以并行运行。

(强调我的)

可能能够通过提供自定义分区程序强制多个线程(不是强制是一个好主意),但我还没有尝试过

http://msdn.microsoft.com/en-us/library/dd560853.aspx

TPL仍然可以自由地说“你提供了一个自定义分区器,但我仍然要在一个线程上顺序执行每个分区”。我不知道目前的实施在这方面的表现如何。

更新

重新阅读并查看Henk的评论,我不确定我是否第一次正确阅读了您的问题。

你是说只计算了一些法线?如果是这种情况,可能是因为支持normaly的任何集合都不是线程安全的。

如果是这种情况,您可以进行计算,将其分配给临时变量,然后在实际插入周围使用lock。这会产生插入集合的瓶颈,但你仍然可以获得计算的并行性。

答案 1 :(得分:0)

几乎可以肯定,normaly.Insert(t, ...)不是线程安全的,也不可能是您想要执行的操作。你想要做的是提前创建一个空白的数据结构与你需要的所有插槽,然后用你的并行循环填充它们。您可以这样做:

var temp = new double[normalx.Count];
Parallel.For(0, normalx.Count, t =>
    temp[t] = 2 / ((Math.Pow(2 * Math.PI, 0.5)) * rmsnormalvalue)) *
              Math.Exp(-0.5 * Math.Pow(standardnormalx.ElementAt(t), 2));
normaly = temp.ToList();