6

科学計算に使用している新しいヘッドレスワークステーションマシンで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はOSX10.5を実行しているほぼ5年前の2.4GHzCore2 Duo MacBook Proであり、このコードを約6.8秒で実行します。ただし、Ubuntu11.10を実行している新しい3.4GHzCore i7 Dellでは、約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

ありがとう、

ルイ

4

6 に答える 6

3

5 年近く前のラップトップが新品のデスクトップ ワークステーションの 10% 以内というのはばかげています。

特定の 1 つの関数( )をベンチマークしていることに注意してくださいexp。ベンチマークしている関数の 2 つの実装が同一であるかどうかはわかりませんexp()(一方が他方よりも最適化されていることは考えられません)。

別の関数のベンチマークを行った場合、結果はまったく異なるものになる可能性があります (おそらく、期待に沿っているかどうかは別として)。

exp()が実際のアプリケーションのボトルネックである場合、1 つの可能性は高速近似の使用を検討することです。これは、そのような近似の 1 つを提供する論文です:指数関数の高速でコンパクトな近似。

于 2012-02-23T17:40:19.247 に答える
1

-ffast-mathオプションをオンにしてみてください。これにより、exp(). 問題は、生成される可能性のある間違った答えが必要かどうかです。

于 2012-02-24T23:17:16.437 に答える
1

exp( )他の人が指摘したように、ある数学ライブラリの実装を別のライブラリに対してベンチマークしているだけです。Linux で高品質の数学ライブラリが必要な場合は、Intel のコンパイラ ツール (優れたライブラリ セットが付属) を検討することをお勧めします。OS X および Windows でも利用できます。

于 2012-02-23T18:57:48.630 に答える
0

リンゴとオレンジを比較しています。Macの場合、ubuntuにはないアーキテクチャ固有の最適化が可能です。-O3 -march=native公正な比較を行うために両方で使用してください。

于 2012-02-23T17:49:44.537 に答える
0

試してみるいくつかのこと:

  • 実験中は、CPU がフル スピードで動作するように設定されていることを確認してください。上下にトグルする可能性があり、多くのオーバーヘッドが追加されます
  • を使用してテスト プログラムを 1 つのコアtasksetに固定し、OS スケジューラがそれを移行しないようにします。
于 2012-02-23T18:43:08.667 に答える
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);
}
于 2012-02-23T19:06:44.817 に答える