objective-c - 使用C++從檔案讀取五千萬個資料存入vector中如何加快速度?
PHP中文网
PHP中文网 2017-05-31 10:36:40
0
4
1054

我需要從txt檔案讀取五千萬個double數據,並且存入vector中,我最初覺得可能是文件io太慢,所以使用了文件內存映射,將文件內容當成block全部讀入內存中,然後再一個一個push_back進vector中,但直接從檔案一個一個讀取資料只需要3分鐘,我優化之後反而增加到了5分鐘。

我的最佳化方案是,將檔案整塊讀入內存,放在char*的buffer中,再使用vec_name.reserve(50000000);分配五千萬的容量,避免重複分配內存,但是好像沒有什麼作用。

難道是因為時間主要花在push_back上面了麼?

請問有什麼好的最佳化方法麼?謝謝各位大神了!
優化後的關鍵程式碼如下:(需要五分鐘才能將全部資料讀入vector)

        
        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级讲师

全部回覆(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試試


哇怎麼這麼對待我答案的?檢舉我的網友倒是說說,這答案怎麼就有問題了?

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板