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