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

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

C# と VB.NET の入門サイト

Re[4]: ASCIIファイルから数値データを高速読み出し [1]


(過去ログ 174 を表示中)

[トピック内 48 記事 (21 - 40 表示)]  << 0 | 1 | 2 >>

■100225 / inTopicNo.21)  Re[6]: ASCIIファイルから数値データを高速読み出し
  
□投稿者/ KOZ (282回)-(2022/07/11(Mon) 23:56:15)
No100223 (伝説のカレー さん) に返信
> CSng : 6514msec
> Convert.ToSingle : 1313msec
> Single.Parse : 1300msec
> Val : 952msec
> Val(AsParallel) : 315msec
>
> Valって速いんですねー、環境依存かもしれないですけど
> 並列化するとコア数6のCPUで処理時間が1/3くらいにはなるっぽいです

おお、これは興味深い。
Microsoft.VisualBasic.dll って VB で書かれてるんですが、それでこの速度はすごいですね。

引用返信 編集キー/
■100226 / inTopicNo.22)  Re[5]: ASCIIファイルから数値データを高速読み出し
□投稿者/ radian (68回)-(2022/07/12(Tue) 00:59:40)
No100224 (KOZ さん) に返信
> 数秒、とか数百MB とか非常にあいまいなんですよね。
> 改行コード込みで 1行 9 バイトとすると 1,000万件で 100 MB 弱?

恐らく、とかきちんとボトルネック計測すらしてなさそうな受け答えなんで、
アルゴリズム云々より、まずそこからな気がします。
引用返信 編集キー/
■100227 / inTopicNo.23)  Re[6]: ASCIIファイルから数値データを高速読み出し
□投稿者/ banana (4回)-(2022/07/12(Tue) 08:44:52)
No100223 (伝説のカレー さん) に返信

> Valって速いんですねー、環境依存かもしれないですけど
> 並列化するとコア数6のCPUで処理時間が1/3くらいにはなるっぽいです

あいやー!Val()侮るなかれ!
何ともお恥ずかしい限りです。
いい加減なことを書いてゴメンナサイ...m(__)m
引用返信 編集キー/
■100232 / inTopicNo.24)  Re[7]: ASCIIファイルから数値データを高速読み出し
□投稿者/ くま (218回)-(2022/07/12(Tue) 10:06:13)
私の場合は
windows10 vb.net .net framework4.8

CSVファイル
1.7MB 100000レコード

でした。

1番はじめの状態(一番遅いであろう処理)でも十分な速度になりましたからね...。
ちなみに私の場合は個人で使う用なので。
引用返信 編集キー/
■100233 / inTopicNo.25)  Re[8]: ASCIIファイルから数値データを高速読み出し
□投稿者/ radian (69回)-(2022/07/12(Tue) 10:35:23)
2022/07/12(Tue) 11:02:04 編集(投稿者)

No100232 (くま さん) に返信
> 私の場合は
> windows10 vb.net .net framework4.8
>
> CSVファイル
> 1.7MB 100000レコード
>
> でした。
>
> 1番はじめの状態(一番遅いであろう処理)でも十分な速度になりましたからね...。
> ちなみに私の場合は個人で使う用なので。

質問者の方は数百Mで、読み込み時間だけ雑に見ても
大体くまさんの200msec前後の100倍で20秒前後くらいは掛かる事になりますね。
(ディスクやPCスペックが同じではないでしょうから、単純にはそうはならないと思いますが)
ただ、元の質問の数秒が、読み込みまで含めた変換全体の時間なのか、
String->Single変換のみの時間なのか不明なんですよね。

読み込み自体の時間が大きく占めているなら、
変換のアルゴリズムを多少工夫した所でそこまで差は出ないので、
口を酸っぱくしてボトルネック計測してくださいと言っている訳です。
引用返信 編集キー/
■100234 / inTopicNo.26)  Re[8]: ASCIIファイルから数値データを高速読み出し
□投稿者/ KOZ (283回)-(2022/07/12(Tue) 10:36:56)
No100232 (くま さん) に返信
> 1番はじめの状態(一番遅いであろう処理)でも十分な速度になりましたからね...。
そうですよねーあの速さなら充分ですね。

> ちなみに私の場合は個人で使う用なので。
あらま、そうでしたか。

ほんじゃーこのトピックは放置かなぁ
引用返信 編集キー/
■100235 / inTopicNo.27)  Re[3]: ASCIIファイルから数値データを高速読み出し
□投稿者/ 魔界の仮面弁士 (3433回)-(2022/07/12(Tue) 12:05:46)
No100217 (魔界の仮面弁士) に追記
> そもそも Val と CSng と Single.Parse では、それぞれの変換仕様が
> 微妙に異なっているので、ロジックだけでは単純比較ができませんでした。
> パフォーマンスの差は、実際に測定してみないと分からない所ですね。

No100223 の伝説のカレーさんの投稿で、速度面で Val の優位性が明らかに…!
.NET Core、.NET Framework バージョンの差でも変わってきたりするんでしょうかね。

CSng は全角数字も解釈するので、多分遅いとは思ってましたが、Val が予想以上にはやくて吃驚です。


以下、それぞれの変換仕様の差について例示。

たまに「Val だと変換エラーにならない」と書かれた記事を見ることがあるので、その否定を兼ねて…。
なお CSng の変換仕様は、VBA と .NET では異なります。


"1,234.56" を変換した場合
 Single.Parse(s) → 1234.56F
 CSng(s)         → 1234.56F
 CSng(Val(s))    → 1.0F

"1d 3h" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → エラー
 CSng(Val(s))    → 1000.0F

"123.4.5" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → エラー
 CSng(Val(s))    → 123.4F

"&H12" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → 18.0F
 CSng(Val(s))    → 18.0F

"&o123" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → 83.0F
 CSng(Val(s))    → 83.0F

"100%" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → エラー
 CSng(Val(s))    → 100.0F

"1.23%" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → エラー
 CSng(Val(s))    → エラー ※Val がエラーを返すパターン

"1.23" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → 1.23F
 CSng(Val(s))    → 0.0F

"(12.34)" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → -12.34F
 CSng(Val(s))    → 0.0F

"1.23E+45" を変換した場合
 Single.Parse(s) → エラー
 CSng(s)         → エラー
 CSng(Val(s))    → Single.Infinity

"∞" を変換した場合
 Single.Parse(s) → Single.Infinity
 CSng(s)         → Single.Infinity
 CSng(Val(s))    → 0.0F

引用返信 編集キー/
■100239 / inTopicNo.28)  Re[6]: ASCIIファイルから数値データを高速読み出し
□投稿者/ 魔界の仮面弁士 (3434回)-(2022/07/12(Tue) 18:46:15)
No100223 (伝説のカレー さん) に返信
> Dim numbers = lines.AsParallel().Select(Function(x) Val(x)).ToArray()

そのコードだと Single 配列 ではなく Double 配列になるので、もう一変換必要かも。


それと、順序に問題が出る可能性は無いでしょうか。PLINQ の使用経験があまり無くてこの方面は疎いのですが、
PLINQ ではソース シーケンスの順序が維持されるとは限らないと聞いていたので。
https://docs.microsoft.com/ja-jp/dotnet/standard/parallel-programming/order-preservation-in-plinq
https://docs.microsoft.com/ja-jp/dotnet/standard/parallel-programming/how-to-control-ordering-in-a-plinq-query


AsOrdered すらば順序が保証されるそうですが…遅くなるかな? (未測定)
 Dim numbers = lines.AsParallel().AsOrdered().Select(Function(x) CSng(Val(x))).ToArray()


順序情報付きで .ForAll するのはどうかと思考実験したものがこちら。(未実施)
でも numbers.IsSynchronized は False なので、複数スレッドからの同時操作は NG かもしれない。
 Dim numbers(lines.Length - 1) As Single
 lines.Select(Function(s, i) (s, i)).AsParallel().ForAll(Sub(x) numbers(x.i) = CSng(Val(x.s)))
引用返信 編集キー/
■100241 / inTopicNo.29)  Re[7]: ASCIIファイルから数値データを高速読み出し
□投稿者/ 伝説のカレー (30回)-(2022/07/12(Tue) 19:44:53)
No100239 (魔界の仮面弁士 さん) に返信

> そのコードだと Single 配列 ではなく Double 配列になるので、もう一変換必要かも。

そうなんですよね

> AsOrdered すらば順序が保証されるそうですが…遅くなるかな? (未測定)
>  Dim numbers = lines.AsParallel().AsOrdered().Select(Function(x) CSng(Val(x))).ToArray()

そうなんです

もう完全にそうなんですって感じなんですけど棚上げにしてました

AsOrdered()を付けたら私の環境では少しだけ速くなりました
PLINQが良い感じに最適化してるのかJITコンパイラが良い感じに最適化してるのか
CPUのキャッシュが良い感じなのかわからないですけど超ラッキって思いました
引用返信 編集キー/
■100275 / inTopicNo.30)  Re[4]: ASCIIファイルから数値データを高速読み出し
□投稿者/ radian (76回)-(2022/07/14(Thu) 16:08:47)
2022/07/14(Thu) 16:36:39 編集(投稿者)

No100219 (HattariB さん) に返信
> ピリオドがあるから、一律な数値変換が出来ないし、
> 桁が不動だから行末迄読まなきゃいけないし、
> KOZさんの実装以外に、どんな工夫があるんだろ?オイラはマヂわかんない。

データ形式が限定されているなら、(文字数固定、負数・指数・NaN・Infinity等を一切考慮しない)
ルックアップテーブルやSIMD、並列処理使うなど、色々工夫の余地はありそうな気はします。
どこまで最適化可能かは、正確なデータ形式の提示が必要になります。
(提示したから作ってくれと言われたら、私はお断りしますけど)

条件分岐、メモリアロケーションを減らす等を徹底的に行うと、
数倍とか数十倍のオーダーで変わる事もままあります。
ただ、作成コストもメンテナンスのコストも非常に高い割に、当然汎用性は落ちるので、
本当にそれを作る必要があるのかは、よくよく考える必要はありますが。

C++界隈だとなんかそのへん思いっきり最適化した処理が
どこかに転がってそうな気がするので、
そういうのをDLL化して叩くのが一番速そうですけどね。
引用返信 編集キー/
■100321 / inTopicNo.31)  Re[5]: ASCIIファイルから数値データを高速読み出し
□投稿者/ HattariB (13回)-(2022/07/15(Fri) 19:13:22)
No100275 (radian さん) に返信

※長文になっちゃったんでごめんなさい。たいしたことないのでスルーしていただいて構いま千円
レスどうもです。
スレ主さんが、「数値の変換のトコが速くなれば...」みたいなことをお書きだったんで、
個別処理部分の高速化ロジックを主眼にしてました。

> ルックアップテーブルやSIMD、並列処理使うなど、色々工夫の余地はありそうな気はします。
ルックアップテーブルと並列処理が異なるカテゴリってのはわかるんですが、
SIMDと並列処理が分けられている理由は理解できてないです。オイラは。

もしもオイラがルックアップテーブルみたいなのを採用するなら、
とりあえずシングルトン用意して、そこに文字コードを添え字にしたジャンプテーブルとか、
階層情報とか、積算情報とかを用意して、
一文字毎にジャンプテーブルを参照させて、数値関連ノードにヒットした時だけ
処理する!みたいなデータを作っておきながら、
文字毎に処理するための再帰関数を作るかもです。

再帰関数が行末に到達したら終わり。そこで桁を確定させて積算して回答!

ループの判定よりも、関数呼び出しのスタックプッシュの方が速いかなと。
まぁ戻りのポップで時間がかかりそうですけど。
続く→
引用返信 編集キー/
■100322 / inTopicNo.32)  Re[6]: ASCIIファイルから数値データを高速読み出し
□投稿者/ HattariB (14回)-(2022/07/15(Fri) 19:17:14)
続き書きたかったんですが、オイラが迷惑投稿者らしいので止めました。
ごめんさない
引用返信 編集キー/
■100324 / inTopicNo.33)  Re[6]: ASCIIファイルから数値データを高速読み出し
□投稿者/ radian (83回)-(2022/07/15(Fri) 21:02:58)
2022/07/15(Fri) 21:15:31 編集(投稿者)

No100321 (HattariB さん) に返信
> SIMDと並列処理が分けられている理由は理解できてないです。オイラは。

SIMDもまあ並列処理の一部ですけど、
後者はマルチスレッドによる分割処理という意図で書きました。
伝説のカレーさんが既にやってる奴ですね。
引用返信 編集キー/
■100325 / inTopicNo.34)  Re[7]: ASCIIファイルから数値データを高速読み出し
□投稿者/ HattariB (15回)-(2022/07/15(Fri) 21:22:14)
No100324 (radian さん) に返信
> 2022/07/15(Fri) 21:15:31 編集(投稿者)
>
> ■No100321 (HattariB さん) に返信
>>SIMDと並列処理が分けられている理由は理解できてないです。オイラは。
>
> SIMDもまあ並列処理の一部ですけど、
> 後者はマルチスレッドによる分割処理という意図で書きました。
> 伝説のカレーさんが既にやってる奴ですね。


SIMD、並列処理はよくわかんなかったです。
数値の桁毎に解析用のスレッド割り当てたとしても、起動したスレッドが全部完了しないと
データのマージはできそうにないし。
仮にでかいファイルを扱うために、読み込み領域を変えて、区間を限定して、
それぞれの部分解析を並列処理させるというのであればまぁ、分かるんですが、、、
スレ主さんが望んでおられたのって、それなんですかね。

条件分岐を減らすってのもよくわかんなかったです。
まぁ条件判定は時間がかかる処理なんですけど、それをトリガにしてコンパイラが
分岐予測してくれるようにアセンブラ吐いてくれるかもしれないし、ちょっとした冗長判定なら、
最近のコンパイラって、最適化してくれてませんか?

メモリアロケーションもそう。
っつか、今回のお題に関して、明示的にヒープが絡む処理が思いつきませんでした。
せいぜいファイルを開く際に、マッピングさせることくらいしか思いつかない。

数倍とか数十倍とか、は一般論ですよね。
今回のロジックにはあまり関係なさそうな気がしてました。

引用返信 編集キー/
■100326 / inTopicNo.35)  Re[8]: ASCIIファイルから数値データを高速読み出し
□投稿者/ HattariB (16回)-(2022/07/15(Fri) 21:24:14)
/*続きがかけたので調子にのりました*/

> C++界隈だとなんかそのへん思いっきり最適化した処理が
> どこかに転がってそうな気がするので、
探してみたんですけど見つからなかったですねー
ちなみに↓を探してて疲れたので止めましたw
https://xlinux.nist.gov/dads/
以上でつ
引用返信 編集キー/
■100327 / inTopicNo.36)  Re[8]: ASCIIファイルから数値データを高速読み出し
□投稿者/ radian (84回)-(2022/07/15(Fri) 21:45:29)
No100325 (HattariB さん) に返信
> SIMD、並列処理はよくわかんなかったです。
> 数値の桁毎に解析用のスレッド割り当てたとしても、起動したスレッドが全部完了しないと
> データのマージはできそうにないし。

データ量が多ければ多いほと絶大な効果がありますよ。
今回のケースよりよほど複雑なデータ形式のJSONを、
SIMDを使用してGB/sで処理するライブラリも存在します。
https://github.com/simdjson/simdjson

> 条件分岐を減らすってのもよくわかんなかったです。
> まぁ条件判定は時間がかかる処理なんですけど、それをトリガにしてコンパイラが
> 分岐予測してくれるようにアセンブラ吐いてくれるかもしれないし、ちょっとした冗長判定なら、
> 最近のコンパイラって、最適化してくれてませんか?
そこはアセンブリコード実際に確認したり、ベンチマークとったり
地道に確認する事になるでしょうね。
(だから面倒なのでよほど必要に迫られない限りやりたくない)

> メモリアロケーションもそう。
> っつか、今回のお題に関して、明示的にヒープが絡む処理が思いつきませんでした。
> せいぜいファイルを開く際に、マッピングさせることくらいしか思いつかない。
>
> 数倍とか数十倍とか、は一般論ですよね。
> 今回のロジックにはあまり関係なさそうな気がしてました。

まあここに関しては、今回の話に限定した話をした訳ではないので、確かに一般論です。
引用返信 編集キー/
■100328 / inTopicNo.37)  Re[9]: ASCIIファイルから数値データを高速読み出し
□投稿者/ HattariB (17回)-(2022/07/15(Fri) 22:16:11)
No100327 (radian さん) に返信
> データ量が多ければ多いほと絶大な効果がありますよ。
並列処理による効果が大きいのはなるほどですね。
クラスタリングとかCPU勘通信とか、いろいろと効果があるものは存じております。

> 今回のケースよりよほど複雑なデータ形式のJSONを、
> SIMDを使用してGB/sで処理するライブラリも存在します。
そうそうこです。単純なデータ形式の処理対象を、わざわざ並列化させる意味は何処なのかと。

> https://github.com/simdjson/simdjson
ちょっと眺めてみたんですが、ライブラリの使い方とベンチマークは見れたんですが、
考え方とか、どのようにしてSIMDを制御させてるのかはわかりませんでした。
単にSIMD向けオプションを付けてコンパイルしたライブラリってわけじゃぁ無いんですよね。

>>最近のコンパイラって、最適化してくれてませんか?
> そこはアセンブリコード実際に確認したり、ベンチマークとったり
> 地道に確認する事になるでしょうね。
> (だから面倒なのでよほど必要に迫られない限りやりたくない)
やりたくないのは分かります。ぇぇ。すごくよくわかりますが、
実装において条件判定を減らすという工夫で得られた効果の事では無いですよね。

私は、最近のコンパイラは賢く最適化してくれるので、
冗長な条件判定を書いても大きな問題にはならないと思ってます。
ですから、たとえ冗長でも、意図が明確に伝わるような
実装があれば良い!(とは言い切れないけど)位の勢いでカキコしたんです。

ですから、実装・そしてコードにおいて条件分岐を減らすロジックを提供する事の
意義みたいなのを教えてくださればいいなぁと思っています。

引用返信 編集キー/
■100329 / inTopicNo.38)  Re[10]: ASCIIファイルから数値データを高速読み出し
□投稿者/ radian (85回)-(2022/07/15(Fri) 22:28:28)
> >>最近のコンパイラって、最適化してくれてませんか?
>>そこはアセンブリコード実際に確認したり、ベンチマークとったり
>>地道に確認する事になるでしょうね。
>>(だから面倒なのでよほど必要に迫られない限りやりたくない)
> やりたくないのは分かります。ぇぇ。すごくよくわかりますが、
> 実装において条件判定を減らすという工夫で得られた効果の事では無いですよね。
>
> 私は、最近のコンパイラは賢く最適化してくれるので、
> 冗長な条件判定を書いても大きな問題にはならないと思ってます。
> ですから、たとえ冗長でも、意図が明確に伝わるような
> 実装があれば良い!(とは言い切れないけど)位の勢いでカキコしたんです。
>
> ですから、実装・そしてコードにおいて条件分岐を減らすロジックを提供する事の
> 意義みたいなのを教えてくださればいいなぁと思っています。

例えば、単純なループだと8回ループしないといけない処理が、
ベクトル演算数命令で1回のループで8個のデータが同時に処理出来たりしたらクソ速くなります。
自分の記事ですが、最大値を求める、という単純な処理でも
大幅に速度が変わる例を載せています。
https://qiita.com/radian-jp/items/186862f355ac5625a704
引用返信 編集キー/
■100330 / inTopicNo.39)  Re[11]: ASCIIファイルから数値データを高速読み出し
□投稿者/ HattariB (18回)-(2022/07/15(Fri) 22:34:48)
> 自分の記事ですが、最大値を求める、という単純な処理でも
> 大幅に速度が変わる例を載せています。
> https://qiita.com/radian-jp/items/186862f355ac5625a704
ロジックじゃなくって、ハードウェアアクセラレーションを使用した環境って事ですか?
並列処理はロジックの考え方の基本だけど、SIMDって並列処理を実現するための手法の一つって
ゅーぐあぃに解釈しても大丈夫なんすかね?
引用返信 編集キー/
■100331 / inTopicNo.40)  Re[12]: ASCIIファイルから数値データを高速読み出し
 
□投稿者/ radian (86回)-(2022/07/15(Fri) 22:38:04)
No100330 (HattariB さん) に返信
>>自分の記事ですが、最大値を求める、という単純な処理でも
>>大幅に速度が変わる例を載せています。
>>https://qiita.com/radian-jp/items/186862f355ac5625a704
> ロジックじゃなくって、ハードウェアアクセラレーションを使用した環境って事ですか?
> 並列処理はロジックの考え方の基本だけど、SIMDって並列処理を実現するための手法の一つって
> ゅーぐあぃに解釈しても大丈夫なんすかね?

並列処理のアプローチの違いで、
マルチスレッドによる並列処理はCPUのコアを生かし、
SIMD専用命令はCPU命令そのもので効率的にデータを処理する手法です。
引用返信 編集キー/

<前の20件 | 次の20件>
トピック内ページ移動 / << 0 | 1 | 2 >>

管理者用

- Child Tree -