22

プログラミングで非常に一般的なパターンは、ある種の更新後に最大値を制限することです。私が知りたいのは、次の2つのコードに違いがあるかどうか、そして1つを優先する必要があるかどうかです。

value += increment;
value = std::min(value, valueMax);

vs

value += increment;

if (value > valueMax)
    value = valueMax;

私の考えでは、これはCPUが2つの値を取り、最小値を生成するための命令を持っているかどうかにかかっていると思います。その場合、std :: minを呼び出すと、この命令が生成され、不要な分岐が回避されます。そうでない場合、2番目のバージョンはvalue<=valueMaxのときに不要な割り当てを回避します。

私はこの種のことはあまり得意ではありませんが、これを知っている古い学校のアセンブリハッカーがいると確信しています。彼らに私は尋ねます:どちらが良いですか?

4

4 に答える 4

14

最新のコンパイラは、どちらの場合でも同じコードを生成できるほどスマートです。たとえば、32 ビット GCC は次を生成します。

addl    %esi, %edi
cmpl    %edx, %edi
movl    %edi, %eax
cmovgl  %edx, %eax

64 ビット Clang:

%1 = add nsw i32 %increment, %value
%2 = icmp sgt i32 %1, %valueMax
%value = select i1 %2, i32 %valueMax, i32 %1
于 2013-03-21T05:44:49.207 に答える
4

次のコードのリリースの VC10 では、次のアセンブリがあります。

int main(int argc, char *argv[])
{ 
  int dummyValue = 0, valueMax = 3000, value = valueMax + 1;

  cin >> valueMax;
  cin >> value;

  dummyValue = std::min(value, valueMax);

  cout << dummyValue;
  cin >> valueMax;
  cin >> value;

  if (value > valueMax)
    dummyValue = valueMax;

  cout << dummyValue;
  return 0;
}

生成:

  24:   dummyValue = std::min(value, valueMax);
00E112AF  mov         eax,dword ptr [valueMax]  
00E112B2  cmp         eax,dword ptr [value]  
00E112B5  lea         edx,[value]  
00E112B8  lea         ecx,[valueMax]  
00E112BB  cmovge      ecx,edx     // <-- this is our conditional assignment
00E112BE  mov         esi,dword ptr [ecx]  

if (value > valueMax)
  dummyValue = valueMax
00E112ED  mov         eax,dword ptr [valueMax]  
00E112F0  cmp         dword ptr [value],eax  
00E112F3  mov         ecx,dword ptr ds:[0E13038h]  
00E112F9  cmovg       esi,eax  

したがって、どちらの場合も または のいずれcmovgeかのcmovg命令に最適化されています。

それは声明std::minよりも意図をよく示しているので、私はまだ行きます. if最適化されており、読みやすくなっています。

于 2013-03-21T05:45:26.120 に答える
0

答えは、値のタイプによって異なります。すべての操作がコード オプティマイザーに対して完全に透過的である場合、コードは効果的に最適化される可能性があります。ただし、値が std::string の場合もコードがコンパイルされ、代入が条件付きであるため、2 番目のバージョンの方が高速になる可能性があります。

于 2013-03-21T08:24:52.540 に答える