我正在實施一個map/reduce並行項目。然而,使用一個輸入文件(或多或少)1GB,對於一個字數玩具的例子,只有一個映射器(它映射整個文件),我收到一個std::bad_alloc
異常。不幸的是,這隻發生在遠程Xeon Phi(更小的RAM)上,所以沒有深度調試。爲什麼std :: bad_alloc被拋出?
然而,內存資源佔用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
key
和value
是基於模板的,但我忽略了他們在這個例子中claricity。
在我認爲std::bad_alloc
是由於char *value
(這需要1GB)拋出的第一位置,但異常被測試cout
消息放置在value
分配之後(因此that'not問題)後拋出。
從我讀到的關於strtok
的實現中,原始的char*
被修改(在每個令牌的末尾添加\0
),所以沒有增加內存分配。
唯一剩下的可能性是vector<pair<char*,int>>
佔用的空間,但我無法計算其空間(請幫助我)。假設平均字長爲5個字,我們應該有〜2 * 10^8個字。
更新後1201ProgramAlarm's answer: 不幸的是,預先計算單詞的數量,然後調用resize()
以消除未使用的矢量的內存是不可行的,原因有二:
- 這將大大降低性能。在不調用
emit
的情況下,只計算280MB的文件的字數,在1329ms的總時間執行時間內(在第一次讀取文件時約爲5000s),需要1242ms。 - 使用此解決方案時,最終用戶應該在編寫map函數時深入考慮內存使用情況,這通常不會發生在像Hadoop這樣的經典地圖/縮減框架中。
您是否嘗試使用調試器來查看引發異常的位置? –
正如我在問題中所說的那樣,由於我在遠程Xeon Phi上啓動了該程序,因此無法進行調試。 – justHelloWorld