Haskell:两个版本代码之间的速度差异

Haskell:两个版本代码之间的速度差异,haskell,optimization,profiling,Haskell,Optimization,Profiling,我开始潜入哈斯克尔,试图解决一些小问题 我偶然发现“标准haskell友好型”解决方案和我的“非常丑陋且haskell不友好型”解决方案之间存在巨大的性能差异(~100-200x) 我相信哈斯凯勒的同事们,这种表现上的差异有一个很好的原因,我不知道这一点,可以在这个话题上教育我 问题:查找数字字符串中的最大5位数 两者在求解时使用相同的概念:生成所有5位数字并找到最大值 优雅快速的代码 digit5 :: String -> Int digit5 = maximum . map (read

我开始潜入哈斯克尔,试图解决一些小问题

我偶然发现“标准haskell友好型”解决方案和我的“非常丑陋且haskell不友好型”解决方案之间存在巨大的性能差异(~100-200x)

我相信哈斯凯勒的同事们,这种表现上的差异有一个很好的原因,我不知道这一点,可以在这个话题上教育我

问题:查找数字字符串中的最大5位数

两者在求解时使用相同的概念:生成所有5位数字并找到最大值

优雅快速的代码

digit5 :: String -> Int
digit5 = maximum . map (read . take 5) . init . tails
丑陋且非常慢的代码(一旦字符串大)

我对这一点的肤浅理解是,fast代码使用的是预先可用的高阶函数。对于较慢的版本,使用递归,但我认为咬尾应该是可能的。但在天真的层面上,对我来说,两人似乎做了同样的事情

虽然较慢的函数对字符串进行比较,而不是将其转换为数字,但我也尝试将字符串转换为整数,但没有任何大的改进

我尝试过使用ghc(不带任何标志)和以下命令进行编译:

ghc 
ghc -O2 
ghc -O2 -fexcess-precision -optc-O3 -optc-ffast-math -no-
recomp 
stack runhaskell 
ghc -O3
为了再现性,我在代码中添加了一个链接,其中也包含测试向量:

您的“慢”版本的问题是这一行:

| length xs < 5 = maxim
它将使整个事情只是线性的,它将与“优雅”的解决方案一样快。当然,这将导致额外的5次迭代,但通过降低总体复杂性,损失得到了更多的补偿

或者,您也可以通过过滤掉5个字符或更短的尾巴,使“优雅”解决方案同样缓慢:

digit5 = maximum . map (read . take 5) . filter ((>= 5) . length) . tails

有一些函数在列表上递归,并在每次迭代时调用
length
<代码>长度为O(n)。您不小心在运行时添加了一个O(n^2)项。只需跳过保护
| length xs<5=maxim
就可以获得一个额外的模式
digit5'[]maxim=maxim
给我0.004秒而不是1.7秒。这比优雅的解决方案还要快。(读取将始终消耗5字节的部分字符串,而字符串比较可能只需要比较第一个字符。)关于进一步提高速度的一些建议:对
string
的字典顺序和对
Integer
的顺序一致,因此您可以完全跳过
读取
。您还可以使用一个奇特的技巧来避免
过滤器
zipWith const(tails xs)(drop 4 xs)
将生成
xs
的所有至少5个尾部(…或者您可以移动
read
,如
read.maximum.map(take 5)
,如果您想保持相同的类型。我已在以下计时测试中完成了此操作。)结果:
digit5ReadFilter
,长度为10000的
字符串为0.32s<编码>数字5ReadzipWith
,0.04s
digit5LexFilter
,0.27s
digit5LexZipwith
甚至没有注册(报告为0.00s)。这是我在学习Haskell时遇到的第一个严格错误:
length xs<5
在这里太严格了,因为
Int
太严格了。如果使用像
Data.Nat
这样的惰性数字类型,它将在5个元素之后停止计算
xs
genericLength xs<(5::Nat)
。这同样适用于
过滤器((>=(5::Nat)).genericLength)
。请尝试
digit5=最大值。扫描(\ab->rem(10*a+b)100000)0。地图数码点
。我没有对它进行基准测试,但我认为缺少字符串操作应该会有所帮助。
| length xs < 5 = maxim
| null xs = maxim
digit5 = maximum . map (read . take 5) . filter ((>= 5) . length) . tails