X



C++相談室 part136
レス数が950を超えています。1000を超えると書き込みができなくなります。
0001デフォルトの名無しさん (ワッチョイ bf81-LHz9)
垢版 |
2018/06/07(木) 23:40:12.36ID:GNQuDMaA0
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512

C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。

前スレ
C++相談室 part135
https://mevius.5ch.net/test/read.cgi/tech/1522495206/

このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.102【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1509780815/

■長いソースを貼るときはここへ。■
 http://codepad.org/
 https://ideone.com/

[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)

----- テンプレ ここまで -----
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured
0859デフォルトの名無しさん (ワッチョイ 4750-SFkP)
垢版 |
2018/07/09(月) 21:26:46.46ID:AazuLIX60
floatの配列は別に用意して

struct LOG {
uint32_t str_start;
uint32_t str_end;
uint32_t str_line;
uint32_t num_start;
uint32_t num_end;
};

みたいな、
ブロックごとの構造体に入れていく方がいいのかな?
0870754 (アウアウウー Sa0b-sule)
垢版 |
2018/07/10(火) 00:11:54.08ID:L9+HOK/Ta
>>851
テストまでしていただいだきありがとうございます。
1分ちょっとならとてもいい感じです。
なるほどDRAMよりも高速なCPU内のキャッシュを有効に使うと効果的ってことですね。
そんなこと今まで考えたこともなかったです。勉強になります。

>>854
ご推察の通りです。

>>857
文字列の方はせいぜい10行〜20行です。
数値の方は何万行にもなったりします。

>>858
メモリは10GBつかっても問題にならないくらい潤沢に使えると思うので、まずは速度重視で行こうと思っています。

>>861,862
すみません昨日書き込みエラーになって書き込めなかったのでそのままでした。
クリックするたびに毎回int->float演算したら1項目で何万行もあったりするので
読み込み時に演算しておいた方がよいかなと思っていました。

>つづきます
0871754 (アウアウウー Sa0b-sule)
垢版 |
2018/07/10(火) 00:20:12.97ID:L9+HOK/Ta
>>863
全部のフォーマットは複雑になってくるので簡易的なフォーマットをと思って出していましたが
説明していくと細かい話になってきましたのでもう少し具体的なものを書きます。
テストまでしてもらっているのに変わってすみません。。
-------------------------------
SECTION_NAME @
11200 11200 2 Jun 9 23:23:00 2018 A
This is pen. B
hello world. B
x 1 2 C
100 1 -2000 10
101 10 -2001 10
y 2 4
-100 10000
-101 10100
x 3 28
QQ subname -1 0 0 1 -21000000 600000 2 D
100 100 110 110
100 100 110 110
〜あと26行〜
SECTION_NAME E

@GUI表示する
A11200がx or yの個数、3カラム目がテキスト行の個数、それ以降は捨てる。11200のところは1の時もあれば100万超えることもある
BGUI表示する
Cこれが非常に多く、ひたすら繰り返される。x,yはランダムでくる。
1カラム目はx or y固定。x=次行に来る数値は4カラム。y=2カラム
2カラム目は1からインクリメントしていき、Aの11200回出てくる。カウント数値
3カラム目は次行から始まる数値行が何行かの数値
Dx or yの次の行にたまにこの行があります。この行も使いますが、ちょっと複雑なのでまずはスキップで。
Eここからまた@の繰り返し、要するにファイルの最後はCのところで終わる。
-------------------------------
0872754 (アウアウウー Sa0b-sule)
垢版 |
2018/07/10(火) 00:23:35.36ID:L9+HOK/Ta
すみません、上記QQはQQという固定文字です。
行頭が"Q"のときはこの行という判定で良いと思います。

>>859,860
格納先は構造体に入れようと思っていて、下記のようにテキスト行も入れようかなと思っていました。

struct x_or_y{
 char type; // x or y
 int num; // Cの2カラム目
 float list;
};
struct elem{
 char section_name;
 char comments;
 array系の何かの型 x_or_y_array; // 配列にしておくと(Cの2カラム目-1)で簡単にアクセスできそう
};
0873デフォルトの名無しさん (ワッチョイ e7c3-WPlw)
垢版 |
2018/07/10(火) 01:34:56.63ID:C7bP6ErJ0
なんかのログなんだろうけど、ログ吐く時に読み込みやすいように出し方考え直した方がいいよ
大本が変えられないならパイプ繋いでフィルタ噛まして、読みやすいように直したファイルを並行して吐くとかさ

というかまず単にSECTION_NAMEごとにファイルぶった切っておくだけで良かったりしない?難しく考えすぎてない?
0874デフォルトの名無しさん (ワッチョイ e7c3-WPlw)
垢版 |
2018/07/10(火) 01:46:08.72ID:C7bP6ErJ0
どういうGUIが必要なのかわからんから的外れかもしれないけど
ワイならSECTION_NAMEごとに集計したHTMLファイルかなんかを出力するプログラムをワンパスかけてから
後でそのHTMLをブラウザで見ることを考えたくなるんだけどそれじゃダメなの?
0880デフォルトの名無しさん (ワッチョイ 4750-SFkP)
垢版 |
2018/07/10(火) 07:31:15.21ID:wSs+8Os00
初めて開くファイルは使いやすいように変換して(キャッシュとして)保存しておいて
次回以降それを使うか
全ファイルバッチ処理で事前に変換しておくか

かな

ファイルを開く度に分オーダーかかるのは使いづらい
どちらが良いかは使い方次第で
0883754 (ワッチョイ 7ff1-XcsY)
垢版 |
2018/07/10(火) 14:27:03.15ID:VT/DQ/OS0
>>873,874
ソフトが出しているログなので変えられず、並行で吐くこともできないんです…

> ワイならSECTION_NAMEごとに集計したHTMLファイルかなんかを出力するプログラムをワンパスかけてから
これも考えたのですが、元ファイルと加工したファイルが常に等価ではないので、
間違って古いままの加工ファイルを参照する事故を、全員が気にする必要が
出てくるため今は保留とし、どうしてもできない時の最終手段と考えています。
こういうご意見も新しい視点が見えたりするんでありがたいです。

>>877
こんなのをイメージしています。
====================
項目名   | 個数 ※各カラムの説明行
====================
-SECTION1  | 11200
 subname1 | 8800 ※subnameがあれば折り畳みツリー形式。なければ折り畳みなし
 subname2 | 2400
+SECTION2  |  1
+SECTION3  | 666
====================
This is pen. ※SECTION1を選択するとそれに対応するテキストをここに表示
hello world.
====================
1 2 3 4 5 6 7 ※上と同じくSECTIONに対応した数値を特定できる番号を表示
8 9 10 11 12 13 14 ※ここはHTMLぽいものにし、数字クリックでその数値をprint
....
====================
0884754 (ワッチョイ 7ff1-XcsY)
垢版 |
2018/07/10(火) 14:39:44.08ID:VT/DQ/OS0
>>878
> 1カラム目と2カラム目は同じ数字?
2カラム目が何の数字かまだ把握できていません。
とりあえず1カラム目と2カラム目の数値比較を行い、違う場合はエラーにしようと思います。
> y 2 4 の後、データ行が2行だけど4行の間違い?
ご指摘の通り4行の間違いでした。
> データ行の値の範囲は?
intの範囲を超えるか?ということですか?
int(-2147483648〜2147483647)で大丈夫と思います。

>>879
ユニークな名前で重複しません。

>>880
仰る通りどちらも一長一短で、今回は874さんに回答した通り、古いキャッシュを参照する事故を防ぐため、まずはテンポラリファイルを作らないことを考えています。

>>881
ファイルは毎回更新されて新しい15GBのファイル1つをインポートします。
15GBも現在のMAXサイズなのでそのうち20GBとかのものが出てくる可能性はありますが、
そこは「読み込みをひたすら待つ」と割り切りで考えています。

>>882
@の行→100行以下
Aの行→SECTIONごとに1行出るので同じく100行以下
Bの行→SECTIONごとにせいぜい20行程度。(20行*100行=20000行)
Cの行→SECTIONごとにたまに数千万のSECTIONあり(全SECTIONだと数千万〜億超えも出てきそう)
1つのSECTIONで数千万や億になり、それ以外のSECTIONは1000以下だったり、
1千万のSECTIONが複数SECTIONになることもあります。
そしてCに対して数値行が1行〜数十行、場合によっては数百行がくるので、Cとそれにかかる数値行が支配的になると思われます。

あと忘れていましたが、テキスト行は日本語がくることもあります。
それ以外は1byte文字です。
0885デフォルトの名無しさん (ワッチョイ 4750-SFkP)
垢版 |
2018/07/10(火) 18:26:12.65ID:wSs+8Os00
キャッシュせず
変換して保存しないとなると
ほとんど読み込み時間
解析はそれに比べれば速い

なので
もし高速化したければ
全読みしない方法を考えるしか

全読みの時間くらいは待てるっていうならその方が簡単だけど

読み込み15GB 30秒って異様に速いな
うちの8TB 7200rpmのHDD(内側の方) だと78秒
SSD? RAID? キャッシュ? RAMディスク?
0886754 (アウアウウー Sa0b-XcsY)
垢版 |
2018/07/10(火) 18:39:22.79ID:AbfeQ9t7a
>>885
HDDだと思います。
サーバ用なので高速なんですかね。
ちなみに cat /proc/cpuinfo でCPUも調べたらXeonで20コア以上ありました。
(ハイパースレッドかもしれませんが)
〜次キャッシュも民生用CPUより多いと予想されます。
0887754 (アウアウウー Sa0b-sule)
垢版 |
2018/07/10(火) 22:05:54.09ID:zwgBQXGGa
>>885
あと、全読みの時間は >>851 を参考にすると2分くらいにはなりそうなので、それくらいなら全然待てます。
fgets, sscanfの時は5分かかっていて、それで我慢するしかないのか、と諦めかけていたので。

評価もscanfもしないでfgets()だけで78秒なんですかね?
大きな違いはCPU、CPU内臓キャッシュ、HDD、メモリあたりと思いますが、それだけで本当に半分以下になるのか少し気になりますね。
0888754 (ワッチョイ 7ff1-sule)
垢版 |
2018/07/10(火) 23:40:47.46ID:VT/DQ/OS0
とりあえずみなさんのコードを眺めましたが初めて目にする関数だらけで自分のレベルでは全くついていけてないです。
一つ一つの関数がどんな動作をするのか調べていきます。

>>782,833 を見るとcharのポインタをインクリして読むやりかたとか昔ちらっと読んだことある。程度のレベルなので。。

今833-837の動作確認ができたので、まずはこれがどう動いているかと、バイナリ読み込みの手法について調べていきます。
0889デフォルトの名無しさん (ワッチョイ 4750-SFkP)
垢版 |
2018/07/11(水) 00:11:48.47ID:Faj75qU20
>>887
fgetsじゃなくて
freadで1MBずつ読むだけで78秒
庶民の普通のHDDはこんなもんです
解析入れてもほぼ同じなので
読むのに30秒なら解析入れても30秒で終わるよ
もちろんうまく作ればだけど
0908デフォルトの名無しさん (ワッチョイ 0780-Rmg1)
垢版 |
2018/07/11(水) 23:39:25.00ID:r1UJt2Dq0
やっぱりな低学歴しかいないわ
0910デフォルトの名無しさん (ワッチョイ 0780-Rmg1)
垢版 |
2018/07/11(水) 23:43:40.24ID:r1UJt2Dq0
そもそも最初のフォーマットと全然違うやんけ
普通にfgetsでとって、必要最低限の位置をマーキングするほうが
メモリに入れるのはそれだけ

位置からメモリブロックをとって、>>834>>835みたいなやりかたで表示が必要になったときに解析
0911デフォルトの名無しさん (ワッチョイ 0780-Rmg1)
垢版 |
2018/07/11(水) 23:46:44.47ID:r1UJt2Dq0
そもそも解析アプリが出力してる規定されてるフォーマットなのに
いちいち形式をチェックする必要すらない

ホントな知恵遅れはなにをいってんのか意味不明だからな
クソニートのエアプログラマがテキトーなことばっかりいってんのは分かる
0914デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 00:09:52.26ID:LmT6lrwh0
ちなみな
fgets()は知恵遅れのキミラが考えてるよりぜんぜん速い
このスレの知恵遅れが書くようなクソコードより全然速い

書式付の標準関数は書式解析のオーバーヘッドがあるからクソ遅い
0915デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 00:14:29.53ID:LmT6lrwh0
ちなみにな手で入力したときは
fscanfやsscanfは使えない
書式より引数が少ない場合簡単に死ぬからな

手で入力してるデータの場合fgets()でデータとって丹念に解析するしかない
つまりfscanfやsscanfの使用も想定する=間違いなく妥当な形式の入力がある
ことを意味する
0917デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 00:17:19.69ID:LmT6lrwh0
メモリブロックとるときは
普通にfreadでいい
どうせ改行位置は解析しないといけないから
fgetsにやらせとけばいい

知恵遅れはTPOにあった関数の使い方がわかってないからな
0918デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 00:22:11.12ID:LmT6lrwh0
知恵遅れはなにをどういった場面で使うのか分かってないからな
そもそも話がかみあうワケがない

知恵遅れにありがち
電車みて電車の型番いえるだけみたいな頭悪いのが
このスレにはウヨウヨいる
0922754 (アウアウウー Sa21-Y8gp)
垢版 |
2018/07/12(木) 00:32:07.09ID:2mlSfrk0a
>>889

なるほどですね。
解析入れてもあまり変わらないのか。
scanfって本当に遅いんですね、嬉しい誤算です。

話題に出ているregexですが、↓ここを見た感じ、

ttps://www.sejuku.net/blog/25962

下記のように感じました。
perlやpythonの正規表現と似た感じなので使えるかもしれません。
1文字づつシフトしてスペースや改行を判定しながら抽出するより早いのであれば試して見ようと思います。

regcomp →正規表現オブジェクト?の作成。()でグループ化。読み込み前にすべてのフォーマットパターンを生成して使い回す。
regexec →正規表現オブジェクトを使ってパターンマッチ
rm_so、rm_eo →マッチの先頭、終端が取れるので文字列が拾える。こんな感じ?→strncpy(&str, data+match[i].rm_so, match[i].rm_eo - match[i].rm_so);
regfree →読み込み終了後にすべてのオブジェクトをこれで開放すればいい?

spirit::qiはググりましたがまったくわかりませんでした。。
0923デフォルトの名無しさん (ワッチョイ 3d50-Se03)
垢版 |
2018/07/12(木) 00:34:07.21ID:KB59nVpm0
15GBともなると
関数を呼ぶ時間でもトータル時間に影響するんでね
fgetsの関数コール回数だってバカにならんでしょ

全てのfloatをvectorにpush_backするだけでも
結構な時間ですよ
この辺も工夫しないと
0924デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 00:34:22.25ID:LmT6lrwh0
正規表現なんか使ったらコンパイル済の正規表現でも
クソ遅いにきまってるやんけ

そんなもん使うならスクリプトでやったほうがいい
0925デフォルトの名無しさん (ワッチョイ b5b3-kMcx)
垢版 |
2018/07/12(木) 09:04:08.15ID:8O8kwVFO0
ディスク読むより遅いでしょうか。
0926デフォルトの名無しさん (ワッチョイ 7db3-iomh)
垢版 |
2018/07/12(木) 09:40:21.55ID:yoYPGeS70
>>922
だからregexもspiritも使わなくていいってばw
すでに実例出してくれてるような昔ながらのC言語的な書き方でいいと思う
まともな実例も示さずに「○○使え」は無視していいよ
0928デフォルトの名無しさん (ワッチョイ f1d2-LQig)
垢版 |
2018/07/12(木) 13:31:18.35ID:9k08EbFv0
ちなみに gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0 だと、 C++がちゃんとしてて、std::getline()はfread()と同じくらい速い。
各自で実際に試してみるとよいだろう。

Visual Studio だとstd::getline()はfgets()よりも遅い。
コンパイラによって性能に極端な差がでるのがC++のiostream周り。iostreamが地雷扱いされる主因。
0929デフォルトの名無しさん (ワッチョイ 119e-dYrz)
垢版 |
2018/07/12(木) 14:27:06.99ID:Jbx8ub/k0
15GB なんて、もし画像ファイルなら、触った途端に、メモリ不足でフリーズするレベル。
普通、8GB ぐらいしか、メモリを積んでいないだろ

1行毎に、読んでは捨てる方式じゃないと無理。
それか、ファイル分割する

Ruby で、HTML, Node.js などが良さそう。
それか、DB
0933デフォルトの名無しさん (ワッチョイ 3d50-Se03)
垢版 |
2018/07/12(木) 21:42:21.02ID:KB59nVpm0
>>871のフォーマットでC++で作ったら
解析15GBで8.6秒
1バイト平均2クロック!

これを越えるには
マルチスレッド / AVX命令 /アセンブラ / GPU
に手を出さないと無理かな

----
Haswell
3.4GHz固定
シングルスレッド
C++で1文字ずつ15G文字解析
普通の命令のみ使用(SIMD命令は使用しない)
数値の合計のみ計算して結果を最後に表示
固定4KBを繰り返し解析、トータル15GB分の時間を計測
----
0936754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 22:08:43.66ID:8VUYfWV40
>>926
おとなしく1文字づつ評価します。

>>933
8.6秒早いですね。

自分はまず初バイナリ読み込みなので勉強から始めてとりあえず1行読みができましたが、
アスキー読み込みのfgetsの方が早かったです、、
コードを載せるのでどこが悪いか見てもらって良いですか?

対象=13GBのファイル(約8億行)。

○fgets版 →約17秒
if((fp=fopen(file_path,"r"))==NULL){
  printf("file not open %s\n", file_path);
 return 1;
}
while( fgets(buf,MAX,fp) != NULL ){
 buf;
}

次にバイナリ読み↓
0937754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 22:11:04.95ID:8VUYfWV40
○バイナリ読み版 →約44秒
struct CCC {
 FILE *fp ;
 bool read(char* file_path);
 t_read_db read_db;
};
bool CCC::read(char file_path[]){
 FILE *fp;
 if((fp=fopen(file_path, "rb"))==NULL){ printf("ファイルを開けません。%s",file_path); return 0; }
 unsigned char buf[BUF_SIZE];
 int newline_index;
 while( !feof( fp ) ){
  size_t size = fread( &buf, sizeof(buf[0]), sizeof(buf), fp );
  // 終端処理。最大値で取得されてなければそこを末尾にする
  if( size != BUF_SIZE ) buf[size] = '\x00';
  // 取得bufの最後尾が改行でなければfpを改行まで戻す
  if( buf[size-1] != '\x0a' ){
   newline_index = -2;
   for(; buf[size+newline_index] != '\x0a'; --newline_index);
   fseek(fp,newline_index+1,SEEK_CUR);
   // bufの最後の改行の次にx00(null)を入れてそれ以降をカット
   // 「配列参照はポインタの移動より遅い」とあったがbufは実体で移動できないので[]参照で代入。
   buf[size+newline_index+1] = '\x00';
  }
  unsigned char const* c_buf = buf;
  while( c_buf[0] != '\x00' ){
   print_line(c_buf, &c_buf);
  }
 }
}
0938754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 22:11:35.38ID:8VUYfWV40
bool print_line(unsigned char const* p_buf, unsigned char const** pct_next);
bool print_line(unsigned char const* p_buf, unsigned char const** pct_next){
 unsigned char const* c_buf = p_buf;
 //改行位置を検索
 for(; *c_buf != '\x0a'; ++c_buf);

 char line[LINE_SIZE];
 strncpy( line, (char const*)p_buf, c_buf - p_buf );
 // nullで区切らないと過去に代入した文字数より少ないときにゴミが残る
 line[c_buf - p_buf] = '\x00';

 ++c_buf;
 *pct_next = c_buf;
 return true;
};
0939754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 22:13:44.64ID:8VUYfWV40
○fgets版 →約17秒
○バイナリ読み版 →約44秒

両方ともとりあえず文字列の読み取りまでしていて、条件は同じではないかと思うのですが、freadのほうが倍以上遅いです。。
0942754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 22:17:52.40ID:8VUYfWV40
すみません、44秒はfreadの読み込みサイズ(BUF_SIZE)が512byteでした。
16MBにすると34秒になりましたが、それでも倍の差があります。
0944754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 23:04:55.64ID:8VUYfWV40
>>943
mmapですか。
要チェックですかね。
でもそれだけで数倍早くなるとも思えないし、 >>933 さんの8.6秒は圧倒的パフォーマンスですね。
シングルスレッドで特殊なものは使ってないようだし、たった4KBの繰り返しだし。
根本的なところから違いそう。。

>>933
もし可能であれば、テストしたコードを見せていただくことはできませんでしょうか?
0945デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 23:10:07.38ID:LmT6lrwh0
あのな
そこまで読みこみ速度を気にするなら
そもそもFILEポインタ使う関数なんか使うなよ
そもそもFILEポインタ使う関数はバッファリングしてるから
いちいちメモリコピーしてんのに

そこまでガタガタいうなら
openとreadで普通にメモリブロック読みこむ処理にしろよ
ハゲ
0946754 (ワッチョイ 66f1-Y8gp)
垢版 |
2018/07/12(木) 23:13:14.06ID:8VUYfWV40
>>940,941
setvbufも初耳です。
941さんのコメントからすると、これまた難しそう。。

色々と情報ありがとうございます。
0947デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 23:13:42.35ID:LmT6lrwh0
ちなみになFILEポインタは構造体にファイルデスクリプタもってる
fopenでopenを呼び出してファイルディスクリプタ生成して構造体に保存してる
ファイル読むときはファイルディスクリプタでread使ってバッファリングしながら読みこんでる

このスレの低学歴どもはこういう基本的なことわかってんの
0948デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 23:15:00.75ID:LmT6lrwh0
そのsetvbufというのが
バッファリングするバッファのサイズだ
つまり、バッファにたまったメモリをひたすらコピーしてる
0950デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 23:18:11.64ID:LmT6lrwh0
32bit越えるmmapとか
そんなやばそうなもん使うのか
まずちゃんと動作するか確認することになるわ
0951デフォルトの名無しさん (ワッチョイ a580-lT5f)
垢版 |
2018/07/12(木) 23:31:34.69ID:LmT6lrwh0
休日にオレのエレガントなファイル読みこみ処理作ってやるから
楽しみにしてなさい
レス数が950を超えています。1000を超えると書き込みができなくなります。

ニューススポーツなんでも実況