- 1 名前:デフォルトの名無しさん [2008/02/27(水) 02:03:30 ]
- C++標準ライブラリの一つ、STLについて。
前スレ 【C++】STL(Standard Template Library)相談室 8 pc11.2ch.net/test/read.cgi/tech/1198435319/ 過去ログ・リンク・書籍紹介は >>2 以降
- 684 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 15:38:38 ]
- vectorの扱う型ががフリーストアを使ってないという保証があればあるいは
- 685 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 15:46:36 ]
- boost::serialization使うって手も <あまり使いやすくは無い
- 686 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 16:45:27 ]
- VS2005では一応下のコードは正常に動きました。
とりあえずこれが動けば十分です。 std::vector<std::string> v1; v1.clear(); v1.push_back("要素1"); v1.push_back("要素2"); v1.push_back("要素3"); FILE *fp; fopen_s(&fp, "vec.bin", "wb"); fwrite(&v1, sizeof(v1), 1, fp); fclose(fp); std::vector<std::string> v2; char* buf = (char*)&v2; fopen_s(&fp, "vec.bin", "rb"); while(fread(buf++, 1, 1, fp) > 0); fclose(fp);
- 687 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 16:53:25 ]
- >>686
まてまて、それv1の確保したメモリアドレスをv2が指しているだけだろ。 終了時に2重解放でエラーになってないか?
- 688 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 16:54:48 ]
- と思ったら、デストラクタで怒られました。
何がいけないんだろう・・・
- 689 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 16:58:00 ]
- 上の人も書いてるけどvectorは内部にポインタを持ってるんだってば。
(ついでにstringもな) fwriteでv1を直書きすると、ポインタのアドレスが保存されるだけで、 ポイント先は保存されないんだよ。
- 690 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:00:54 ]
- >>687,689
どうすればいいでしょうか。 やりたいことは、カンマ区切りで並んでいる大量の文字列データがあって、 それをカンマの区切りを探しつつ読み込むと非常に時間がかかるので、 初回だけカンマ区切りを解釈したら、その後はインスタンスをバイナリで一気に保存、一気に復元したいのです。
- 691 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:04:45 ]
- vector使わずに配列を使えばいいんでしょうが、vectorのデータをシリアライズ化するということは
ニーズとしてあるはずなので、そういう手法があれば教えていただきたいのです。 ただシリアライズのためにboostという別ライブラリを使用するのは、ちょっと大げさすぎかなと。。 そこまでするなら配列でやります。
- 692 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:10:08 ]
- 自分の力量・理解度に応じた実装をするべし
- 693 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:11:11 ]
- 最低限のデータを保存したい場合はこうじゃない?
std::vector<std::string> v1; v1.clear(); v1.push_back("要素1"); v1.push_back("要素2"); v1.push_back("要素3"); FILE *fp; fopen_s(&fp, "vec.bin", "wb"); const char *pstr; fwrite(&v1.size(), sizeof(size_t), 1, fp); //読み込むときの利便を考えて要素数を保存 for(size_t c=0, e=v1.size(); c < e; c++) { pstr = v1[c].c_str(); fwrite(pstr, strlen(pstr), 1, fp); } fclose(fp);
- 694 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:21:42 ]
- stringのサイズ保存してなかったので訂正
書き込み std::vector<std::string> v1; v1.clear(); v1.push_back("要素1"); v1.push_back("要素2"); v1.push_back("要素3"); FILE *fp; fopen_s(&fp, "vec.bin", "wb"); fwrite(&v1.size(), sizeof(size_t), 1, fp); //読み込むときの利便を考えて要素数を保存 size_t size; for(size_t c=0, e=v1.size(); c < e; c++) { size = v1[c].size(); fwite(&size, sizeof(size), 1, fp); fwrite(v1[c].c_str(), size, 1, fp); } fclose(fp);
- 695 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:28:10 ]
- 読み込み
std::vector<std::string> v2; FILE *fp; fopen_s(&fp, "vec.bin", "rb"); size_t size; fread(&size, sizeof(size), 1, fp); v2.resize(size); for(size_t c=0, e=size; c < e; c++) { fread(&size, sizeof(size), 1, fp); v2[c].resize(size); fread(&v2[c][0], size, 1, fp); //stringの確保するメモリが連続してない環境なら、一度vectorなりに読み込む必要が //あるが、vcなら問題ないので省略 } fclose(fp);
- 696 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:33:26 ]
- 最初にもちらっと書いたが、serialization使うとこれですむ
//保存 { vector<string> data; data.push_back("Hello"); data.push_back("World"); ofstream file("save.dat"); boost::archive::text_oarchive oa(file); oa << (const vector<string>&) data; } // 復元 { vector<string> data; ifstream file("save.dat"); boost::archive::text_iarchive ia(file); ia >> data; } 下準備がちょっと面倒だけどな。 興味あったら下記を参照してください。 ttp://www.kmonos.net/alang/boost/classes/serialization.html
- 697 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:48:04 ]
- >>694,695
やっぱり要素ごとにサイズと一緒に保存という形しかないんでしょうか。 私のイメージではシリアライズというと、メモリ上にあるオブジェクトの塊を そのままバイナリで一気に書き込むという感じで、だからこそ高速化に役立つと思うのです。 要素ごとに書き込んでいると、カンマ区切りのケースとそれほど時間の差が出ないような・・・ MFCのCObjectを継承したクラスはシリアライズができますが、それはおそらく、 オブジェクトのデータやステートをメモリ空間上で一塊になるようにしている配置しているからこそ できるんじゃないかと思います。 STLではどうもそういう仕組みはないようなので、保存や復元に時間がかかるのは無理ないんでしょうかね。。。 >>696 boostの場合はどうなんでしょうか。 保存と復元を高速化できるかどうかがキモなんです。
- 698 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 17:55:59 ]
- >>690
カンマ区切りの文字列の読み込みに、そんなに時間がかかるとは思えんが。 時間がかかっているのはパースよりもvectorの伸張だろう。 先にカンマの数をカウントしてvector.reserve()するとか、vectorではなくて dequeにするとかの方が速くなるかと。
- 699 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 18:06:48 ]
- >>697
MFCのシリアライズは、各メンバをひとつずつCArchiveに書き込んでたと思うよ CObjectを継承すれば自動的にサポートされるものでもなく、メンバをひとつずつ書き込むコードを各クラスに個別に実装する必要があった シリアライズに対するそのイメージは誤りかと
- 700 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 18:31:32 ]
- データ個数にもよるが保存と読み込み時間を短縮したいなら
まずデータ構造自体から見直すべきだろ。 というか、そこがネックになってる時点で何かが間違ってる。
- 701 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 18:44:43 ]
- >>699,700
そうなんですか。 可変長データ配列のオブジェクトの保存と復元を高速化するためには、 各自が工夫して実装するしかないんですかね。 なんか車輪の再発明のような気が・・・ 配列要素の変更・追加・削除は頻繁にはやらないので、そちらの時間コストは多少増えてもいいんです。 とにかくソフトの起動をコンマ1秒でも速くするために、ドカンと一気に読み込めるようにしたいんですよね。 BYTE型配列1本と、ポインタ・サイズを格納した配列の計2本で、 そういったことをやれそうなイメージはあります。
- 702 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 18:45:42 ]
- vector<string>が固定長なデータじゃないので、要素ごとにアクセス
しなければならないのは仕方が無い。 また、上の例でも1文字ずつカンマをチェックしながらアクセスするよりは、 単純に数倍は速いよ。 ディスクアクセスが気になってるのなら、あらかじめメモリ上に 直列化して、総サイズも一緒に書き込むとか工夫しなさい。 (もともとfread、writeがバッファリングしてるので、あまり効果は無いだろうけど) あとboostのも1要素ごとの読み書きです。 入れ子になってるコンテナの巡回探査がデフォで出来るってだけ。
- 703 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 20:42:53 ]
- ほんとに直列の読み書きがしたければAPI叩くしかないんじゃないかなあ
- 704 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 20:59:26 ]
- >>701
まぁ今回の件に限らず、「コンマ1秒でも速くする」というような目標を持っている場合、 車輪の再発明は避けられないことが多いよね(そうでない場合も勿論あるけど)。
- 705 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 21:01:24 ]
- 本当に速くしたいなら MMX とか SIMD とか使うと
- 706 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 21:54:44 ]
- DANGOさんの出番だな
- 707 名前:デフォルトの名無しさん mailto:sage [2008/06/20(金) 22:09:39 ]
- : premature optimization is
(省略されました。続きを読むにはワッフルワッフルと書き込んでください)
- 708 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 01:24:43 ]
- ポインタのない言語なら>>686みたいなことは当たり前にできるんだけどな。
ポインタのある言語では、一気に話が複雑になるな。
- 709 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 06:23:29 ]
- データの入出力なんて元々複雑で時間の掛かる処理なんだから
横着するつもりなら効率の劣化には目を瞑るべき。 大体そんな困るほど遅くなることなんぞ滅多に無いし。
- 710 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 12:47:42 ]
- だいたい直列化してないデータを直列させるからシリアライズと
いうのに、最初からメモリ上に直列に並んでると考えるのはどうなのよw
- 711 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 12:51:19 ]
- >>708
ポインタの無いJAVAみたいな言語だって、>686みたいな記述はできても、 要素の実際の読み書きは1つずつだろ?
- 712 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 14:46:07 ]
- >>686
これは素晴らしい!!! すこぶる高速ですね
- 713 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 14:49:44 ]
- >>686
これstringの実装によってはやばくないのかな
- 714 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 15:00:33 ]
- >>686
こんな気持ち悪いコード見たことない
- 715 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 15:01:03 ]
- >>713
そのコードがダメなのははっきりしてるから。 続きも読め
- 716 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 15:01:06 ]
- それ以前の問題。
- 717 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 15:42:55 ]
- ポインタ保存してポインタ復帰してるだけだからな。
- 718 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 16:59:18 ]
- >>709
いや、プログラムの起動を可能な限り速くしたいというニーズはどこにでもある。 3秒で起動するブラウザと1秒で起動するブラウザ、どっちを使いたいかといえば速い方がいいに決まってる。 そういう場合のクラスデータのシリアライズは、1分かかるのを30秒にしたいとかいうオーダーの話ではなくて、 0.3秒かかるのを0.05秒に縮めたいとかいうオーダーなんだよ。 起動時にデシリアライズするオブジェクトの数は1つじゃないしな。 トータルで1秒以内で起動させたいとか、そういうレベルのことをやりたいとなると、 バイト配列の中に直列化したデータ(多少隙間があってもいい)をあらかじめ揃えておいて 一気にシリアライズするという考えも、アリだと思う。
- 719 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 17:02:02 ]
- ファイル読み書きのオーバーヘッドなんてI/O待ちが大半なんだから、
よっぽどアホな処理でもしてない限り大差ないだろ
- 720 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 17:09:11 ]
- >>718
さっきドラゴンボール全巻買ってきた までは読んだ :そこ、高速化したいなら横着せず書かないといけないって書いてんじゃん
- 721 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 17:38:07 ]
- その手のオーバーヘッドで一番時間食うのはstatだったりするんだよな
- 722 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 17:46:02 ]
- >>718
将来まで不変のデータ構造ならいいけど、 少しでも変えると過去のバージョンで直列化したデータが読めなくなるよね。 (すべてのバージョンに対するコンバータを付けるのもどうかと思うし) 痛し痒しだなぁ。
- 723 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 18:12:43 ]
- ちゅーか目的が高速化なのに質問者が面倒がって
既存の実装使おうと食い下がってるだけだじゃん。
- 724 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 18:28:07 ]
- 既存の実装で高速化できないってことは既存の実装がクソだということですよね
- 725 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 18:35:28 ]
- F-1を公道に持っていったら全く使い物にならないのと同じ。
普通車なら速くはないが大体どこでも走れる
- 726 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 19:27:12 ]
- >>724
べっ別にあんたのために実装したんじゃないんだからね。 すべてに効果のある実装は存在しない。自分の目的に合う実装がなければ自分で作る。
- 727 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 19:39:42 ]
- 暇だから素のテキストと長さ情報付きのバイナリで試してみた。
入力データはwindows.hおよびそこからincludeされているファイルから抽出した 全て大文字の先頭以外にアンダーバー入りの定数マクロ(WM_hoge等)18364個。 文字列の平均の長さは20.8文字。 手抜きのために、カンマ区切りではなく改行区切りで保存。 テキスト(ifstream.getline()で読み込み) vector<string> 23ms deque<string> 21ms list<sting> 21ms バイナリ(ifstream.read()で読み込み) vector<string> 14ms deque<string> 12ms list<sting> 12ms ちなみに、VC++2008Stdでコンパイル、E8400のPCで実行。 全て複数回実行した中で一番速かった結果。
- 728 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 19:54:00 ]
- freadに変えればさらに速くなるぜ
- 729 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 23:43:18 ]
- ifstreamをやめて、fopen,fgets,freadにしてみた
テキスト(fgets()で読み込み+改行コード除去) vector<string> 14ms バイナリ(fread()で読み込み) vector<string> 14ms CreateFile,ReadFileも試してみた テキスト(2048バイトずつ読み込み) vector<string> 11ms バイナリ(必要なサイズだけ読み込み) vector<string> 100ms
- 730 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 23:47:59 ]
- つーかstringって時点でバッファに直読みできねーよな
CString::GetBuffer()使ってみ
- 731 名前:729 mailto:sage [2008/06/21(土) 23:51:07 ]
- 結局、ifstream.getline()が遅いだけで、読み込み部分を最適化したら
テキスト形式でもバイナリ形式でも差がない感じ。 ちなみにテキスト形式でファイル一気読みでは、稀に10msが出る程度。 あと、バイナリ形式でReadFile()でチマチマ読むのは何故か遅かった。 fread()は速いのにね。
- 732 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 23:51:41 ]
- それはスレ違い。
- 733 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 23:56:05 ]
- >>731
それは「何故か」でも何でもなく明らかなことだ fread()はチマチマじゃなくて「一気に」バッファに読み込んで 読み込んだ分だけユーザに渡してるから速いんだよ
- 734 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 23:57:47 ]
- >>732
スレ違いかもしれないが重要なことだろ。 stringに高速にデータを読み込む方法は存在しない。 必ずコピーが発生するのだから。 カーネルバッファ→stdioバッファ→ユーザバッファ(典型的にはchar[])→string こんな感じ ほらみろ、効率悪い
- 735 名前:デフォルトの名無しさん mailto:sage [2008/06/21(土) 23:59:58 ]
- stringの実装を知っていれば環境依存の方法で…
ってもうSTL作者になる以外ないな
- 736 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:00:38 ]
- >>730
この場合だと、GetBuffer使うメリットねーと思う。
- 737 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:01:56 ]
- >>736
いーやある。 fread()ではstringに直接読み込めないので一時的にchar[]に読み込んでコピー するしかないが、 CString::GetBuffer()ならfreadで直接読み込める つまり、一段コピーを減らせる
- 738 名前:736 mailto:sage [2008/06/22(日) 00:03:33 ]
- >>737
理由は>>733が書いてる。GetBufferつかったら、それ以上に読み込み遅くなるだろ。
- 739 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:05:30 ]
- >>738
は?何言ってんの。 CStringで適当なサイズをリザーブしといて、 GetBuffer()で取ったchar*のポインタにfread()しろっつってんだぞ? 間違いなくchar[]に読み込んでからstd::stringにコピーするより 速いよ。
- 740 名前:739 mailto:sage [2008/06/22(日) 00:09:03 ]
- ああ、話のズレがわかった。
俺はstd::stringなんて使わなきゃ速いよつってるんだ。 最後にstd::stringにコピーしなきゃならないんなら意味ないわな、 そりゃ。 コピー君だもの。
- 741 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:11:10 ]
- 単に速いだけの話しならstd::istreambuf_iteratorとstd::ostreambuf_iterator
が速いんじゃないの?書式化なしだし
- 742 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:12:10 ]
- >>739
いってることはりかいできるけど、俺が言いたかったのはそうじゃない。 俺が言ってるのは、読み込んだデータには 複数のデータ(複数の文字列と文字列サイズのペア)が格納されてるってことだ。 んで、>>686あたりからの流れのように、vectorに一個一個格納すると。 まあすれ違いだからもう自重する。
- 743 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:12:33 ]
- >>741
それはどんだけ頑張ってもマクロ版のgetc()/putc()と同等の速度で、 言うまでも無くfread()より遅いよ
- 744 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:12:56 ]
- またEffective STLを読み返さねばならんようだな
- 745 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 00:27:04 ]
- >>743
そりゃそうだ 比べるのが無謀 というか比べるな
- 746 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:02:51 ]
- std::stringのかわりにstd::vector<char>つかえばいいんじゃね
char*, const char*のかわりに使えるし STLやboostのiterator取るタイプの関数も全部使えるし std::stringと違ってバッファ直接書き換えできるよ
- 747 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:04:21 ]
- どんだけ頑張ってもAPI直書きより
遅い。
- 748 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:10:19 ]
- >>747
上に出てるように、ちまちまReadFile()を呼ぶようなアホなまねをやるぐらいなら まだfread()のほうが速いよ
- 749 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:11:46 ]
- もうRAMDisk使います
- 750 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:17:54 ]
- 一応言っとくけど、バッファ渡して書き換えてもらう系の
関数だのAPIだのを使う際には全てこの議論は当てはまるんだぜ 別にI/Oだけの問題じゃない std::stringを使っている限りは常にコピーがワンクッション入ることを 覚悟せよってこった 通常はどうでもいい問題だがな
- 751 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:57:38 ]
- あーつまり何だ?
ドライバ書けと
- 752 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 01:59:57 ]
- tcpのread/writeでのコピーは減るように各OSがんばってるネー
- 753 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 02:07:28 ]
- x86はリトルエンディアンであるというだけでtcp/ipのビッグエンディアンを
実現するのに少し不利なんだよな
- 754 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 02:07:52 ]
- 物理層じゃなくてアプリケーション層の話な
- 755 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 02:08:10 ]
- データ本体だからendianは関係ないのでは・・
- 756 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 02:21:07 ]
- データをストアする時にひっくり返るでしょう
ブラウザはどういう仕組みになっているのか知らないが Unicodeをリトルエンディアンのまま画面出力できるようになっているのか、 それともビッグエンディアンに並び替えて表示しているのか
- 757 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 02:56:12 ]
- 速度最重視ならLEで送ってもらうんでないの
- 758 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 02:58:27 ]
- OSネイティブの文字コードで送られてくることなんか超レアケースだろ。そんなところが
最適化されててもたいしたメリットは無い。
- 759 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 08:20:06 ]
- 保存したファイルを直接ファイルマッピングして、そのまま利用するのが最速なんじゃね
要するにオンメモリでの利用形式を、保存形式に合わせるw
- 760 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 09:06:23 ]
- >>759
ファイルマッピングはファイルサイズを伸ばせないのが難点だな。何かいい方法がないものか。
- 761 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 09:50:40 ]
- >>759
ReadFile()やWriteFile()は別にディスクをガリガリ読み書きする わけじゃなくて、オンメモリのバッファキャッシュが相手だからな 事実上裏でOSがページ単位でファイルマッピングしてるのと同じで CreateFileMapping()したからつって経験上別に速くならないよ Windowsではな 話を大幅に戻すと、小手先の最適化に走る前に、本当にCSVやvector<string> じゃなければいけないのかってところを考えるべきだと思うね 固定長データ、ISAM、SQLite、Berkeley DBのようなものが適切なんじゃないかとかさ
- 762 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 16:22:09 ]
- fopenは、内部的にReadFileを呼び出しているものの、バッファリングしているので
(普通に使う分には)充分な速度が出る。 ただし、複数回のコピーが無駄と言えば無駄。 ReadFileは、OSのバッファにキャッシュしていてディスクアクセスはしないものの、 システムコールだから、カーネルとのスイッチが発生する。 だから、細かく何度も呼び出すと非常に遅くなる。 CreateFileMappingと使うと、OSのバッファキャッシュを経由しないので ゼロコピーとなり、読み出しに限れば最速を期待できる。 書き込みは、普通はバッファリングされるfwriteを使うべき。 Readと同様、直接APIを叩いても大して効果ないし 逆にバッファリングを無効にすると、ディスクアクセス完了まで待たされることになる。 この場合にどうしても最速を求めるなら、非同期APIを使う。
- 763 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 16:52:11 ]
- 俺、この類はcatコマンドのソース読んで参考にした。
読み込みと、書き込み(表示)について練り込まれた結果の 知識が詰まってるなと思った。 ちなみに read() write() 使ってた。
- 764 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 17:36:20 ]
- あ、そうだ。
stdioはバッファリングしてるけど fgetc/fputcのような、1文字入出力系は注意。 最近のVCとかは、マルチスレッド対応ライブラリで 1文字ごとにロックしているので、このコストがバカにならない。 遅いと言われるcygwinとかもそうかもしれない。 istream_iteratorとかは知らんが、MT対応を謳っているなら ロックしている可能性は十分ある。
- 765 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 19:54:16 ]
- iostreamの比較なんて昔から皆やってるのになぜいまさら
- 766 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 19:56:02 ]
- 実装が進化しているかもしれん。
- 767 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 20:17:58 ]
- 残念ながらstdioより速いiostreamなんてのは見たこともないし、今後も無いだろ。
実装の質の問題というよりは、仕様上無理なんじゃないか。 ios_base::sync_with_stdio()とかあるし、デフォでシンクロしてるのが仕様だから、 stdioをバイパスできず、stdioの上に構築せざるをえないってことになる。 おまけに仕様も複雑だ。 これでstdioより速くなるわけがないんだぜ。
- 768 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 20:23:36 ]
- _CRT_DISABLE_PERFCRIT_LOCKS
- 769 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 22:22:47 ]
- まあ、速さだけが基準じゃつまらんよな。
- 770 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 22:53:16 ]
- >>697
そもそも (世にある)シリアライズ機構 = 高速化のためのもの という発想が間違い。 シリアライズ機構 = ヘテロなオブジェクトの集合であっても、汎用的に直列表現に置き換えるための汎用枠組み ととらえる方が常識で、(たとえば>>699みたいに) でも汎用では自アプリにとっては遅くて不都合!という場合に、 自アプリに特化した、汎用無視の保存方法作る、というのがさらに常識。 CSVって決まってるならCSV特化とかね。そのかわりそこ変わった瞬間に大幅変更だけど。
- 771 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 23:19:12 ]
- はぁ?手軽に最高速がC++の売りなんじゃないですかぁ?
バカなの? ぶっちゃけRubyのほうが100万倍マシ
- 772 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 23:23:20 ]
- >>771
はいはい、そうですね
- 773 名前:デフォルトの名無しさん mailto:sage [2008/06/22(日) 23:27:47 ]
- C++が手軽なんて話は始めて聞いた
- 774 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 02:08:48 ]
- 最初に「100万倍」ってとこだけ目に入って、
あーきっとアホの子なんだろうなーと思って残りを見たら 完全にその通りだった。
- 775 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 03:37:07 ]
- Ruby信者が例外なく全員キモイのは何故なんだろう
- 776 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 07:43:16 ]
- Rubyは優秀な言語なのに、使ってる人の中身がDQNだからもったいないよなw
- 777 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 08:06:04 ]
- 釣りだったことにして逃げ切りを図るレスが来る頃合いだけど、
それを先にこうして予測したことで、ちょっとルートが変わるかもしれないな。
- 778 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 10:59:25 ]
- いつも思うんだが信者がわざわざRubyの評判を落とすような事をするかな。
- 779 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 11:23:27 ]
- 儲に見えないのは俺だけか
- 780 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 11:55:36 ]
- >>771-778は全て自演
- 781 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 13:00:25 ]
- ということにしたいんですね
- 782 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 14:35:23 ]
- >>778
例えば宗教団体の信者は熱心に勧誘を行って、結果周りから見るとイメージダウンをしている。 似たようなもんでは
- 783 名前:デフォルトの名無しさん mailto:sage [2008/06/23(月) 17:29:52 ]
- そうかそうか
- 784 名前:デフォルトの名無しさん [2008/06/24(火) 20:00:11 ]
- vectorの要素を指すポインタは無効になることがあります。
では、queueの要素を指すポインタは無効になることがありますか? 下のプログラムを実行すると、1 2 4 4 5 6 と出力され、期待通りに動きました。 このプログラムは正しいプログラムですか? #include <iostream> #include <queue> using namespace std; int main() { queue<int> q; q.push(1); q.push(2); q.push(3); int* x = &q.back(); q.push(4); q.push(5); q.push(6); (*x)++; while (!q.empty()) { cout << q.front() << ' '; q.pop(); } return 0; }
|

|