2012-03-03 3 views
4

私のCコードを修正した後(元々はWindows用でVS 2008でコンパイル)、Linux上で実行しました。驚いたことに、今はWindows版より少なくとも10倍遅いです。Windowsと比較してLinuxでコードが遅い

/* advance by n bits */ 

void Flush_Buffer(N) 
int N; 
{ 
int Incnt; 


ld->Bfr <<= N; 

Incnt = ld->Incnt -= N; 

if (Incnt <= 24) 
{ 
if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4)) 
{ 
do 
{ 
if (ld->Rdptr >= ld->Rdmax) 
     Next_Packet(); 
    ld->Bfr |= Get_Byte() << (24 - Incnt); 
    Incnt += 8; 
    } 
    while (Incnt <= 24); 
} 
else if (ld->Rdptr < ld->Rdbfr+2044) 
{ 
    do 
    { 
    ld->Bfr |= *ld->Rdptr++ << (24 - Incnt); 
    Incnt += 8; 
    } 
    while (Incnt <= 24); 
} 
else 
{ 
    do 
    { 
    if (ld->Rdptr >= ld->Rdbfr+2048) 
     Fill_Buffer(); 
    ld->Bfr |= *ld->Rdptr++ << (24 - Incnt); 
    Incnt += 8; 
    } 
    while (Incnt <= 24); 
} 
ld->Incnt = Incnt; 
} 

} 

この機能は、Windows上で無視できない時間を取っていた:私は次の関数は、アプリケーションに費やされた時間のほとんどを消費していることを考え出しプロファイラツールを使用して

。 Linuxでは14秒近くかかります。私はここで何を間違えたのですか?

このコードセクションはOS固有の呼び出しから独立している必要があります。したがって、同じ時間に実行する必要があります。

(私の推測:この関数は複数回呼び出されているため、プロファイラがすべての呼び出しの時間を累積している可能性があります。そのような場合は、関数がその関数を取得していない可能性があります)Windowsの場合と比較してすぐに入力パラメータ。

ここで私は間違っていますか?どんな推測?

Rgrds、あなたがカウンターにあなたのコード内のすべてのコードパスに注釈を付けることを試みることができ

H

+4

少なくとも、(1)使用したコンパイラオプションと、(2)費やした時間をどのように測定しているかを問わない限り、この質問は無意味です。 –

+0

どのようにコードをコンパイルしましたか(コンパイラ、オプション、警告レベル) – Mat

+0

別の推測では、2つのマシンでデータ型のサイズが異なるため、Linux上でさらに低レベルで計算を行うことになるかもしれません。データ型のサイズが2つのシステムで一致しているかどうかを確認する必要があります。私は正しい方向に向かっていますか? – gpuguy

答えて

0

。プログラムの終わりに、各カウンタには、コードパスが何回実行されたかに関する情報が含まれます。 WindowsバージョンとLinuxバージョンとの間でこれらの数字を1行ずつ比較すると、が異なるコードパスに従っていることがわかります。コードパスの性質に応じて、の場合はという理由で、LinuxバージョンがWindowsバージョンより遅い理由を説明することができます。

int count[100]; 

// Call this function at the end of program 
void PrintCounts() { 
    int i; 
    for(i=0; i<100; i++) printf("%d\n", count[i]); 
} 

void Flush_Buffer(int N) { 
    int Incnt; 

    ld->Bfr <<= N; 

    Incnt = ld->Incnt -= N; 

    if (Incnt <= 24) { 
    count[0]++; 
    if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4)) { 
     count[1]++; 
     do { 
     count[2]++; 
     ... 
+0

ありがとう、私はあなたのコメントとしてそれをテストしており、あなたに戻ってきます – gpuguy

1

これは、回答よりも多くの注釈ですが、コメントにはあまり合いませんので、私には反対しないことを願っています。

「プロファイリング」という用語には、関連性はありますが異なる意味があります。抽象的な文脈では、通常は特定のランタイムデータに関してプログラムの「測定」を意味します。しかし、それはあなたのプログラムを単に「タイミングする」ことと同じではありません。タイミングはプロファイリングの1つの形式ですが、他にも多数あります。

たとえば、データ構造がstd::set(ツリー)またはstd::unordered_set(ハッシュテーブル)であるかどうかが不明であるとします。普遍的な答えはありません。なぜなら、使用するものと処理しているデータに依存するからです。あなたが使用しようとしている実際の実際のデータを指定するまで、が正しい答えを知ることはできません。その場合、「プロファイルと決定」は、プログラムの2つのバージョンを作成し、それらを実データに対して実行し、ランタイムを測定することを意味します。より速いものがおそらくあなたが望むものです。

一方、GCCには「プロファイラ」と呼ばれる非常に異なる目的のツールがあります。これは実行パスプロファイラで、プログラムのどこで(つまりどの関数で)時間を費やしているかを示します。サブルーチンがたくさんある複雑なアルゴリズムを使用している場合、どのサブルーチンが重要なのか分からず、実際には実際の入力に依存する可能性があります。その場合、プロファイラは入力データがの場合に最も多くの関数がであると判断し、これらの関数に最適化作業を集中することができます。現在、「最適化前のプロファイル」は、作業に入る前に優先順位を決定する必要があることを意味します。

しかし、比較のために、GCCプロファイラを使用しないでください。むしろ、両方のプラットフォームでコンパイルし、すべての最適化を有効にしてリリース条件で実行し、同じ入力データセットでランタイムを測定します。

+0

私はgccプロファイラを使用しないことをお勧めします。大きな関数の場合、オーバーヘッドは小さくなりますが、小さな関数の場合、関数に費やされる時間はプロファイリングオーバーヘッドによって支配されます。これは、gccプロファイラを使用すると、十分に考慮されたプログラムが恐ろしく実行され(ひどく歪んだプロファイリング結果を与える)ことを意味します。それからもちろん、選択的なインライン展開によって結果が歪んでいろいろな問題があります。あなたのプログラムでどこの時間が費やされたかを測定したいのであれば、実行可能な唯一の方法は命令ポインタとスタックの定期的なサンプリングを含む方法です。 oprofile。 –

関連する問題