ベンチマーク

次の様なコードを書いてベンチマークを取りました。

#include <stdio.h>
#include <stdlib.h>
#include <xmmintrin.h>
#include <windows.h>

template<int N> int f2i(float f)
{
  return (int)f;
}

template<> int f2i<1>(float f)
{
  return _mm_cvttss_si32(_mm_load_ss(&f));
}

template<> int f2i<2>(float f)
{
  return _mm_cvttss_si32(_mm_set_ss(f));
}

template<> int f2i<3>(float f)
{
  _asm {
    movss xmm0, f
    cvttss2si eax, xmm0
  }
}

template<> int f2i<4>(float f)
{
  _asm {
    cvttss2si eax, f
  }
}

template<int N> void process(float f)
{
  LARGE_INTEGER li;
  QueryPerformanceCounter(&li);
  int sum = 0;
  for(size_t i = 0; i < 1024 * 1024; i++)
  {
    f *= f;
    sum += f2i<N>(f);
  }
  LARGE_INTEGER liEnd;
  QueryPerformanceCounter(&liEnd);
  printf("sum=%d TIME=%u\n", sum, (int)(liEnd.QuadPart - li.QuadPart));
}

int main(int argc, char* argv[])
{
  float f = atoi(argv[1]);
  process<0>(f);
  process<1>(f);
  process<2>(f);
  process<3>(f);
  process<4>(f);
}

VC8 /OxなコードをCore Duo T2500上での結果は、だいたい理想的な結果の奴だと、

sum=234740 TIME=1470631
sum=234740 TIME=1418952
sum=234740 TIME=1409258
sum=234740 TIME=1421215
sum=234740 TIME=1404352

のような感じ。キャスト版が群を抜いて遅いが、それ以外は、誤差のようなものか。


おもしろいのは、VC7.1 (.NET 2003)での結果。

sum=-958466572 TIME=2900252
sum=234740 TIME=1338547
sum=234740 TIME=1347701
sum=234740 TIME=1904928
sum=234740 TIME=1857062

キャスト版の結果だけ違うし、速度も他と比べて2倍程度違う。ここまで遅いと他の処理方法を考えたくなるのは当たり前。そして、面白いことに、組み込み関数版が最も速いだけではなく、VC8のコードの速度を上回っている。それもぶっちぎりで。アセンブラ版は最適化の度合いが低いせいか、VC8のキャストよりも断然遅い結果に。