裏目小僧の部屋でLazarusの話

LazarusでRDTSCを使う

[Lazarusでx64 SIMD命令を使ってみる]で 実際にどれくらい処理時間が短縮出来るかuRDTSC.pas(37)を作ってみた

uRDTSC.pas(37)

  • 使用目的
・この関数は全体の何割を消費してるか知りたい
・この処理は現在何クロックを消費してるか知りたい
という趣味の領域が目的です
  • 使用方法
 測定したい処理全体の先頭で startRDTSC;
 測定したいユニットの先頭で RDTSCst(dtTSC[n]);
 測定したいユニットの終了で RDTSCed(dtTSC[n]);
   ....
測定したい処理全体の終了 endRDTSC;
 この時点で結果はクリップボードに出力されます
 ユニットには名前を付けておけます  dtTSC[n].name='func1'; なくても問題ない
nは0〜9の数字でユニットを識別
 つまり最大10個のユニットを識別出来ます(増やすならTSCtimerSizeを修正)

パフォーマンスチェックの都度、入れたり外したりが面倒なら
関数の先頭で
  |$IFDEF enTSC}RDTSCst(dtTSC[0]);{$ENDIF}
のように入れて 終了で
  |$IFDEF enTSC}RDTSCed(dtTSC[0]);{$ENDIF}
と入れます。enTSC をコンパイル時に入れなければこれらは外れます

関数の先頭は常に同じ場所を通りますが、exitやraiseがあると入れ忘れる場合もあるでしょう
その場合は処理時間が少な目に出るので stcntとedcntのカウント値で確認出来ます
また意図的に途中終了の比率を確認する事にも使えるでしょう
結果を自分で表示処理したい場合は
endRDTSC;をendRDTSC(false);として、その後でdtTSC配列を確認して下さい
  • 作者:裏目小僧
  • 利用はご自由に。
    • Lazarus2.2.4 32bit/64bit Delphi5 Delphi 10.4.2である程度動作する事を確認しています
    • Delphiで利用するにはUTF8からの文字コード変換が必要です

[Lazarusでx64 SIMD命令を使ってみる]でのSIMD命令の効果

 startRDTSC;
 dtTSC[0].name:='for文による場合'  ;
 dtTSC[1].name:='AVXによる場合'    ;
 dtTSC[2].name:='SSEによる場合'    ;
 RDTSCst(dtTSC[0]);
 for j := low(test1S) to High(Test1S) do test1D[j] := test1D[j] + coff * test1S[j];
 RDTSCed(dtTSC[0]);
 canUSEAVX:=true;
 RDTSCst(dtTSC[1]);
 AVXcoffSum(test2D[0], test2S[0], coff, length(test2D));
 RDTSCed(dtTSC[1]);
 canUSEAVX:=false;
 RDTSCst(dtTSC[2]);
 AVXcoffSum(test3D[0], test3S[0], coff, length(test3D));
 RDTSCed(dtTSC[2]);
 endRDTSC;
配列の大きさは256個です

実行結果は

no cyc 全体の st回数 ed回数 ed/st name
0 2218 54.18 1 1 100.00 for文による場合
1 720 17.59 1 1 100.00 AVXによる場合
2 762 18.61 1 1 100.00 SSEによる場合
4094

  • AVXの書き方が悪いのかSSEの4並列に比べて8並列なのに、あまり速度は上がらない
  • 配列サイズ256程度では効果がないのか
  • 同じ関数を呼んでるのでキャッシュの影響なのか

という事で 2番目と3番目を入れ変えると

no cyc 全体の st回数 ed回数 ed/st name
0 2556 55.52 1 1 100.00 for文による場合
1 366 7.95 1 1 100.00 AVXによる場合
2 864 18.77 1 1 100.00 SSEによる場合
4604
AVXの効果はやはり大きいようですね

プライバシーポリシー本文は日本語以外に翻訳禁止 click寄付