Я реализую параллельный проект map/reduce. Однако, используя входной файл (более или менее) 1 ГБ, для примера слов с подсчетом слов, только с одним картографом (который отображает весь файл), я получаю исключение std::bad_alloc
. К сожалению, это происходит только на удаленном Xeon Phi (с меньшей ОЗУ), поэтому нет глубокой отладки.Почему 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;
Примечание: обычно key
и value
в emit
шаблоно основе, но я опускаю их claricity в этом примере.
В первую очередь я думал, что std::bad_alloc
был выброшен из-за char *value
(который занимает 1 Гб), но было брошено исключение после тестирования cout
сообщения, размещенного после value
распределения (так that'not проблем).
Из того, что я прочитал о реализации strtok
, изменен оригинал char*
(добавление \0
в конце каждого токена), поэтому не добавляется дополнительная память.
Единственная оставшаяся возможность - это занятое пространство vector<pair<char*,int>>
, но я не могу определить его пространство (пожалуйста, помогите мне об этом). Предполагая, что средняя длина слова составляет 5 символов, мы должны иметь ~ 2 * 10^8 слов.
UPDATE ПОСЛЕ 1201ProgramAlarm's answer: К сожалению, предвычисления количество слов, а затем вызвать resize()
для того, чтобы исключить память не использованные вектора не представляется возможным по двум причинам:
- Это позволит значительно снизить производительность. Не вызывая
emit
и считая только слова файла размером 280 МБ, он занимает 1242 мс в течение общего времени выполнения 1329 мс (~ 5000 секунд, когда файл читается впервые). - Используя это решение, конечный пользователь должен глубоко учитывать использование памяти, когда он записывает функцию карты, чего обычно не бывает в классических картах/сокращениях, таких как Hadoop.
Пробовал ли вы использовать отладчик, чтобы увидеть, где вызывается исключение? –
Как я уже сказал в вопросе, я не могу отлаживать, так как я запускаю программу на удаленном Xeon Phi. – justHelloWorld