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

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

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

No.83253 の関連記事表示

<< 0 | 1 | 2 | 3 >>
■83273  Re[3]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ なちゃ -(2017/03/16(Thu) 10:25:27)
    マルチスレッド化して高速化できる可能性があるとすれば、読み込みとその後の処理の並列化です。
    何倍も変わることはまずあり得ないですが。

    この場合、読み込んだ後の処理だけを並列化しても意味がありません。
    読み込みと処理を、並列化する必要があります。
    前の読み込みデータを処理しながら、次の読み込みを並行して行うということです。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83275  Re[4]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 10:58:24)
    ありがとうございます。

    > UTF-8 Binary → 改行文字の位置のみを列挙 → 必要な部分だけ随時 String 化


    これは私も考えていたところです。
    1次元のバイト配列で
    ある要素からある要素までのみをstring化するにはどうしたら良いですか?
    一度別の小さな配列にforループでコピーする必要がありますか?
     
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83276  Re[5]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 魔界の仮面弁士 -(2017/03/16(Thu) 11:22:45)
    No83275 (金尾 さん) に返信
    > 一度別の小さな配列にforループでコピーする必要がありますか?
    部分コピーを作らないで下さい。「無駄な配列を作らない」ことが目的なので。

    > 1次元のバイト配列で
    > ある要素からある要素までのみをstring化するにはどうしたら良いですか?
    Encoding クラスの GetString メソッドには、
    引数 1 個の「bytes」なオーバーロードだけではなく、
    引数 3 個の「bytes, index, count」なオーバーロードもあります。
    これを使えば、バイナリの一部のみを文字列化できるかと。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83277  Re[6]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 11:26:49)
    ありがとうございます。

    あと、vbcrlfの検索の仕方なのですが

    Array.IndexOfを使えば良いとは思うのですが
    合っていますか?

    vbcrlfはバイトにしたときにどういう数値になりますか?
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83279  Re[7]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 魔界の仮面弁士 -(2017/03/16(Thu) 11:44:16)
    No83277 (金尾 さん) に返信
    > vbcrlfはバイトにしたときにどういう数値になりますか?

    Encoding クラスの GetBytes メソッドで変換してみれば分かる事ですよね? (^^;

    結論から言えば、
     vbCr → {&H0D}
     vbLf → {&H0A}
     vbCrLf → {&H0D, &H0A}
    です。数値で言えば 13 と 10 。この機会に覚えておくことをお奨めします。



    > あと、vbcrlfの検索の仕方なのですが
    > Array.IndexOfを使えば良いとは思うのですが
    > 合っていますか?

    それで良いとおもいます。今回は Cr + Lf の探索になるので、
    まずは Cr の位置を探してから、その後続バイトが Lf かどうかを
    追加チェックすればことで対応してみて下さい。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83278  Re[7]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 11:34:24)
    試しに
    vbcrlfを検索せずにforループで行数分splitしてみましたが
    5%程度しか速くなりませんでした。
     
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83280  Re[8]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 魔界の仮面弁士 -(2017/03/16(Thu) 11:47:22)
    2017/03/16(Thu) 12:03:35 編集(投稿者)

    No83278 (金尾 さん) に返信
    >> UTF-8 Binary → 改行文字の位置のみを列挙 → 必要な部分だけ随時 String 化
    > vbcrlfを検索せずにforループで行数分splitしてみましたが
    > 5%程度しか速くなりませんでした。


    「必要な部分だけ随時 String 化」するのではなく、
    「列挙した位置情報ですべてを String() 化」しているとか?

    -- 追記 --

    改行位置を取り出して、その後何をするのかにもよりますが、
    「一行ずつ読み取る」ことだけが目的なら、データすべてを
    String() として変換する必要は無く、

    For Each 改行位置情報 In 改行位置列挙処理(rawBinary)
     Dim line As String = enc.GetString(rawBinary, 改行位置情報.Index, 改行位置情報.Length)


    Next

    となるような実装を用意すれば十分ではなかろうか、という意味です。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83281  Re[9]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 12:06:02)
    ありがとうございます。

    納得しました、
    コードが複雑になることは避けられませんが、仰る通り高速化は実現できると思います。

    ところで、
    ある任意の文字列をバイトにしたときにどのような数値になるか調べたい場合
    どのような関数を使えば調べられますか?

    vbcrなら13、vblfなら10といったことを調べられる関数を探しています
     
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83283  Re[10]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 魔界の仮面弁士 -(2017/03/16(Thu) 12:18:40)
    No83281 (金尾 さん) に返信
    > ありがとうございます。
    > 納得しました、

    で、これに相当することを行ってくれるのが、
    System.IO.File.ReadLines メソッドなんですが、これだと
    「後半の8割程度のみ」まで進めるには、Skip 拡張メソッドで進めるか
    TakeWhile して読み捨てるしか無さそうです。

    FileStream とどちらが早くなるかは、データサイズと内容次第では
    速度差が逆転する可能性もあるので、測定してみないと何とも言えません。


    > ある任意の文字列をバイトにしたときにどのような数値になるか調べたい場合
    > どのような関数を使えば調べられますか?

    No83279 の冒頭で答えたばかりですよね…?


    > vbcrなら13、vblfなら10といったことを調べられる関数を探しています
    既定のコードページでの文字列符号化なら、Asc 関数、
    UCS-2 としてなら、AscW 関数がお手軽です。逆変換は Chr / ChrW。

    それ以外のエンコードの場合は、No83279 の手法を使いましょう。

    たとえば System.Text.Encoding.UTF32.GetBytes(vbCrLf) なら、
    0D-00-00-00-0A-00-00-00 な 8 バイトに符号化されます。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83284  Re[11]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 12:25:57)
    とりあえず、全てのコードを文字列化する方法で
    高速化できるか試してみたのですが
    SSDだと2倍程度高速化できましたが
    HDDだと10%程度逆に遅くなってしまいました。

    ストレージの読み込みは律速していないと思ったのですが
    なぜでしょうか?
    もう少し試してみます
     
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83285  Re[12]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 12:32:21)
    ところで、
    読み出しソースのテキストファイルですが
    秀丸で確認すると、
    shift jisやutfなどではなく
    「欧文」となっています。
    Encoding.UTF8.GetStringのところも「欧文」に合わせてやれば
    高速化できるのではないかと思うのですが、
    https://dobon.net/vb/dotnet/string/getencodingobject.html

    このページでは「欧文」というものがないようです。
    「欧文」での取得はできないのでしょうか?
     
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83289  Re[13]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ Azulean -(2017/03/16(Thu) 12:41:03)
    No83285 (金尾 さん) に返信
    > このページでは「欧文」というものがないようです。
    > 「欧文」での取得はできないのでしょうか?

    それが、Window-1252 と呼ばれるエンコードなら、Encoding.GetEncoding(1252) で取れるものだったはず。(スマホからなのでテストしてません)
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83286  Re[12]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ Azulean -(2017/03/16(Thu) 12:36:40)
    No83272 (金尾 さん) に返信
    > もちろん数量のはかり方は分かるのですが
    > そのはかった数量をどのようにして共有したら良いのか分からないのですが
    > Split関数では生成した配列をそのままコピーされますので
    > 前回使用した配列のサイズなどは流用できないと思うのですが
    > どのようにすれば良いですか?

    私の共有は、変数やコードの話ではなく、金尾さんと、ここを見ている他の方との情報共有という意味で書いていましたのでご留意ください。
    処理量が第三者の予想のつかない数値になってたら話が通じない状態が続くので、それを懸念してです。

    No83284 (金尾 さん) に返信
    > HDDだと10%程度逆に遅くなってしまいました。
    >
    > ストレージの読み込みは律速していないと思ったのですが
    > なぜでしょうか?

    なちゃさんが途中で示唆されていたと思いますが、同じファイルの読み込みを繰り返すと、OS などによって、メモリにキャッシュされるので HDD と SSD の差がなくなるように見えることがあります。
    ただ、所詮はキャッシュなのでいつかはなくなり、ストレージの差が出ます。
    これは、マルチスレッドにしようと、メモリをどうしようとも変わりません。(打つ手がない)
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83288  Re[13]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 12:39:50)
    すいません
    「欧文」の件は解決しました
    ファイル読み込み時にバイナリデータとして読んでいるので
    この当たりは速度と無関係でした
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83292  Re[14]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 13:20:50)
    Azuleanさん

    ありがとうございます。

    ちなみにメモリは毎回RamMapというソフトでクリアしていますので
    この影響は排除できています
     
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83295  Re[15]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 14:28:01)
    Private Sub main()
    
        For i As Integer = 1 To 1000
    
            Dim s As Integer = (i - 1) * div
    
        For j As Integer = 1 To 10
    
            Dim k As Integer = (i - 1) * div + j
    
    
            Dim fs As New FileStream(StrPath(k), FileMode.Open, FileAccess.Read)
            fs.Read(bs, 0, file_size)
            fs.Close()
    
    
            MultiTask_in(j) = New Task(AddressOf Data_in, bs)
            MultiTask_in(j).Start()
    
        Next j
    
    
    
        For j As Integer = 1 To 10
    
            MultiTask_in(j).Wait()
    
        Next j
    
        Next i
    
    End Sub
    
    
    
    Private Sub Data_in(ByVal bs1() As Byte)
    
    Dim bs0() As Byte = bs1.Clone
    
     Dim foundIndex As Integer = Array.IndexOf(Of Byte)(bs0, 13)
    
    
    While 0 <= foundIndex
    
        If foundIndex + 1 < bs0.Length - 130 Then
            '次の要素を検索する
            Dim str As String = Encoding.UTF8.GetString(bs0, foundIndex, 130)
            foundIndex = Array.IndexOf(Of Byte)(bs0, 13, foundIndex + 1)
        Else
            '最後まで検索したときはループを抜ける
            Exit While
        End If
    End While
    
    End Sub
    
    というコードを書いたのですが
    Forループでバイト配列を流用したい場合
    Dim bs0() As Byte = bs1.Clone
    のようにして配列を一度コピーしないと、次の
    ループで前のデータが上書きされてしまうと思います。
    
    しかし、このクローンコピーは結構時間がかかってしまいます。
    
    このクローンコピーを避けるためには、
    
    
        For j As Integer = 1 To 10
    ・・・・
    
        Next j
    
    のところを
    
    
    
            Dim fs As New FileStream(StrPath(k), FileMode.Open, FileAccess.Read)
            fs.Read(bs, 0, file_size)
            fs.Close()
    
            MultiTask_in(1) = New Task(AddressOf Data_in, bs)
            MultiTask_in(1).Start()
    
    
    
            Dim fs As New FileStream(StrPath(k), FileMode.Open, FileAccess.Read)
            fs.Read(bs, 0, file_size)
            fs.Close()
    
            MultiTask_in(2) = New Task(AddressOf Data_in, bs)
            MultiTask_in(2).Start()
    
    ・・・
    
    
    のようにしてforを使わずに書くしかないでしょうか?
    もっと良い方法があれば教えてください。
    
    
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83297  Re[16]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ とっちゃん -(2017/03/16(Thu) 16:00:36)
    No83295 (金尾 さん) に返信
    > もっと良い方法があれば教えてください。
    >


    > For j As Integer = 1 To 10
    >
    > Dim k As Integer = (i - 1) * div + j
    >
    >
    > Dim fs As New FileStream(StrPath(k), FileMode.Open, FileAccess.Read)
    > fs.Read(bs, 0, file_size)
    > fs.Close()
    >
    >
    > MultiTask_in(j) = New Task(AddressOf Data_in, bs)
    > MultiTask_in(j).Start()
    >
    > Next j

    このループを、Parallel.For() にして、
    bs をそのループの中のローカル変数としてメモリを確保。
    Data_in は、Taskにせず直接呼び出して Clone せずに利用でファイルごとにユニークデータにできます。

    あとは、Data_in 内部で同時実行制御ができてれば大丈夫です(データ取りまとめ処理部分の実装がわからないので我々には不明ですが)。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83298  Re[17]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 16:53:44)
    ありがとうございます。

    Parallel.For() というものをしらなかったので非常に勉強になりました。

    ただ、今回のケースでは、
    上で書いたように、ファイルを読み込む場所だけは
    シングルスレッドにしないと、それぞれのファイルの読み込みがぶつかり合って
    逆に遅くなってしまいます。

    どうするのがもっともスマートな書き方でしょうか?
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83299  Re[18]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ 金尾 -(2017/03/16(Thu) 16:54:58)
    fs.Read(bs, 0, file_size)
    を同時に実行するのが問題ですので
    fs.Read(bs, 0, file_size)
    が完了するまで、他のスレッドを停止させるような方法があれば
    教えてください


記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

■83303  Re[18]: 大量のテキストファイルをマルチスレッドで高速に読み込む方法
□投稿者/ とっちゃん -(2017/03/16(Thu) 18:01:21)
    No83299 (金尾 さん) に返信


    No83298 より
    > シングルスレッドにしないと、それぞれのファイルの読み込みがぶつかり合って
    > 逆に遅くなってしまいます。

    えーっと。。。これは計測済みの結果ですか?試してみましたか?
    SSDが対象で、一括読み込みですよね?

    シングルスレッドにしないと、Cloneしてる間にデータが壊れてたり
    Data_in が実行された時点で bs1 が意図したファイルの内容ではないとか
    そういうことではありませんか?

    まずは、
    > bs をそのループの中のローカル変数としてメモリを確保。
    と書いていますが、各ファイルごとにメモリを用意して、
    Cloneをしないように書き換えてみるところから始めることをお勧めします。
記事No.83253 のレス /過去ログ142より / 関連記事表示
削除チェック/

<前の20件 | 次の20件>

<< 0 | 1 | 2 | 3 >>

パスワード/

- Child Tree -