c++による高速なテキストファイルの読み込み
質問
私は現在、たくさんの大きなテキストファイルを読むことを含むプログラムをc++で書いています。それぞれは、極端な場合、1行あたり4000文字以上で、~400.000行あります。テストのために、ifstream と cplusplus.com によって提供される実装を使用して、ファイルの 1 つを読みました。その結果、約60秒かかりましたが、これはあまりにも長すぎます。今思ったのですが、読み取り速度を向上させる簡単な方法はあるのでしょうか?
を編集しています。 私が使用しているコードは多かれ少なかれこれです。
string tmpString;
ifstream txtFile(path);
if(txtFile.is_open())
{
while(txtFile.good())
{
m_numLines++;
getline(txtFile, tmpString);
}
txtFile.close();
}
edit 2: 私が読み込んだファイルは82MBしかありません。私が主に4000に達する可能性があると言ったのは、バッファリングを行うために知る必要があるかもしれないと思ったからです。
edit 3: ご回答ありがとうございました。行数をカウントしたいので、readlineを使用しなければなりません。ifstreamをバイナリとしてインスタンス化しても、読み込みは速くなりませんでした。出来るだけ並列化するようにします、それくらいはうまくいくはずです。
edit 4: どうやら私にできることがいくつかあるようです。
これのために多くの時間を費やしてくれたseheに感謝します、私はそれに非常に感謝します! =)
どのように解決するのですか?
更新情報です。 最初の答えの下にある(驚くべき)更新を必ず確認してください。
メモリ マップされたファイルは私にとても役に立ちました。 1 :
#include <boost/iostreams/device/mapped_file.hpp> // for mmap
#include <algorithm> // for std::find
#include <iostream> // for std::cout
#include <cstring>
int main()
{
boost::iostreams::mapped_file mmap("input.txt", boost::iostreams::mapped_file::readonly);
auto f = mmap.const_data();
auto l = f + mmap.size();
uintmax_t m_numLines = 0;
while (f && f!=l)
if ((f = static_cast<const char*>(memchr(f, '\n', l-f))))
m_numLines++, f++;
std::cout << "m_numLines = " << m_numLines << "\n";
}
これは割とすぐ終わるはずです。
更新
この方法をテストするのに役立つかもしれないので、以下はそのバージョンです。
を使って
mmap
をBoostを使わず直接使用します。
Coliruでライブを見る
#include <algorithm>
#include <iostream>
#include <cstring>
// for mmap:
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
const char* map_file(const char* fname, size_t& length);
int main()
{
size_t length;
auto f = map_file("test.cpp", length);
auto l = f + length;
uintmax_t m_numLines = 0;
while (f && f!=l)
if ((f = static_cast<const char*>(memchr(f, '\n', l-f))))
m_numLines++, f++;
std::cout << "m_numLines = " << m_numLines << "\n";
}
void handle_error(const char* msg) {
perror(msg);
exit(255);
}
const char* map_file(const char* fname, size_t& length)
{
int fd = open(fname, O_RDONLY);
if (fd == -1)
handle_error("open");
// obtain file size
struct stat sb;
if (fstat(fd, &sb) == -1)
handle_error("fstat");
length = sb.st_size;
const char* addr = static_cast<const char*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0u));
if (addr == MAP_FAILED)
handle_error("mmap");
// TODO close fd at some point in time, call munmap(...)
return addr;
}
更新情報
GNU coreutils のソースを見ることで、これで最後の性能を引き出すことができました。
wc
. から引用した次の (大幅に簡略化した) コードを使うと、驚いたことに
wc
は約 84% の時間で実行されます。
上記のメモリマップドファイルで撮影したものです。
static uintmax_t wc(char const *fname)
{
static const auto BUFFER_SIZE = 16*1024;
int fd = open(fname, O_RDONLY);
if(fd == -1)
handle_error("open");
/* Advise the kernel of our access pattern. */
posix_fadvise(fd, 0, 0, 1); // FDADVICE_SEQUENTIAL
char buf[BUFFER_SIZE + 1];
uintmax_t lines = 0;
while(size_t bytes_read = read(fd, buf, BUFFER_SIZE))
{
if(bytes_read == (size_t)-1)
handle_error("read failed");
if (!bytes_read)
break;
for(char *p = buf; (p = (char*) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
++lines;
}
return lines;
}
1 は、例えばこちらのベンチマークをご覧ください。 C++でスペースで区切られた浮動小数点を素早くパースする方法は?
関連
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] PythonでUnicode(UTF-8)のファイル読み書きをする。
-
[解決済み】C++で大きなバッファをバイナリファイルに高速に書き込むには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる