【发布时间】:2011-04-08 11:04:51
【问题描述】:
我正在解决 Project Euler 中的问题作为学习 Haskell 的一种方式,我发现我的程序比可比较的 C 版本慢很多,即使在编译时也是如此。我可以做些什么来加快我的 Haskell 程序?
例如,我对Problem 14 的蛮力解决方案是:
import Data.Int
import Data.Ord
import Data.List
searchTo = 1000000
nextNumber :: Int64 -> Int64
nextNumber n
| even n = n `div` 2
| otherwise = 3 * n + 1
sequenceLength :: Int64 -> Int
sequenceLength 1 = 1
sequenceLength n = 1 + (sequenceLength next)
where next = nextNumber n
longestSequence = maximumBy (comparing sequenceLength) [1..searchTo]
main = putStrLn $ show $ longestSequence
这大约需要 220 秒,而“等效”的蛮力 C 版本只需要 1.2 秒。
#include <stdio.h>
int main(int argc, char **argv)
{
int longest = 0;
int terms = 0;
int i;
unsigned long j;
for (i = 1; i <= 1000000; i++)
{
j = i;
int this_terms = 1;
while (j != 1)
{
this_terms++;
if (this_terms > terms)
{
terms = this_terms;
longest = i;
}
if (j % 2 == 0)
j = j / 2;
else
j = 3 * j + 1;
}
}
printf("%d\n", longest);
return 0;
}
我做错了什么?还是我天真地认为 Haskell 甚至可以接近 C 的速度?
(我使用 gcc -O2 编译 C 版本,使用 ghc --make -O 编译 Haskell 版本)。
【问题讨论】:
-
您的
unsigned long可能只有 32 位长。为了公平比较,请使用unsigned long long或uint64_t。 -
@KennyTM - 公平点 - 我在 32 位 Ubuntu 上进行测试,其中 long 恰好是 64 位。
-
@stusmith:我明白了。那没关系。
-
@stusmith:你确定吗?我可以发誓
sizeof(long)在 32 位平台上使用 gcc 是 4。 -
@stusmith:Linux 使用 ILP32 和 LP64,这意味着
int总是 32 位,long long总是 64位(尽管我相信有一些关于将 DEC Alpha CPU 迁移到 128 位的讨论)和long始终与指针相同。所以,如果你在 32 位 Linux 上运行,那么你的 Haskell int 确实是两倍大小。
标签: c performance haskell