【发布时间】:2016-07-06 12:51:49
【问题描述】:
当我运行下面的代码时,第 5 位和第 6 位的结果总是不同的:
public void TestParallel()
{
object locker = new object();
double grandTotal = 0;
Parallel.For( 1, 1000000,
() => 0.0, // Initialize the local value.
( i, state, localTotal ) => // Body delegate. Notice that it
{
return localTotal + Math.Sqrt( i ); // returns the new local total.
},
localTotal => // Add the local value
{
lock( locker ) grandTotal += localTotal; // to the master value.
}
);
Console.WriteLine( string.Format( "Grand Total = {0}", grandTotal ) );
}
我不知道为什么结果并不总是总计 = 666666166,458842。这是我这样运行时得到的:
double grandTotal = 0;
for ( int i = 1; i < 1000000; i++ )
{
grandTotal += Math.Sqrt( i ); // returns the new local total.
}
Console.WriteLine( string.Format( "Grand Total = {0}", grandTotal ) );
【问题讨论】:
-
浮点数学很难。
-
您也可以使用多个线程更改单个变量。这些处理的顺序将会改变
-
@Liam 请注意,他更改的唯一共享变量是 grandTotal,他在更改之前将其锁定。
-
好点@Liam。 Sqrt 函数可能是现代处理器上的一条指令,虽然它可能有多个“虚拟处理器”,但它们可能没有多个浮点单元。在这种特殊情况下,Parallel.For 不太可能显示出任何好处(并且可能由于锁定而减慢速度)。
-
浮动加法不是关联的。进化顺序很重要。比较
(-1000000 + 1000000) + 0.1和-1000000 + (1000000 + 0.1)。