簡體   English   中英

為什么會引發std :: bad_alloc?

[英]Why std::bad_alloc is thrown?

我正在實現一個map / reduce並行項目。 但是,對於一個字數玩具示例,使用一個(或多或少)1GB的輸入文件,並且只有一個映射器(映射整個文件),我會收到一個std::bad_alloc異常。 不幸的是,這僅發生在遠程Xeon Phi(具有較小的RAM)上,因此沒有進行深度調試。

但是,內存占用了2個地方:當映射器以char *讀取(存儲)整個文件時:

void getNextKeyValue() {
    key = pos;//int
    value = new char[file_size];//file_size only with 1 mapper
    ssize_t result = pread(fd, value, file_size, pos);
    assert(result == ( file_size ) );
    morePairs = false;
}

另一個則是在調用map函數時,將一系列pair<char*,int>存儲在vector作為地圖的結果:

地圖功能:

std::function<void(int key, char *value,MapResult<int,char*,char*,int> *result)> map_func = [](int key,char *value,MapResult<int,char*,char*,int> *result) {
    const char delimit[]=" \t\r\n\v\f";
    char *token , *save;
    token = strtok_r(value, delimit, &save);
    while (token != NULL){
        result->emit(token,1);
        token = strtok_r (NULL,delimit, &save);
    }
};

emit實現(以及地圖的結果生成):

    void emit(char* key, int value) {
        res.push_back(pair<char*,int>(key,value));
    }
    ...
    private:
    vector<pair<char*,int>> res;

注意:通常, emit中的keyvalue基於模板,但是在此示例中,為了清楚起見,我省略了它們。

首先,我認為是因為char *value (占用1GB)而引發了std::bad_alloc ,但是在value分配之后放置了一個測試cout消息之后引發了異常(所以這不是問題)。

根據我對strtok實現的了解,原來的char*被修改了(在每個標記的末尾添加\\0 ),因此沒有分配額外的內存。

剩下的唯一可能性是vector<pair<char*,int>>占用的空間,但是我無法弄清楚它的空間(請幫我解決這個問題)。 假設平均單詞長度為5個字符,則應該有〜2 * 10 ^ 8個單詞。

1201ProgramAlarm之后的更新:不幸的是,預先計算字數,然后調用resize()以消除未使用的向量的內存是不可行的,原因有兩個:

  1. 這樣會大大降低性能。 如果不調用emit並僅計算280MB文件的字數,則需要1342ms的總執行時間中的1242ms(第一次讀取文件時約為5000s)。
  2. 使用此解決方案,最終用戶在編寫map函數時應深刻考慮內存使用情況,而在Hadoop等經典map / reduce框架中通常不會發生這種情況。

問題不在於vector使用的空間,而是矢量在其容量較小時先前使用的所有空間。 除非您在向量上調用reserve ,否則它在開始按下第一個元素時會開始為空並分配少量空間(通常對於一個元素來說足夠大)。 在以后的推送期間,如果沒有分配足夠的剩余空間,它將分配更多空間(當前大小的1.5倍或2倍)。 這意味着您需要足夠的可用內存以用於較小的尺寸和較大的尺寸。 由於釋放的內存塊組合起來仍然不足以容納下一個更大的請求數量,因此可能會有很多空閑但未使用的內存。

您應該調用res.reserve(/*appropriate large size*/) ,或將容器切換為deque ,盡管最終將需要更多空間,但是隨着容器的增長,它不需要進行重新分配。 要保留大小,您可以遍歷一次文件以查看其中實際上有多少個單詞,為它們保留空間,然后再次遍歷並保存單詞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM