Использование нового обработчика с библиотекой Eigen

Я пытаюсь использовать пользовательский новый обработчик для ответа на ошибки нехватки памяти в программе, где я использую собственный библиотека.

Когда я решаю экземпляр, я кеширую результаты (большой динамический размер вектора), поэтому, если мне нужно решить этот экземпляр снова, у меня уже есть результаты. Через некоторое время может случиться так, что кешируется слишком много экземпляров, поэтому во время вычислений не хватает памяти. В этом случае я бы очистил кеш (или лучше удалил несколько экземпляров).

Самый простой способ, которым я придумал, это иметь глобальную переменную std::map<InputType, ResultType> cacheи установить новый обработчик, который опустошает его (если он уже не пустой, то он возвращается к обработчику по умолчанию). Таким образом, когда распределение завершается неудачно, мой обработчик освобождает часть памяти и возвращает ее, поэтому делается еще одна попытка выделить память.

Однако кажется, что такой обработчик никогда не вызывается, а std::bad_alloc Исключение всегда выбрасывается.

Я попробовал этот пример взят из Вот. Когда используешь std::vector<int> пользовательский обработчик вызывается правильно, и выводится «Выделение памяти завершено». Когда используешь Eigen::VectorXi Я только получил std::bad_alloc исключение.

#include <Eigen/Dense>

#include <iostream>
#include <vector>
#include <new>

void handler()
{
std::cout << "Memory allocation failed, terminating\n";
std::set_new_handler(nullptr);
}

int main()
{
std::set_new_handler(handler);
try {
while(true) {
const unsigned long int Size = 100000000ul;

// Either one of the following:

// new Eigen::VectorXi(Size);
new std::vector<int>(Size);
}
} catch (const std::bad_alloc & e) {
std::cout << e.what() << '\n';
}
}

Интересно, почему это происходит, возможно, Эйген не использует operator new выделить память? Я не смог найти ничего в документации. Есть ли способ использовать эту технику с Eigen? Или я должен перехватить исключение на высоком уровне, очистить кеш и снова выполнить вычисления?

3

Решение

Проверьте этот файл в исходном коде Eigen: Eigen / src / Core / util / Memory.h, чтобы увидеть, что Eigen делает в этом отделе. IIRC мы бросаем bad_alloc явно при неудачном размещении. Не стесняйтесь писать в список рассылки, если мы должны что-то изменить.

2

Другие решения

Благодаря совету Бенуа Джейкоба я отследил ту часть, где Эйген выделяет память. Функция aligned_malloc() определяется в Eigen/src/Core/util/Memory.h, Оказалось, он не использует operator new, но это вызывает malloc(),

я нашел это пример для реализации operator new и изменил функцию aligned_malloc() соответственно:

inline void* aligned_malloc(size_t size)
{
check_that_malloc_is_allowed();

while (true) {
void *result;
#if !EIGEN_ALIGN
result = std::malloc(size);
#elif EIGEN_MALLOC_ALREADY_ALIGNED
result = std::malloc(size);
#elif EIGEN_HAS_POSIX_MEMALIGN
if(posix_memalign(&result, 16, size)) result = 0;
#elif EIGEN_HAS_MM_MALLOC
result = _mm_malloc(size, 16);
#elif (defined _MSC_VER)
result = _aligned_malloc(size, 16);
#else
result = handmade_aligned_malloc(size);
#endif

if(result || !size) {
return result;
}

std::new_handler currentHandler = std::set_new_handler(0);
std::set_new_handler(currentHandler);

if (currentHandler) {
currentHandler();
} else {
throw_std_bad_alloc();
}
}
}

Теперь обработчик памяти корректно вызывается при сбое выделения (есть и другие функции выделения, которые также могут потребоваться изменить, но, похоже, все они обернуты aligned_malloc() так что проверка в этой функции может охватить все).

Однако на данный момент я не уверен, должен ли Eigen соблюдать новый обработчик: он получает память от malloc() который не использует исключения, но уведомляет malloc() неудачи, бросая std::bad_alloc,

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector