Ubuntu的计算工作量令人失望

时间:2012-02-23 17:03:06

标签: c macos ubuntu exp

我发现在Ubuntu下运行一些计算代码的性能相当差,在我用于科学计算的全新无头工作站机器上。我注意到在Ubuntu上运行一些稍微复杂的代码与我用于开发的旧Mac笔记本电脑上的速度有所不同。然而,我已经设法将它提炼成一个非常简单的例子,它仍然表现出比我的旧机器更少的改进:

#include <stdio.h>
#include <math.h>

int main() {
        double res = 0.0;
        for(int i=1; i<200000000; i++) {
                res += exp((double) 100.0/i);
        }
        printf("%lf", res);
        return(0);
}

现在Mac是运行OS X 10.5的近5年的2.4GHz Core 2 Duo MacBook Pro,它运行此代码大约6.8秒。然而,在运行Ubuntu 11.10的全新3.4GHz Core i7戴尔上大约需要6.1秒!有人可以告诉我这里发生了什么,因为一台近5年的笔记本电脑在全新桌面工作站的10%以内是荒谬的吗?这更加荒谬,因为我可以通过监控工具看到Core i7的涡轮增压功能接近4GHz!

Mac编译:

gcc -o test test.c -std=gnu99 -arch x86_64 -O2

Ubuntu编译:

gcc -o test test.c -std=gnu99 -m64 -O2 -lm

谢谢,

路易斯

6 个答案:

答案 0 :(得分:3)

  一台近5年的笔记本电脑在全新桌面工作站的10%以内是荒谬的

请记住,您正在对一个特定功能exp)进行基准测试。我们真的不知道您基准测试的exp()函数的两个实现是否相同(一个比另一个更好地优化是不可想象的。)

如果您要对不同的功能进行基准测试,结果可能会大不相同(可能更符合您的期望;或者不是)。

如果exp()确实是您实际应用的瓶颈,那么可以考虑使用快速近似。这篇论文提供了一个这样的近似值:A Fast, Compact Approximation of the Exponential Function

答案 1 :(得分:1)

正如其他人所指出的那样,您只是将exp( )的一个数学库实现与另一个数学库实现基准测试。如果您需要Linux上的高质量数学库,我建议您查看英特尔的编译工具(它带有一套优秀的库);它们也适用于OS X和Windows。

答案 2 :(得分:1)

尝试启用-ffast-math选项。这可能会让您在exp()的实施中不那么迂腐。那么问题是你是否想要可能产生的错误答案。

答案 3 :(得分:0)

您正在比较苹果和橙子,对于Mac,您允许进行针对ubuntu的体系结构特定优化。在两者上使用-O3 -march=native进行公平比较。

答案 4 :(得分:0)

要尝试的一些事项:

  • 确保您的CPU设置为在实验期间以全速运行。它可能是向上和向下切换,这会增加很多开销
  • 使用taskset将测试程序固定到一个核心,以便OS调度程序不会迁移它

答案 5 :(得分:0)

cpu周期数的差异仅为30%。鉴于我们不确切知道编译器生成了什么代码,我不会说这是荒谬的。新cpu的大部分性能提升都是内核数量,而你的代码没有使用它。

尝试展开循环也可能很有趣。速度比可能会改变。

int main() {
    double res0 = 0.0;        
    double res1 = 0.0;        
    double res2 = 0.0;        
    double res3 = 0.0;        
    double res4 = 0.0;        
    for(int i=1; i<200000000; i+=5) {
            res0 += exp((double) 100.0/i);
            res1 += exp((double) 100.0/(i+1));
            res2 += exp((double) 100.0/(i+2));
            res3 += exp((double) 100.0/(i+3));
            res4 += exp((double) 100.0/(i+4));
    }
    double res=res0+res1+res2+res3+res4;
    printf("%lf", res);
    return(0);
}