object-c – Wie kann ich mit C++ das Lesen von 50 Millionen Daten aus einer Datei und deren Speicherung in einem Vektor beschleunigen?
PHP中文网
PHP中文网 2017-05-31 10:36:40
0
4
1078

Ich muss 50 Millionen Doppeldaten aus einer TXT-Datei lesen und in einem Vektor speichern. Ich dachte zunächst, dass die Datei io möglicherweise zu langsam ist, also habe ich die Dateiinhalte als Blöcke in den Speicher eingelesen in den Vektor einlesen, aber das Lesen der Daten direkt aus der Datei dauert nur 3 Minuten. Nachdem ich es optimiert habe, hat es sich auf 5 Minuten erhöht.

Mein Optimierungsplan besteht darin, die gesamte Datei in den Speicher zu lesen, sie in einen char*-Puffer zu legen und dann vec_name.reserve(50000000); zu verwenden, um 50 Millionen Kapazitäten zuzuweisen, um eine wiederholte Speicherzuweisung zu vermeiden, aber es scheint keine Wirkung zu haben.

Liegt es daran, dass die Zeit hauptsächlich für Push_back aufgewendet wird?

Gibt es eine gute Optimierungsmethode? Danke euch allen!
Der optimierte Schlüsselcode lautet wie folgt: (Das Einlesen aller Daten in den Vektor dauert fünf Minuten)

        
        ifstream iVecSim("input.txt");
        
        iVecSim.seekg(0, iVecSim.end);
        long long file_size = iVecSim.tellg();//文件大小
        iVecSim.seekg(0, iVecSim.beg);

        char *buffer = new char[file_size];
        iVecSim.read(buffer, file_size);

        string input(buffer);
        delete[]buffer;

        istringstream ss_sim(input);//string流

        string fVecSim;
        vec_similarity.reserve(50000000);
        while (ss_sim.good()) {//从string流中读入vector
            ss_sim >> fVecSim;
            vec_similarity.push_back(atof(fVecSim.c_str()));
        }
PHP中文网
PHP中文网

认证0级讲师

Antworte allen(4)
漂亮男人

debug模式下跑没有意义,我用你的代码在release下跑也就14秒左右的样子。

解决问题先找问题,我把代码修改成这个样子,先查出耗时的地方是哪

std::cout << "Start" << std::endl;
    auto n1 = ::GetTickCount();
    auto n2 = 0;
    auto n3 = 0;
    auto n4 = 0;

    while (ss_sim.good())
    {
        auto n = ::GetTickCount();
        ss_sim >> fVecSim;
        n2 += (::GetTickCount() - n);

        n = ::GetTickCount();
        auto v = atof(fVecSim.c_str());
        n3 += (::GetTickCount() - n);

        n = ::GetTickCount();
        vec_similarity.push_back(v);
        n4 += (::GetTickCount() - n);
    }
    n1 = ::GetTickCount() - n1;

    std::cout << "ss_sim >> fVecSim:" << n2 << "ms" << std::endl;
    std::cout << "atof:" << n3 << "ms" << std::endl;
    std::cout << "push_back:" << n4 << "ms" << std::endl;
    std::cout << "Total:" << n1 << "ms" << std::endl;

所以瓶颈在于"ss_sim >> fVecSim"这一句。atof也已经够快了。

所以我的结论是:终极的优化方案是从存储格式上下手,将你的数据存储为二进制而非字符串,这样就避免了字符串IO和转换函数的开销,真正达到秒取数据。

phpcn_u1582

目前最高效的办法就是用流,而在你的代码实现中可以看出来:你是全部将文件内容一次性读入buffer中,这种方式不是最好的。建议平均每次读 buffer[1024] 也就是1K,或者其他也可以。 读完指针就移到下一行,继续读,直到EOF位置结束

Peter_Zhu

1.如果数据间没有依赖关系的话,可以试试分块多线程读取;
2.另外vector的内存是连续的,如果后面不是要随机访问,而都是遍历的话,用list效率会高不少。

Peter_Zhu

可以换用C风格的scanf试试


哇怎么这么对待我答案的?举报我的网友倒是说说,这答案怎么就有问题了?

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage