ダウンロード ソースコードのダウンロード (53.8 KB)
C++のテスト
今度はC++で同様のことを試してみましょう。
void generate_randoms( int randoms[] )
{
for( int i = 0; i < N_GENERATED; i++ )
randoms[i] = rand();
}
厳密なことを言えば、Javaで生成される数値はC++で生成される数値と同じではありません。従って、両方の実装で同じ数値セットが使われるという保証はありません。もっとも、両者の差異はそれほどないはずです。
C++での計算処理はJavaと似ています。
void nativeCompute(int randoms[])
{
int result = 0;
for(int i = 2; i < N_MULTIPLY; i++)
{
for( int j = 0; j < N_GENERATED; j++ )
{
result = randoms[j] * i;
result++;
}
}
}
C++には演算の時間をミリ秒単位の精度で測定する標準的な方法がなさそうなので、このコードはWindowsプラットフォームに的を絞っています。QueryPerformanceCounter関数を使用すると、高精度のタイマーにアクセスできます。この関数を使用するため、このコードでは2つのメソッド(StartとStop)を持つ簡素な「ストップウォッチ」クラスを利用しています。この時間測定に基づいて、このクラスは2つのメソッドがそれぞれいつ呼び出されたかを記録し、ミリ秒単位の時間差を返します。
// Stop watch class.
class CStopWatch
{
public:
// Constructor.
CStopWatch()
{
// Ticks per second.
QueryPerformanceFrequency( &liPerfFreq );
}
// Start counter.
void Start()
{
liStart.QuadPart = 0;
QueryPerformanceCounter( &liStart );
}
// Stop counter.
void Stop()
{
liEnd.QuadPart = 0;
QueryPerformanceCounter( &liEnd );
}
// Get duration.
long double GetDuration()
{
return ( (liEnd.QuadPart - liStart.QuadPart) / long double(liPerfFreq.QuadPart) ) * 1000; //return result in milliseconds
}
private:
LARGE_INTEGER liStart;
LARGE_INTEGER liEnd;
LARGE_INTEGER liPerfFreq;
};
同様のパターンを利用して、ストップウォッチクラスでかかった時間の平均値を知ることができます。
long double test_times( long double diffs[] )
{
long double shortest = 65535;
long double longest = -1;
long double total = 0;
for( int i = 0; i < N_ITERATIONS; i++ )
{
if( shortest > diffs[i] )
shortest = diffs[i];
else if( longest < diffs[i] )
longest = diffs[i];
total += diffs[i];
}
total -= shortest;
total -= longest;
total /= ( N_ITERATIONS - 2 );
return total;
}
このパターンでは次の実装が必要です(IntMaths.cに入っています)。
int main(int argc, char* argv[])
{
int randoms[N_GENERATED];
generate_randoms( randoms );
CStopWatch watch;
long double timeNative[N_ITERATIONS];
for( int i = 0; i < N_ITERATIONS; i++ )
{
watch.Start();
nativeCompute(randoms);
watch.Stop();
timeNative[i] = watch.GetDuration();
}
printf( "C computing took %lf\n", test_times(timeNative) );
return 0;
}
上記のコードはサンプルコードに含まれているIntMathsプロジェクトに入っています。筆者のラップトップで実行すると、次の結果が返されます(測定値の単位はミリ秒)。
C computing took 0.001427
つまり、約10,000,000回の算術演算を実行するのに約1/1000ミリ秒を要したことになります。
Javaでは25msであるのに対して、C++では0.001msです。大変な違いがあります。ただし、C++コードのコンパイルではフルコンパイラとリンカで速度の最適化が行われていることを忘れてはなりません。最適化を無効にすれば、次の結果が返されます。
C computing took 70.179901
驚いたことに、Javaバージョンより3倍も遅いではありませんか。つまり、こういうことです。一見したところではC++の方が速いのですが、それはコンパイラがコードをうまく最適化する場合に限られるのです(この点は非常に重要です)。
今日の大多数のC++コンパイラは、生成するコードをかなりうまく最適化します。とはいえ、1/1000ミリ秒になるか70ミリ秒になるかはコンパイラに委ねられています。速さゆえにC++に切り替えようという人は、このことを忘れないでください。
この記事は参考になりましたか?
- japan.internet.com翻訳記事連載記事一覧
- この記事の著者
-
japan.internet.com(ジャパンインターネットコム)
japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
Liviu Tudor(Liviu Tudor)
英国在住のJavaコンサルタント。特にオンラインメディアセクタの高可用性システムに関して豊富な経験を持つ。Javaに長年取り組んでいるうちに、パフォーマンスが問題になるアプリケーションをうまく機能させるために必要なのは肥大したミドルウェアフレームワークではなく「低レベル」のコアJavaであると悟る。...
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
