搜尋

首頁  >  問答  >  主體

objective-c - 使用C++從檔案讀取五千萬個資料存入vector中如何加快速度?

我需要從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中文网2739 天前1060

全部回覆(4)我來回復

  • 漂亮男人

    漂亮男人2017-05-31 10:38:40

    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和轉換函數的開銷,真正達到秒取資料。

    回覆
    0
  • phpcn_u1582

    phpcn_u15822017-05-31 10:38:40

    目前最有效率的辦法就是用流,而在你的程式碼實作中可以看出來:你是全部將文件內容一次性讀入buffer中,這種方式不是最好的。建議平均每次讀 buffer[1024] 也就是1K,或其他也可以。 讀完指針就移到下一行,繼續讀,直到EOF位置結束

    回覆
    0
  • 天蓬老师

    天蓬老师2017-05-31 10:38:40

    1.如果資料間沒有依賴關係的話,可以試試分塊多線程讀取;
    2.另外vector的內存是連續的,如果後面不是要隨機訪問,而都是遍歷的話,用list效率會高不少。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-05-31 10:38:40

    可以換用C風格的scanf試試


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

    回覆
    0
  • 取消回覆