【发布时间】:2012-10-04 15:18:46
【问题描述】:
我有这个 haskell 文件,用 ghc -O2 (ghc 7.4.1) 编译,在我的机器上需要 1.65 秒
import Data.Bits
main = do
print $ length $ filter (\i -> i .&. (shift 1 (i `mod` 4)) /= 0) [0..123456789]
在 C 中使用 gcc -O2 (gcc 4.6.3) 编译的相同算法在 0.18 秒内运行。
#include <stdio.h>
void main() {
int count = 0;
const int max = 123456789;
int i;
for (i = 0; i < max; ++i)
if ((i & (1 << i % 4)) != 0)
++count;
printf("count: %d\n", count);
}
更新
我认为这可能是Data.Bits 的东西变慢了,但令人惊讶的是,如果我取消变速并直接执行mod,它实际上运行更慢 5.6 秒!?!
import Data.Bits
main = do
print $ length $ filter (\i -> (i `mod` 4) /= 0) [0..123456789]
而等效的 C 以 0.16 秒的速度运行稍快:
#include <stdio.h>
void main() {
int count = 0;
const int max = 123456789;
int i;
for (i = 0; i < max; ++i)
if ((i % 4) != 0)
++count;
printf("count: %d\n", count);
}
【问题讨论】:
-
Haskell 等效于
%是rem,而不是mod。后者对负数有额外的检查,见stackoverflow.com/questions/339719 -
将
[0..123456789]替换为([0..123456789] :: [Int])有帮助吗?只是想知道你是否得到了一些不幸的Num实例推断(例如Integer)。 -
FWIW,使用
-O2 -fllvm -funfolding-use-threshold1000编译让我运行得很快(与 C 差不多)。 (编辑:实际上不是,只是“更快”——我在两者之间进行了一些其他更改,使其与 C 一样快。) -
这段代码看起来可以融合成一个循环,但是当我查看核心输出时,
filter的调用生成了一个列表。这可能就是 ghc 较慢的原因。 -
@Heatsink:这不会熔断,因为
lengthis not a "good consumer"。
标签: haskell