C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.100217 の関連記事表示

<< 0 >>
■100217  Re[2]: ASCIIファイルから数値データを高速読み出し
□投稿者/ 魔界の仮面弁士 -(2022/07/11(Mon) 17:39:27)
    2022/07/11(Mon) 17:55:11 編集(投稿者)

    No100187 (ロット さん) に返信
    > 各行に数値データが格納された大きなファイルサイズのテキストファイルがあり
    > これをVB.NETを使って、Single配列に読み出したいと考えています。
    内容によっては、出現頻度の高いデータを辞書化しておくことで
    変換コストが下がる可能性もあります。効果があるか逆効果になるかは不明。

    あるいはマルチコア CPU で並列変換させれば、高速化できるかもしれません。
    「短い処理が多数ある状況」のままだと並列処理には向かないので、
    「多数の変換処理」を 1 単位として CPU のコア数程度の数にチャンク化する必要はあるかも。


    > 恐らく、バイトデータをテキストデータに変換するところが
    > もっとも時間がかかっているはずなので、
    テキスト変換に時間がかかっている…というのは、Single 型への解析処理を無しにして

    ・全件を StreamReader.ReadLine するのに要する時間(現在)
    ・File.ReadAllBytes での全体に全件列挙時に要する時間(文字列変換や改行判定なし)
    ・Stream.Read で一定サイズごとに分割しながら全部バイナリのままで読み取った場合の時間

    を比較してみた、ということでしょうか。


    メモリ量が十分にある場合には、
    ・File.ReadLines での全件列挙時に要する時間
    ・File.ReadAllLines での全件列挙時に要する時間
    なども候補に挙がってくるところですが、巨大なメモリの確保と解放というのも
    それなりにコストがかかるものなので、いずれにせよ計測が大事ですね。



    No100191 (ロット さん) に返信
    > 普通にStreamReaderのReadLineで一秒ずつ読み込んで
    これは「一行ずつ」の誤りですよね。
    1000ミリ秒単位で区切って読み込んでいるとは思えないので。



    No100198 (ぶなっぷ さん) に返信
    > VBの文法が分からないので、以下C#ですが、
    > Out = ByteValue - (int)'0';
    > とすれば、整数演算だけで数値化できます。
    C# だったら
      Out = (int)ByteValue - (int)'0';
    じゃないんでしたっけ…?

    と思ったら、実際は
      Out = ByteValue - '0';
    だけで十分なんですね。※unchecked を付与するかはお好みで。

    Char を Int32 に直接キャストできるのは、C# や IL の場合の話ですが、
    VB は言語仕様上 NG だったりします。この場合には
     Out = CInt(ByteValue) - 48
    または
     Out = CInt(ByteValue - 48)
    と書くことで、提示された内容に近い結果になるかと思います。


    C# の場合は、Char を Int32 にキャストできるのですが、
    VB の場合は AscW 関数を挟まないと変換できず、文法エラーになります。
    >> エラー BC32006
    >> 'Char' 値を 'Integer' に変換することはできません。
    >> 文字を Unicode 値として扱うには 'AscW' を、
    >> 数字として扱うには 'Val' を使用してください。

    ということで、このケースでは
     Out = ByteValue - AscW("0"c)
    と書くことになるでしょう。そしてこの場合、最適化されて
     Out = CInt(ByteValue - 48)
    に相当するコードとしてコンパイルされるはずです。
    ※「整数オーバーフローのチェックを削除」が off の場合の IL 命令は 0xDA (sub.ovf)
    ※「整数オーバーフローのチェックを削除」が on の場合の IL 命令は 0x59 (sub)



    No100214 (banana さん) に返信
    > あと、Val()関数によるSingle型への変換は遅いんじゃないかと。

    Val 関数には、
     Val(Char) As Integer
     Val(String) As Double
    があって、今回は恐らく後者の方でしょうね。

    今回は As Single を求めるので、私も Val だと冗長には思えました。
    型も違いますし、変換コストが若干高くついたりしないかな…と。

    でも調べてみると、CSng(string) した場合も内部実装では Double へ変換していて、
    それをその後でそれを Single へと縮小変換しているみたいです。
    となると、実はそれほど変わらないかも…? (当方では未計測です)

    一方、Single.Parse や Single.TryParse の場合は、直接 Single 変換しているっぽい。


    そもそも Val と CSng と Single.Parse では、それぞれの変換仕様が
    微妙に異なっているので、ロジックだけでは単純比較ができませんでした。
    パフォーマンスの差は、実際に測定してみないと分からない所ですね。


    ただいずれにせよ、 No100187 のように自前で Single 化しようとすれば、
    かえって遅くなってしまうかと思います。Single への変換処理については、
    出来る限り、ライブラリ側の変換機構を利用する方針の方が良いと思いますよ。


    あとは、System.Text.Decoder クラスの Convert メソッドや
    System.Text.Encoding クラスの GetString メソッドや、
    Single 構造体の Parse メソッドには、パフォーマンス最適化を目的として
    ReadOnlySpan(Of Byte) や ReadOnlySpan(Of Char) を受け付けるオーバーロードが追加されているので、
    .NET Framework ではなく .NET (.NET Core) にすれば、ReadOnlySpan(Of ) のオーバーロードを
    活かす書き方にできるかも…と思ったりもしましたが、そもそも Visual Basic では
    ReadOnlySpan がサポートされないので、意味が無さそう。
記事No.100187 のレス /過去ログ174より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -