更新:
我的编译命令是ghc -O2 Montecarlo.hs
。我使用的随机版本是random-1.1
,ghc版本是8.6.4
,我的系统是macOS Big Sur 11.1(Intel芯片)。我用来测试速度的命令是time ./Montecarlo 10000000
,它返回的结果是real 0m17.463s, user 0m17.176s, sys 0m0.162s
。
以下是一个使用蒙特卡罗方法计算π的Haskell程序。然而,当输入为1000万时,该程序运行了20秒。在相同逻辑下编写的C程序只需要0.206秒。为什么会这样,并且如何加快速度?谢谢大家。
这是Haskell版本:
import System.Random
import Data.List
import System.Environment
montecarloCircle :: Int -> Double
montecarloCircle x
= 4*fromIntegral
(foldl' (\x y -> if y <= 1 then x+1 else x) 0
$ zipWith (\x y -> (x**2 + y**2))
(take x $ randomRs (-1.0,1) (mkStdGen 1) :: [Double])
(take x $ randomRs (-1.0,1) (mkStdGen 2) :: [Double]) )
/ fromIntegral x
main = do
num <- getArgs
let n = read (num !! 0)
print $ montecarloCircle n
以下是C语言版本:
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define N 10000000
#define int_t long // the type of N and M
// Rand from 0.0 to 1.0
double rand01()
{
return rand()*1.0/RAND_MAX;
}
int main()
{
srand((unsigned)time(NULL));
double x,y;
int_t M = 0;
for (int_t i = 0;i < N;i++)
{
x = rand01();
y = rand01();
if (x*x+y*y<1) M++;
}
double pi = (double)4*M/N;
printf("%lf\n", pi);
}
gcc -O3
编译的时间为0.11秒,使用ghc -O2
编译的时间为0.69秒。请展示您如何编译和运行它们。如果性能关键,可能可以将它们的性能差距缩小到7倍以下--我的直觉是两者之间的伪随机数生成算法可能不同。但100倍绝对是错误的。 - Daniel WagnerinsiderCount = length $ filter (<= 1.0) squaredNorms
,并像您的C代码一样将x ** 2
替换为x * x
,我只需要455毫秒,因此比C代码慢不到3倍。为什么您看到100倍的速度差异仍然是个谜团:-( - jpmarinier