web-dev-qa-db-ja.com

実行時間がゼロのループ

実行時間がゼロのループを持つことは可能ですか?それに関連するオーバーヘッドがあるので、空のループでさえ実行時間が必要だと思います。

74
user3678189

はい、as-ifルールのもとでは、コンパイラーはコードの監視可能な動作をエミュレートすることのみが義務付けられているため、観察可能な動作は完全に最適化できるため、実行時間は実質的にゼロになります。

たとえば、次のコード:

int main()
{
  int j = 0 ;
  for( int i = 0; i < 10000; ++i )
  {
    ++j ;
  }
}

gcc 4.9フラグを使用して-O3でコンパイルすると、基本的には次のようになります(ライブで確認):

main:
  xorl  %eax, %eax  #
  ret

許可されているほとんどすべての最適化はas-ifルールに該当しますが、私が知っている唯一の例外は copy elison です。観察可能な動作に影響を与えることができます。

他のいくつかの例には dead code elimination が含まれ、コンパイラーが実行されないことを証明できるコードを削除できます。たとえば、次のループには実際に副作用が含まれていますが、実行されないことを証明できるため、最適化できます(実際に見る):

#include <stdio.h>

int main()
{
  int j = 0 ;
  if( false ) // The loop will never execute
  {
    for( int i = 0; i < 10000; ++i )
    {
      printf( "%d\n", j ) ;
      ++j ;
    }
  }
}

ループは前の例と同じように最適化されます。より興味深い例は、ループ内の計算を定数に演繹できるため、ループの必要性を回避できる場合です(これがどの最適化カテゴリに該当するかわからない)、例えば:

int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
  ++j ;
}
printf( "%d\n", j ) ;

実際に見る)に最適化できます:

movl    $10000, %esi    #,
movl    $.LC0, %edi #,
xorl    %eax, %eax  #
call    printf  #

ループが含まれていないことがわかります。

As-ifルールは標準でどこにカバーされていますか

as-ifルールは、C99標準ドラフトセクション5.1.2.3プログラムの実行言う:

抽象マシンでは、すべての式がセマンティクスで指定されたとおりに評価されます。実際の実装では、その値が使用されておらず、必要な副作用(関数の呼び出しや揮発性オブジェクトへのアクセスによって引き起こされるものも含む)が生成されていないと推定できる場合、式の一部を評価する必要はありません。

as-ifルール はC++にも適用され、gccはC++モードでも同じ結果になります。 C++ドラフト標準では、これをセクション1.9プログラムの実行で扱います。

この国際標準の意味論的記述は、パラメータ化された非決定論的な抽象マシンを定義しています。この国際規格は、適合実装の構造に要件を課していません。特に、抽象マシンの構造をコピーまたはエミュレートする必要はありません。むしろ、以下で説明するように、抽象マシンの観察可能な動作を(のみ)エミュレートするには、準拠する実装が必要です。

121
Shafik Yaghmour

はい-ループがデッドコードである(コンパイラーが実行しない)とコンパイラーが判断した場合、そのコードは生成されません。そのループの実行時間は0ですが、厳密に言うと、マシンコードレベルでは存在しません。

52

コンパイラーの最適化と同様に、一部のCPUアーキテクチャ、特にDSPには、ゼロのオーバーヘッドループがあり、これにより、反復回数が固定されたループが効果的に最適化されます。ハードウェア、例えば参照してください http://www.dsprelated.com/showmessage/20681/1.php

12
Paul R

コンパイラーは、副作用のない式または式の一部を評価する義務はなく、その結果は破棄されます。

Harbison and Steele、 C:Aリファレンスマニュアル

3
Maxim Chetrusca