2015-12-30 130 views
0

我正在实施一个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; 

注:通常emitkeyvalue是基于模板的,但我忽略了他们在这个例子中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()以消除未使用的矢量的内存是不可行的,原因有二:

  1. 这将大大降低性能。在不调用emit的情况下,只计算280MB的文件的字数,在1329ms的总时间执行时间内(在第一次读取文件时约为5000s),需要1242ms。
  2. 使用此解决方案时,最终用户应该在编写map函数时深入考虑内存使用情况,这通常不会发生在像Hadoop这样的经典地图/缩减框架中。
+0

您是否尝试使用调试器来查看引发异常的位置? –

+0

正如我在问题中所说的那样,由于我在远程Xeon Phi上启动了该程序,因此无法进行调试。 – justHelloWorld

回答

0

问题不是vector所用的空间,它是容量较小时以前由矢量使用的所有空间。除非您在向量上调用reserve,否则当您推入第一个元素时,它将开始为空,并分配少量空间(对于一个元素通常足够大)。在稍后的推送中,如果没有足够的剩余空间分配,它将分配更多(1.5倍或2倍的当前大小)。这意味着你需要足够的空闲内存来用于较小的尺寸和较大的内存。因为释放的内存块在组合时仍然不足以满足下一个较大的请求量,则可能会有很多免费但未使用的内存。

您应该致电res.reserve(/*appropriate large size*/),或将容器切换为deque,尽管最终需要更多空间,但在增长时不需要进行重新分配。为了保留大小,您可以走一遍文件,查看其中有多少单词,为它们预留空间,然后再次行走并保存单词。

+0

回答了更新问题 – justHelloWorld

相关问题