Eigenライブラリを使用するプログラムでメモリ不足エラーに対応するために、カスタムの new-handler を使用しようとしています。
インスタンスを解決すると、結果 (大きな動的サイズのベクトル) がキャッシュされるため、そのインスタンスを再度解決する必要がある場合は、既に結果が得られています。しばらくすると、キャッシュされたインスタンスが多すぎて、計算中に十分なメモリが残らない場合があります。この場合、キャッシュを空にします (または、いくつかのインスタンスを削除したほうがよいでしょう)。
私が思いついた最も簡単な方法は、グローバル変数std::map<InputType, ResultType> cache
を用意し、それを空にする new-handler をインストールすることです (既に空でない限り、デフォルトのハンドラーにフォールバックします)。このように、割り当てが失敗した場合、ハンドラーはメモリの一部を解放して戻るため、メモリを割り当てるための別の試行が行われます。
ただし、そのようなハンドラーは呼び出されないようで、代わりに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 で使用する方法はありますか? それとも、高レベルで例外をキャッチし、キャッシュをクリアして、計算を再度実行する必要がありますか?