3

我正在尝试使用自定义新处理程序来响应我使用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';
    }
}

我想知道为什么会发生这种情况,也许 Eigen 不operator new用于分配内存?我在文档中找不到任何内容。有没有办法将这种技术与 Eigen 一起使用?还是我必须在高级别的地方捕获异常,清除缓存,然后再次执行计算?

4

2 回答 2

2

查看 Eigen 源代码中的这个文件:Eigen/src/Core/util/Memory.h,看看 Eigen 在这个部门做了什么。IIRC 我们确实在分配失败时明确抛出 bad_alloc 。如果我们要更改某些内容,请随时写信给邮件列表。

于 2012-10-16T22:19:53.730 回答
2

感谢 Benoit Jacob 的建议,我找到了 Eigen 分配内存的部分。该函数在 中aligned_malloc()定义Eigen/src/Core/util/Memory.h。原来它不使用 a 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()通过 throw 通知失败std::bad_alloc

于 2012-10-22T10:16:43.450 回答