Это все виды неправильно:
(x until 1.0 by 1.0/interval).par.foreach(i => {
y = 4.0/(1.0+x*x)
mypi += (1.0/interval)*y
})
Первая проблема заключается в том, что все вычисления y
идентичны: вы не используете i
при его вычислении. Поскольку x
не изменяется, все потоки вычисляют одно и то же значение.
И вот вторая проблема, вы вычисляете mypi
(и y
) параллельно . Это означает, что несколько потоков одновременно читают и пишут mypi
и y
.
Давайте рассмотрим одно выполнение, чтобы понять проблему в этом. Допустим, первый поток запускается, вычисляет y
, а затем читает y
и mypi
. Затем этот поток приостанавливается, и все остальные потоки запускаются. Наконец, этот поток возобновляет и записывает результат своего вычисления в mypi
. В этом случае все вычисления всех других потоков тратятся впустую, поскольку окончательное значение было задано этим одним потоком.
Это был простой случай. По сути, вы вообще не можете предсказать, что произойдет для каждого из этих операций чтения и записи в mypi
(y
проще, поскольку все потоки присваивают ему одно и то же значение).
И, да, когда вы вызываете .par
на NumericRange
, он создает коллекцию со всеми значениями этого NumericRange
.