Re: dmd 2.058 のリリース

投稿ツリー


このトピックの投稿一覧へ

なし Re: dmd 2.058 のリリース

msg# 1.2.1
depth:
2
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2012/3/3 3:27
SHOO  管理人   投稿数: 658
御返事遅くなりました。

ちょっとだけ調べてみました。

#code(d){{{
foreach (i; 0..0x3FFF)
{
c[] += a[] * b[];
a[] += rnds[i&0xf];
c[] = a[] * b[];
b[] -= rnds[i&0xf];
}
}}}
このコードは、
#code(console){{{
dmd -O -release -inline -c main
obj2asm main>output.txt
}}}
として吐いたアセンブリでは
#code(asm){{{
L168: push dword ptr -018B4h[EBP]
push dword ptr -018B8h[EBP]
push dword ptr -018ACh[EBP]
push dword ptr -018B0h[EBP]
push dword ptr -018A4h[EBP]
push dword ptr -018A8h[EBP]
call near ptr __arraySliceSliceMulSliceAddass_d
mov ESI,EBX
and ESI,0Fh
push dword ptr -08Ch[ESI*8][EBP]
push dword ptr -090h[ESI*8][EBP]
push dword ptr -018B4h[EBP]
push dword ptr -018B8h[EBP]
call near ptr __arrayExpSliceAddass_d
push dword ptr -018B4h[EBP]
push dword ptr -018B8h[EBP]
push dword ptr -018ACh[EBP]
push dword ptr -018B0h[EBP]
push dword ptr -018A4h[EBP]
push dword ptr -018A8h[EBP]
call near ptr __arraySliceSliceMulSliceAssign_d
push dword ptr -08Ch[ESI*8][EBP]
push dword ptr -090h[ESI*8][EBP]
push dword ptr -018ACh[EBP]
push dword ptr -018B0h[EBP]
call near ptr __arrayExpSliceMinass_d
inc EBX
add ESP,050h
cmp EBX,03FFFh
jb L168
}}}
このようになります。
これはつまり、 c[] += a[] * b[]; というようなコードが、 _arraySliceSliceMulSliceAddass_d という関数の呼び出しに変換されているということです。この関数はdmdが自動生成しているようです。(この関数にはXMM命令を使用していません。また、_arraySliceSliceMulSliceAssign_d という関数はdruntimeが定義していて、XMM対応している)
したがって、この関数の中身を見れば、バージョンアップ前後の違いがわかるかと思います。
#code(asm){{{
__arraySliceSliceMulSliceAddass_d comdat
assume CS:__arraySliceSliceMulSliceAddass_d
push EBX
xor EDX,EDX
cmp 8[ESP],EDX
je L28
L9: mov EAX,01Ch[ESP]
mov ECX,014h[ESP]
mov EBX,0Ch[ESP]
fld qword ptr [EDX*8][EAX]
fmul qword ptr [EDX*8][ECX]
fadd qword ptr [EDX*8][EBX]
fstp qword ptr [EDX*8][EBX]
inc EDX
cmp EDX,8[ESP]
jb L9
L28: mov EDX,0Ch[ESP]
mov EAX,8[ESP]
pop EBX
ret
__arraySliceSliceMulSliceAddass_d ends
}}}
多分これ?が中身です。
すべての処理系でこれと同一のものが吐かれるとは限りませんし、どのCPUがこれらの命令を実行するのにどれだけコストを使うか等しりませんが…。
参考になれば幸いです。

また、ベンチマーク用のコードで少し気になった点が。
+ スレッドを使用していますが、場合によっては浮動小数点演算の精度や速度に影響する可能性があります。詳しくは知りませんが、昔浮動小数点演算の精度がやたら落ちて結局スレッドのせいだった覚えがあります。
+ 乱数の生成がベンチマークのコード内のループ処理内に入っています。浮動小数点演算のベンチマークがしたいのであれば、これらはループ処理内に入れるべきではありません。
+ あと、ベンチマークには関係ないですし、結論としては問題ないのですが、
double[arr] a , b, c = 0;
このコードはあまりオススメできません。a, bはdouble.nanで初期化され、cだけ0で初期化されます。
a,bはあとのfor文で初期化しますので問題ありませんが、こういった、あとで初期化することを明示したい場合は
double[arr] a = void, b = void, c = 0;
とするのがいいでしょう。もっと言えば、宣言を分けるのがいいでしょう。
double[arr] a = void;
double[arr] b = void;
double[arr] c = 0;
+ 定数の宣言はenumでしたほうが良いでしょう(enumなら確実にコンパイル時に実行されます。staticではないimmutableではコンパイル時か実行時か曖昧です。)
immutable uint arr = uniform(0, 10, rnd); // 実行時に初期化されて値が決定
enum arr = 0x100; // コンパイル時に確実に値が決定
投票数:34 平均点:5.59
返信する

この投稿に返信する

題名
ゲスト名
投稿本文

  条件検索へ


メインメニュー

ログイン

ユーザー名:


パスワード:





パスワード紛失  |新規登録

Menu