performance - 在 Haskell 中将所有数字从 1 加到 10 亿

标签 performance haskell

目前我正在追赶 Haskell,到目前为止我印象非常深刻。作为一个 super 简单的测试,我编写了一个程序来计算总和到十亿。为了避免创建列表,我写了一个应该是尾递归的函数

summation start upto 
  | upto == 0 = start
  | otherwise = summation (start+upto) (upto-1)

main = print $ summation 0 1000000000

使用 -O2 运行它,我的机器上运行时间约为 20 秒,这让我感到惊讶,因为我认为编译器会更加优化。作为比较,我写了一个简单的 c++ 程序
#include <iostream>

int main(int argc, char *argv[]) {
  long long result = 0;
  int upto = 1000000000;

  for (int i = 0; i < upto; i++) {
    result += i;
  }
  std::cout << result << std::end;
  return 0;
}

在没有优化的情况下使用 clang++ 编译运行时间约为 3 秒。所以我想知道为什么我的 Haskell 解决方案这么慢。有人有想法吗?

在 OSX 上:

铿锵++--版本:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.2.0
Thread model: posix

ghc --版本:
The Glorious Glasgow Haskell Compilation System, version 7.10.3

最佳答案

添加类型签名将我的运行时间从 14.35 秒降低到 0.27。它现在比我机器上的 C++ 更快。当性能很重要时,不要依赖类型默认。 Ints 不适合在 Web 应用程序中对域进行建模,但如果你想要一个紧密的循环,它们就很棒。

module Main where

summation :: Int -> Int -> Int
summation start upto 
  | upto == 0 = start
  | otherwise = summation (start+upto) (upto-1)

main = print $ summation 0 1000000000


[1 of 1] Compiling Main             ( code/summation.hs, code/summation.o )
Linking bin/build ...
500000000500000000
14.35user 0.06system 0:14.41elapsed 100%CPU (0avgtext+0avgdata 3992maxresident)k
0inputs+0outputs (0major+300minor)pagefaults 0swaps

Linking bin/build ...
500000000500000000
0.27user 0.00system 0:00.28elapsed 98%CPU (0avgtext+0avgdata 3428maxresident)k
0inputs+0outputs (0major+171minor)pagefaults 0swaps

关于performance - 在 Haskell 中将所有数字从 1 加到 10 亿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35019918/

相关文章:

mysql - 如何在 Perl 中提高此 MySQL 查询的性能,直接在 MySQL Workbench 中执行的相同查询快 1600 倍

haskell - 如何删除reactive-banana中的重复事件

performance - if then else 的效率.... break 与 if break if break

c++ - 如何有效地规范化 vector C++

c++ - 氧气,太重而无法维持?

list - 需要根据元素升序的中断将列表划分为列表(Haskell)

scala - 有使用软件事务内存的实际经验吗?

haskell - 通过 nix-build 运行时是否可以保留 Cabal 生成的测试套件日志?

parsing - 为什么 Haskell 的 Prelude.read 不返回 Maybe ?

javascript - 什么是setTimeout(function(){//dostuff}, 0);究竟应该怎么做?