#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <windows.h>
#define PI 3.14159265358979323846264
int cubic_equation( double a, double b, double c, double d, double roots[] );
int main(){
double a, b, c, d, roots[ 3 ];
int i, n;
DWORD started, terminated;
started = GetCurrentTime();
for ( i = 1; i <= 1000000; i++ ){
a = rand(); b = rand(); c = rand(); d = rand();
if ( a != 0 ) n = cubic_equation( a, b, c, d, roots );
}
terminated = GetCurrentTime();
printf( " total %10.3f seconds\n", ( terminated - started ) * 1e-3 );
return 0;
}
double cubic_root( double x ){
double root, prev_root, eps;
int converged, n;
if ( x == 0 ) return 0;
else {
converged = 0;
root = 1e0;
n = 1;
do {
prev_root = root;
root -= ( root * root * root - x ) / ( 3 * root * root );
eps = fabs( root / prev_root - 1e0 );
if ( ( eps < 1e-8 ) || ( fabs( root ) < 1e-8 ) ) converged = 1;
n++;
} while ( converged == 0 );
return root;
}
}
int cubic_equation( double a, double b, double c, double d, double roots[] ){
double p, q, t, a3, b3;
int num_realroots;
b /= ( 3 * a ); c /= a; d /= a;
p = b * b - c / 3;
q = ( b * ( c - 2 * b * b ) - d ) / 2;
a = q * q - p * p * p;
if ( a > 0 ){
num_realroots = 1;
if ( q > 0 ) a3 = cubic_root( q + sqrt( a ) );
else a3 = cubic_root( q - sqrt( a ) );
b3 = p / a3;
roots[ 0 ] = a3 + b3 - b;
roots[ 1 ] = -0.5 * ( a3 + b3 ) - b;
roots[ 2 ] = fabs( a3 - b3 ) * sqrt( 3e0 ) / 2;
}
else {
num_realroots = 3;
a = sqrt( p );
t = acos( q / ( p * a ) );
a *= 2;
roots[ 0 ] = a * cos( t / 3 ) - b;
roots[ 1 ] = a * cos( ( t + 2 * PI ) / 3 ) - b;
roots[ 2 ] = a * cos( ( t + 4 * PI ) / 3 ) - b;
}
return num_realroots;
}
関数cubic_rootはf(x)=x^3-a=0の根をNewton-Raphson法で求めるものである.
pow(a,1e0/3e0)などとするよりも誤差は小さくなるだろう.上記コードをVisual C/C++ 5.0でコンパイルしたバイナリ(45KB)
今回はPCだけでなくUNIX系マシンでもベンチマークを取ってみた.
ただし,UNIXではGetCurrentTime()などという関数は無いので
timeコマンドを使って実行時間を計測する.
time はcshおよびtcshの内部コマンドと/usr/bin/timeの2種類がある.
例えば,カレントにあるa.outの実行時間を計測する場合は
以下のようにすればよい.
出力結果は「a.outというコマンドの実行には11.67秒かかり,
そのうちユーザモードで11.660秒,システムのオーバーヘッドで0.010秒消費した」という意味になる.
その後の出力はファイルシステムとの入出力などに関する情報を示している.
くわしくはここ.
$ time ./a.out
11.660u 0.010s 0:11.67 100.0% 0+0k 0+0io 82pf+0w
テストしたマシンのCPU,メモリ容量,OSおよびバイナリ作成に用いたコンパイラを下表に示す.
CPU | Memory (MB) | OS | Compiler |
Pentium !!! 600MHz | 128 | Windows 2000 | Visual C/C++ 5.0 |
Pentium !!! 700MHz | 256 | Windows 98SE | Visual C/C++ 5.0 |
Athlon K7 650MHz | 256 | Windows 2000 | Visual C/C++ 5.0 |
Athlon K7 650MHz | 256 | Windows 98SE | Visual C/C++ 5.0 |
Athlon TB 1.2GHz | 128 | Windows Me | Visual C/C++ 5.0 |
Celeron 333MHz | 64 | Windows Me | Visual C/C++ 5.0 |
K6-2 300MHz | 98 | RedHat 6.2 | gcc ver. egcs-2.91.66 |
Alpha 667MHz | 768 | Digital UNIX 4.0 | Digital UNIX C Compiler 4.0 |
HP Visualize C180 | 256 | HP-UX ver.10.0 | HP-UX C Compiler |
結果は以下のようになった. コンパイラやOSがそれぞれ異なるので絶対的な比較はできないが,CPU速度比較の おおよその目安にはなるだろう.
CPU | Memory (MB) | OS | Compiler |
Celeron 633MHz | 128 | Windows 98SE | Visual C/C++ 5.0 |
Celeron 300A | 64 | Windows 98SE | Visual C/C++ 5.0 |
Pentium !!! 1GHz | 128 | Windows Me | Visual C/C++ 5.0 |
Athlon TB 1.4GHz | 128 | Windows 98SE | Visual C/C++ 5.0 |
Cyrix III 533MHz | 128 | Windows Me | Visual C/C++ 5.0 |
Pentium !!! 1GHzは予想通り速い. Athlon 1.4GHzは1.2GHzよりも遅い結果となったが, これは測定誤差+環境の違いによるものだろう. CyrixIIIは極めて遅く(ワースト1),Cyrixの伝統が引き継がれている.
SEO | [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送 | ||