C言語関係掲示板

過去ログ

No.1217 処理速度に関する実験

[戻る] [ホームページ]
No.16078

処理速度に関する実験
投稿者---Sciggepy(2004/08/06 00:20:40)


ここでは、プログラミング環境が限定されていないので質問させて頂きます。
現在、数式評価関数を作っているのですが、他の環境では処理にどの程度時間を要するのか、ということを知りたいと思っています。
もし宜しければ、実験にご協力ください。

実験内容は、1+log(abs(sin(2+3))*4)/5という式(文字列)の評価(計算)を10万回繰り返すというものですが、私の実験では、次の結果が得られました。

OS: Windows XP SP1
CPU: Pentium 4 2.80GHz

処理に要した時間(最も多く得られた値)
BCC 5.5の場合: 0.75秒
gcc 2.95.2(msvcrt.dllを使用)の場合: 2.453秒
(いずれも最適化なし)

ソースは入りきらないので(約16KB)、ここに置いておきます。(以前作ろうとしていたプログラムの残骸を強引に書き換えたため、かなり煩雑です。スタック領域が充分でない場合は、実行しないでください。)
3つのファイルをダウンロードし、test.cをコンパイルするだけで、実験用のアプリケーションができます。

実験結果のうち、私が知りたい情報は、OS、CPU、コンパイラ、処理に要した時間(5回程度試行し、その中で最も多く現れた値、もしくは、平均値をとります。)の4つです。
時間があれば、ぜひご協力ください。


No.16087

Re:処理速度に関する実験
投稿者---シャノン(2004/08/06 03:12:08)


OS:WinXP Pro SP1
CPU:Celeron 2.2GHz

コンパイラ:VC++.NET 2003
 最適化無し:
  最大値:3.064
  最小値:2.703
  中央値:2.864
  平均値:2.8598

 最適化あり:
  最大値:3.254
  最小値:2.533
  中央値:2.593
  平均値:2.7372

コンパイラ:VC++ 2005 Express Beta1
 最適化なし:
  最大値:2.733
  最小値:2.653
  中央値:2.723
  平均値:2.699

 最適化あり:
  最大値:2.543
  最小値:2.353
  中央値:2.493
  平均値:2.467

VC++2005 め、βのくせに速い…


No.16088

Re:処理速度に関する実験
投稿者---シャノン(2004/08/06 03:14:47)


VC++ は厳密にはコンパイラじゃなくて IDE だけど、まぁいいよね。
2003 は Enterprise Development Edition だったと思います。多分。


No.16090

Re:処理速度に関する実験
投稿者---tetrapod(2004/08/06 10:31:42)


DELL のノート P3-700MHz/815P/W2KSP4 では
cygwin (gcc-3.3.1) 最適化あり (gcc -O -g test.c -lm) 6.309x5
VC++6SP6 最適化なし (cl test.c) 4.887x3/4.897x2
VC++6SP6 最適化あり (cl -Ox2 test.c) 4.085x5
となりました。
hppa2.0w-hp-hpux11.00 では bus error (core dumped) します。
bigendian マシンでは動かないのかも?


No.16117

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/08 23:45:22)


>hppa2.0w-hp-hpux11.00 では bus error (core dumped) します。
bus errorですか...確か、メモリのアクセス境界を越えてアクセスしたための起こったものだと思うのですが(UNIXユーザーではないので、よく分かりません。)、そのエラーはどこで起こっているのでしょうか。
私としては、
*((double *)pResult)=(double)(r);
が怪しいと思います。


No.16120

Re:処理速度に関する実験
投稿者---tetrapod(2004/08/09 08:33:16)


eval.c:476 dRes=OPTD(op1)+OPTD(op2); で SIGBUS です。
OPTD の実装は #define OPTD(op) (*((double*)(op+1)))
ここで op1=0x40003468 op2=0x40003480 となっているのを確認しました。
「 double 変数は 8byte 境界からでないとアクセスできない」
ため、 BUS Error になったのでしょう。
ix86 では奇数バイトからのワードアクセスが認められていますが
(パフォーマンスを犠牲にした上で)
たいていの RISC 系 CPU では認められていません。

この辺修正すれば ix86 でも速度向上が望めるかもしれません。



No.16122

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/09 10:21:21)


ありがとうございました。
一応、
static double OPTD(const char *op)
{
    double d;
    memcpy(&d,op+1,sizeof(double));
    return d;
}
という方法も考えたのですが、速度が少し落ちるので、double型の値を入れるときは、sizeof(double)境界にします。
あと、文字列を扱っていた頃の名残で、ヒープ領域を何度も割り当てたり開放したりしていますが、その部分も全て取り払うことにします。


No.16127

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/09 17:42:46)


書き換えが完了しました。最初のものと比べると、1.5から2.5倍程度速度が上がり、ソースも小さくなりました。
まさしく、一石二鳥です。

後の人が見て内容不明にならないように、ソースは元の場所のものを置換して置いておきます。(全部あわせても、たったの12KBなので。)


No.16135

Re:処理速度に関する実験
投稿者---tetrapod(2004/08/10 10:12:40)


hppa2.0w-hp-hpux11.00+gcc-3.4.1 でうまく動きました(要修正1箇所)
gcc-3.4.1 gcc -O test2.c -lm で 1.400秒というところです。
先の DELL+VC++6 cl -Ox2 test2.c だと 0.66秒でした
# PC が速いというよりは旧式な WS が遅いというべきか...

修正点は test.c/test2.c の printf
(tm2-tm1)/CLOCKS_PER_SEC だと整数型に評価され %f に型一致しないので
(double)(tm2-tm1)/CLOCKS_PER_SEC にする必要があります。
# 前回言わなかったけど...
# そちらで表示されている値って正しいのだろうか?



No.16137

Re:処理速度に関する実験
投稿者---たか(2004/08/10 14:19:05)


メモリインターリーブをかけているとアラインミスで大幅にメモリアクセスが遅くなるようです。

元のプログラム
Pen4 2.8G(Single Channnel) + VC7.1(最適化なし)
1.833
AthlonXP 2500+(Single Channel 4Bank Interleave) + VC7.1(最適化なし)
8.641

改良プログラム
Pen4 2.8G(Single Channnel) + VC7.1(最適化なし)
1.266
AthlonXP 2500+(Single Channel 4Bank Interleave) + VC7.1(最適化なし)
1.268

単にAMD系のメモリ周りの弱さが出たのかも知れませんが。Athlon64だと
もっといい値が出るかも知れません。


No.16138

Re:処理速度に関する実験
投稿者---たか(2004/08/10 14:27:11)


失礼。OSを書くのを忘れていました。
両方ともWindowsXPSP1です。


No.16142

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/10 21:03:30)


>改良プログラム
>Pen4 2.8G(Single Channnel) + VC7.1(最適化なし)
>1.266
>AthlonXP 2500+(Single Channel 4Bank Interleave) + VC7.1(最適化なし)
>1.268
改良プログラムとは、新しく置いたプログラムのことですか?

OS、プロセッサは同じようですが、私の環境では、

test.c(最適化なし、試行回数=5)
BCC5.5: 0.391*1, 0.407*1, 0.390*1, 0.406*2
gcc 3.1.0(MinGW-msvcrt.dll): 0.859*3, 0.875*1, 0.843*1

という結果になりました。
ここまで値に差が出るのは、メモリへのアクセス速度などの差によるものでしょうか。私のPCでは、
DDR SDRAM DIMM
320MHz
256MB*2
のメモリを使っています。



No.16143

Re:処理速度に関する実験
投稿者---たか(2004/08/10 21:33:04)


申し訳ない!timeではなくて処理結果の方を見ていました。
そうです。改良後とは8バイトアラインにされた新しいプログラムの方です。
(test1.c)

Pentium4 + VC7.1(最適化無し) 0.656
Pentium4 + BCC5.6.4(最適化無し) 0.547
Athlon2500+ + VC7.1(最適化無し) 1.688
Athlon2500+ + BCC5.6.4(最適化無し) 0.719

改良前の物は変わりません。
こうしてみるとAMD系はVC7.1と相性が悪く、Pentium4向けのコードを
吐いているのではないかと思えてきます。


No.16144

Re:処理速度に関する実験
投稿者---たか(2004/08/10 21:39:21)


そしてお察しの通り、Pentium4のメモリはPC2100 512MB×2です。今と
なっては古いですね。しかもマザボの方でメモリインターリーブがかけ
られない(845E)ですので余計にレイテンシの影響が出ているのだと思います。

PC3200 Dual Channel + HT にしようかと何回か思いましたが、Athlon64も
一般的になってきたことですし思いとどまっています(実用上全く問題は
ありませんので)。それよりAthlonXPはPC2700なのに遅いですよね。CPUの
本当のクロック周波数が1.833GHzと遅い(Barton)のが原因かもしれません。



No.16145

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/10 22:54:36)


>申し訳ない!timeではなくて処理結果の方を見ていました。
!!

>Pen4 2.8G(Single Channnel) + VC7.1(最適化なし)
>1.266
>AthlonXP 2500+(Single Channel 4Bank Interleave) + VC7.1(最適化なし)
>1.268
正常に動作すると、
retval=1.268870
が出力されるはずですが...

ちなみに、EVMAX_TOKを16にしたところ、少し速度が上がりました。double型で信頼できる桁数は15か16程度なので、妥当な値だと思います。(数値や関数の後は必ず0(演算子、または、空の要素)がくるので、EVTKLITEM構造体のtokenをすべて文字で埋めても問題ありません。)



No.16146

Re:処理速度に関する実験
投稿者---たか(2004/08/10 23:07:31)


>正常に動作すると、
>retval=1.268870
>が出力されるはずですが...

はい、端折って書いていました。1.266という時間はぱっと見ただけなの
で見間違えたのだと思います。1.268は皆さん小数点以下3桁しか書いて
なかったのでそれに従いました。全部違っていたのですね・・・・

AthlonXPはあれから何度かテストをしてみましたが、Pentium4並の速度
が出る場合もありました。(2500+と銘打っているんですからね)
バックグラウンドで何か動いていると正しく計測できませんね。ただ、
今はそいつが止められない状態でして。



No.16152

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/11 12:34:30)


>EVTKLITEM構造体のtokenをす>べて文字で埋めても問題ありません。
(自分へのツッコミ)嘘です。そんなことはありません。最後の要素が16文字以上になると、確保した領域を超えた部分へのアクセスが発生します。

eval_fmltotokの
if(ct<EVMAX_TOK) pTKL[idx].token[ct++]=szFormula[i];
の部分は、やはり
if(ct<EVMAX_TOK-1) pTKL[idx].token[ct++]=szFormula[i];
と書き換えるべきでした。



No.16141

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/10 20:12:13)


>修正点は test.c/test2.c の printf
>(tm2-tm1)/CLOCKS_PER_SEC だと整数型に評価され %f に型一致しないので
>(double)(tm2-tm1)/CLOCKS_PER_SEC にする必要があります。
処理系によっては、整数型として評価されるのでしょうか?
BCC 5.5、gcc 3.1.0(MinGW)では問題ありませんでした。

># 前回言わなかったけど...
># そちらで表示されている値って正しいのだろうか?
何の値のことですか?
retvalは、電卓の値と比べると、小数点下16桁目まで正しいようです。



No.16147

Re:処理速度に関する実験
投稿者---tetrapod(2004/08/11 08:21:26)


>処理系によっては、整数型として評価されるのでしょうか?
>BCC 5.5、gcc 3.1.0(MinGW)では問題ありませんでした。
CLOCKS_PER_SEC の定義ですが、
VC++6.0SP6 : #define CLOCKS_PER_SEC 1000
BCC5.5.1 : #define CLOCKS_PER_SEC 1000.0
hpux11.00 : #define CLOCKS_PER_SEC 1000000
cygwin : #define CLOCKS_PER_SEC 1000
となっていて BCC5.5.1 以外はすべて整数型です。
clock_t は整数型でなければならないので
(tm2-tm1)/CLOCKS_PER_SEC は BCC55 以外ではすべて汎整数型に評価されます。
# cygwin(gcc-3.3.1) と mingw で CLOCKS_PER_SEC 違うのだろうか?

>何の値のことですか?
>retvalは、電卓の値と比べると、小数点下16桁目まで正しいようです。
retval ではなく時間の値ですね。
%f で整数型の数値を表示することはできないので。



No.16149

Re:処理速度に関する実験
投稿者---Sciggepy(2004/08/11 11:23:39)


># cygwin(gcc-3.3.1) と mingw で CLOCKS_PER_SEC 違うのだろうか?
gcc 3.2.3(MinGW 3.1.0)では、CLOCKS_PER_SECは((clock_t)1000)と定義されていました。
試しに、
printf("retval=%f\ntime=%f\n",d,(tm2-tm1)/CLOCKS_PER_SEC);
として実行したところ、timeの値は0になりました。

ただ、前の2.95.2では問題なかったので、ヘッダファイルを確認すると、CLOCKS_PER_SECは1000.0と定義されていました。
(ダウンロード元
ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2



No.16150

Re:処理速度に関する実験
投稿者---シャノン(2004/08/11 12:26:53)


>># cygwin(gcc-3.3.1) と mingw で CLOCKS_PER_SEC 違うのだろうか?

最初に言っとくべきかなー、とも思ったんですが。
VC++ 7.1 でも 1000 です。
なので、( tm2 - tm1 ) を勝手に double にキャストさせていただきやした。
そーでないと 0.000000 になっちゃうので。


No.16153

Re:処理速度に関する実験
投稿者---たか(2004/08/11 13:07:54)


>VC++ 7.1 でも 1000 です。
>なので、( tm2 - tm1 ) を勝手に double にキャストさせていただきやした。
>そーでないと 0.000000 になっちゃうので。

あ、言いませんでしたけど私も勝手にキャストさせていただきました。
このベンチマークは(どのベンチマークもそうだろうけど)二次キャッシュ
の容量とメインメモリのアクセス時のレイテンシが大きく影響するよう
です。


No.16101

ご協力ありがとうございました。
投稿者---Sciggepy(2004/08/06 17:28:32)


参考までに、他の実験の結果です。マシン、OSは同じです。

最適化ありの場合(試行回数=5)

bcc32 -WC -O2 test.c
0.765(秒)*2(回) 0.766*3 (速度を最適化した方が遅くなる。)

gcc -O test.c
2.031*2 2.046*3 (BCC強し(@@>))

vectorからダウンロードしたCalcXとの比較
(CalcXではabsが使えないため、式を1+log((-1)*sin(2+3)*4)/5に変更して実験しました。)

コンパイラ: BCC
最適化なし

eval 0.922*3 0.937*1 0.938*1
CalcX 7.547*1 7.516*2 7.531*1 7.515*1

ご協力ありがとうございました。