2012-04-04 141 views
0

我写了Wpf代码来使用随机变量生成正态分布。c#中的Parallel.for不起作用

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

... 


} 

这是后缀代码。

要作为并行线程运行,我把它改为

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 < - 我的电脑是I7)

是工作和计算。

什么问题?

+2

什么是'正常',它是线程安全的? – 2012-04-04 06:38:25

回答

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仍然可以自由地说“很好,你提供了一个定制的分区程序,但我仍然要在一个线程上按顺序执行每个分区”。我不知道当前实现在这方面的表现如何。

UPDATE

重读和检查亨克的评论,我不知道我正确地读你的问题的第一次。

你是说只有一些法线已经计算出来了吗?如果是这样的话,那可能是因为无论收集什么后盾normaly都不是线程安全的。

如果是这样,您可以进行计算,将其分配给临时变量,然后在实际插入点周围使用lock。这会造成插入到集合中的瓶颈,但是您仍然可以获得计算的并行性。

+0

会改变输入/输出的区域吗? – 2012-04-04 06:40:19

+0

@亨克:我可能误解了这个问题。更新了我的答案。 – 2012-04-04 06:47:42

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