7

f2 つのパラメーター (またはそれ以上)を受け取る OCaml 関数の結果をメモする方法を探しています。さらに (これが難しい部分です)、2 つのパラメーターの値のいずれかがガベージ コレクションされる場合、このプロセスの基礎となるマップが結果を完全に忘れるようにします。

引数を 1 つだけ取る関数の場合、これはWeakモジュールとそのMakeファンクターを使用して簡単に行うことができます。これをより高いアリティの関数を記憶できるものに一般化するための単純な解決策は、値のタプルから結果値への弱いマップを作成することです。しかし、値のタプルはメモ化関数のスコープ内にのみ存在し、 を呼び出すクライアント コード内には存在しないため、これはガベージ コレクションに関しては正しく機能しませんf。実際、弱い参照はタプルへのものであり、メモ化の直後にガベージ コレクションが行われます (最悪の場合)。

再実装せずにこれを行う方法はありWeak.Makeますか?

Hash-consing は私の要件と直交しており、実際、私の価値観にはあまり望ましくありません。

ありがとう!

4

3 に答える 3

3

1 つのアイデアは、独自のガベージ コレクションを実行することです。

簡単にするために、すべての引数が同じ type であると仮定しましょうk

によってキー付けされたメモ化された結果を含むメインの弱いテーブルに加えて、k * kタイプ の単一の引数を含む二次的な弱いテーブルを作成しますk。アイデアは、メイン テーブルを時々スキャンし、不要になったバインディングを削除することです。これは、2 次テーブルで引数を検索することによって行われます。それらのいずれかがなくなった場合は、メイン テーブルからバインディングを削除します。

(免責事項:私はこれをテストしていません。うまくいかないか、より良い解決策があるかもしれません)

于 2012-04-07T17:00:00.600 に答える
3

タプルによる索引付けの代わりに、ツリー構造を持つことができます。エントリが二次的な弱いテーブルである最初の関数パラメーターによってインデックス付けされた 1 つの弱いテーブルがあります。セカンダリ テーブルは、2 番目の関数パラメーターによってインデックスが作成され、メモ化された結果が含まれます。この構造は、いずれかの関数パラメーターが GC されるとすぐに、メモ化された関数の結果を忘れます。ただし、最初の関数パラメーターが有効である限り、セカンダリ テーブル自体は保持されます。関数の結果のサイズとさまざまな最初のパラメーターの分布によっては、これは妥当なトレードオフになる可能性があります。

私もこれをテストしていません。また、それはかなり明白なようです。

于 2012-04-07T22:19:59.483 に答える
1

これが古い質問であることは承知していますが、私の同僚は最近、この機能を処理できる Adapton と呼ばれるインクリメンタル計算ライブラリを開発しました。コードはこちらにあります。おそらく、LazySABidi ファンクタを使用することをお勧めします (その他はベンチマーク用です)。ライブラリの使用方法の例については、Applications フォルダを参照してください。ご不明な点がございましたら、お気軽にお問い合わせください。

于 2013-12-16T00:42:48.487 に答える