我编写了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)
工作和计算。
有什么不对?
答案 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();