【问题标题】:Using custom new-handler with Eigen library使用带有 Eigen 库的自定义 new-handler
【发布时间】:2012-10-13 14:59:35
【问题描述】:

我正在尝试使用自定义新处理程序来响应我使用 Eigen 库的程序中的内存不足错误。

当我解决一个实例时,我会缓存结果(一个大的 动态 大小的向量),所以如果我需要再次解决那个实例,我已经有了结果。一段时间后,可能会缓存太多实例,因此在计算过程中没有足够的内存。在这种情况下,我会清空缓存(或者最好删除一些实例)。

我想出的最简单的方法是拥有一个全局变量std::map<InputType, ResultType> cache,并安装一个清空它的新处理程序(除非它已经是空的,否则它会使用默认处理程序)。这样,当分配失败时,我的处理程序会释放一些内存并返回,因此会再次尝试分配内存。

但似乎从未调用过此类处理程序,而是始终抛出 std::bad_alloc 异常。

我尝试了这个取自here 的示例。使用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 一起使用?还是我必须在高层捕获异常,清除缓存,然后再次执行计算?

【问题讨论】:

    标签: c++ new-operator eigen


    【解决方案1】:

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

    【讨论】:

    • 感谢您的建议,我设法实现了我正在寻找的行为。我发布了一个包含详细信息的新答案。
    【解决方案2】:

    感谢 Benoit Jacob 的建议,我找到了 Eigen 分配内存的部分。该函数是在Eigen/src/Core/util/Memory.h 中定义的aligned_malloc()。原来它没有使用operator new,而是调用malloc()

    我找到了这个example for implementing 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() 获取内存,但它通过抛出 std::bad_alloc 来通知 malloc() 失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 2014-01-23
      • 1970-01-01
      • 2020-11-18
      • 2012-12-07
      相关资源
      最近更新 更多