问题 C ++和Haskell代码在不同的机器上的执行时间不同


我想问你是什么导致了这种差异。如果我编译以下程序并运行相同的二进制文件 - 在某些平台上,由C ++代码生成的程序比Haskell程序快得多,而在另一些平台上则相反。

另外,根据它们构建的平台,最终二进制文件的性能有很大差异。 (每个平台使用相同的标志和相同版本的LVM和clang)

代码已经过优化,应该可以使用相似的性能 - 请参阅: Haskell可以像Clang / GCC一样优化函数调用吗?

我想问你,怎么可能。

C ++代码:

#include <cstdio>
#include <cstdlib>

int b(const int x){
    return x+5;
}

int c(const int x){
    return b(x)+1;
}

int d(const int x){
    return b(x)-1;
}

int a(const int x){
    return c(x) + d(x);
}

int main(int argc, char* argv[]){
    printf("Starting...\n");
    long int iternum = atol(argv[1]);
    long long int out = 0;
    for(long int i=1; i<=iternum;i++){
        out += a(iternum-i);
    }
    printf("%lld\n",out);
    printf("Done.\n");
}

用。编译 clang++ -O3 main.cpp

haskell代码:

module Main where
import qualified Data.Vector as V
import System.Environment
b :: Int -> Int
b x = x + 5
c x = b x + 1
d x = b x - 1
a x = c x + d x
main = do
   putStrLn "Starting..."
   args <- getArgs
   let iternum = read (head args) :: Int in do
      putStrLn $ show $ V.foldl' (+) 0 $ V.map (\i -> a (iternum-i))
         $ V.enumFromTo 1 iternum
      putStrLn "Done."

用。编译 ghc -O3 --make -fforce-recomp -fllvm ghc-test.hs

结果(在不同平台上测试相同的二进制文件)

// binaries compiled on Ubuntu:
Ubuntu x64 @ Intel i7-3610QM CPU @ 2.30GHz : C++:0.775s, GHC:1.01s
Gentoo x64 @ Intel i7-Q720   CPU @ 1.6GHz  : C++:3.6s,   GHC:2.1s

// binaries compiled on Gentoo:
Ubuntu x64 @ Intel i7-3610QM CPU @ 2.30GHz : C++:0.782s, GHC:1.01s
Gentoo x64 @ Intel i7-Q720   CPU @ 1.6GHz  : C++:2.3s,   GHC:1.3s

4282
2017-07-01 19:39


起源

编译器的输出可以针对不同的芯片组进行优化。我将重复我上次提出的问题:检查装配输出。 - chrisaycock
@chrisaycock我上次没有看到你的评论 - 我会做的 - Wojciech Danilo
@ H2CO3:“C ++是一种编译语言,Haskell是一种解释型语言。”这是错误的。 GHC是一个编译器。它生成本机代码。语言本身既不被解释也不被编译,但是可以为任何实用语言编写解释器或编译器,包括C ++。 - Dietrich Epp
这些是不同的系统,具有不同的内核,不同的特征,可能是您使用不同性能配置文件链接到的不同库。没有理由想象他们会有相同的性能配置文件! - sclv
将它们编译为“静态”以消除由动态库引起的任何差异。 - auselen


答案:


如果我编译以下程序并运行相同的二进制文件 - 在某些平台上,由C ++代码生成的程序比Haskell程序快得多,而在另一些平台上则相反。

另外,根据它们构建的平台,最终二进制文件的性能有很大差异。 (每个平台使用相同的标志和相同版本的LVM和clang)

您正在看到真实计算机令人讨厌的操作细节的影响:

  • 链接器优化
  • 不同版本的动态加载库
  • 给定微架构的汇编代码生成质量
  • 访问专门的说明
  • 缓存大小
  • 操作系统调度程序,分配器,...
  • 记忆延迟

两个平台之间存在大量不同的代码和硬件,这意味着您最终会测量不同的东西。

没有理由期望性能相同,甚至是相同的比例。对于微基准测试,在移动平台时翻转相对排序并不罕见。


16
2017-07-02 09:27