gpt4 book ai didi

wolfram-mathematica - 用内存构造函数的最佳方法

转载 作者:行者123 更新时间:2023-12-03 12:33:47 26 4
gpt4 key购买 nike

美好的一天,

我有一些非常简单和复杂的功能,比如f[x,y]。而且我需要构造它的详细ContourPlot。此外,由于缺少物理内存,功能f[x,y]有时会失败。在这种情况下,我必须停止评估,自己调查点{x,y}的问题情况。然后,我应该将元素{x,y,f [x,y]}添加到f[x,y]的计算值列表(例如“cache”),然后重新开始ContourPlot的评估。 ContourPlot必须从缓存中获取所有已经计算出的f值。我希望将此类列表存储在某个文件中,以便以后可以重用。手动将有问题的点添加到此文件中可能更简单。

如果f的计算值列表可能包含10000-50000点,最快的实现方法是什么?

最佳答案

假设我们的慢速函数具有签名f[x, y]

纯内存方法

如果您对内存缓存感到满意,那么最简单的方法就是使用备忘录:

Clear@fmem
fmem[x_, y_] := fmem[x, y] = f[x, y]

每次调用它时,都会使用以前从未见过的参数组合为其添加一个定义。

文件支持的内存中方法

但是,如果在长时间计算期间内存不足或发生内核崩溃,则将需要某种持久性来支持此缓存。最简单的事情是保留一个正在运行的日志文件:
$runningLogFile = "/some/directory/runningLog.txt";

Clear@flog
flog[x_, y_] := flog[x, y] = f[x, y] /.
v_ :> (PutAppend[Unevaluated[flog[x, y] = v;], $runningLogFile]; v)

If[FileExistsQ[$runningLogFile]
, Get[$runningLogFile]
, Export[$runningLogFile, "", "Text"];
]
flogfmem相同,除了它还会在运行日志中写入一个条目,该条目可用于在以后的 session 中还原缓存的定义。最后一个表达式在找到现有日志文件时(或如果不存在则创建该文件)重新加载这些定义。

当需要手动干预时,日志文件的文本性质很方便。请注意,浮点数的文本表示会带来不可避免的舍入错误,因此从日志文件重新加载值后,结果可能会略有不同。如果这是一个非常令人关注的问题,尽管我将这种方法的细节留给读者,但由于保留增量日志并不十分方便,因此您可以考虑使用二进制 DumpSave功能。

SQL方法

如果内存确实很紧张,并且您希望避免使用较大的内存缓存来为其他计算腾出空间,则先前的策略可能不合适。在这种情况下,您可以考虑使用Mathematica的内置SQL数据库完全在外部存储高速缓存:
fsql[x_, y_] :=
loadCachedValue[x, y] /. $Failed :> saveCachedValue[x, y, f[x, y]]

我在下面定义 loadCachedValuesaveCachedValue。基本思想是创建一个SQL表,其中每行包含一个 xyf三元组。每次需要值时都会查询SQL表。请注意,这种方法比内存中的缓存要慢得多,因此,当 f的计算花费的时间比SQL访问时间长得多时,这种方法才有意义。 SQL方法不会遭受困扰文本日志文件方法的舍入错误。

现在遵循 loadCachedValuesaveCachedValue的定义,以及其他一些有用的辅助函数:
Needs["DatabaseLink`"]

$cacheFile = "/some/directory/cache.hsqldb";

openCacheConnection[] :=
$cache = OpenSQLConnection[JDBC["HSQL(Standalone)", $cacheFile]]

closeCacheConnection[] :=
CloseSQLConnection[$cache]

createCache[] :=
SQLExecute[$cache,
"CREATE TABLE cached_values (x float, y float, f float)
ALTER TABLE cached_values ADD CONSTRAINT pk_cached_values PRIMARY KEY (x, y)"
]

saveCachedValue[x_, y_, value_] :=
( SQLExecute[$cache,
"INSERT INTO cached_values (x, y, f) VALUES (?, ?, ?)", {x, y, value}
]
; value
)

loadCachedValue[x_, y_] :=
SQLExecute[$cache,
"SELECT f FROM cached_values WHERE x = ? AND y = ?", {x, y}
] /. {{{v_}} :> v, {} :> $Failed}

replaceCachedValue[x_, y_, value_] :=
SQLExecute[$cache,
"UPDATE cached_values SET f = ? WHERE x = ? AND y = ?", {value, x, y}
]

clearCache[] :=
SQLExecute[$cache,
"DELETE FROM cached_values"
]

showCache[minX_, maxX_, minY_, maxY_] :=
SQLExecute[$cache,
"SELECT *
FROM cached_values
WHERE x BETWEEN ? AND ?
AND y BETWEEN ? AND ?
ORDER BY x, y"
, {minX, maxX, minY, maxY}
, "ShowColumnHeadings" -> True
] // TableForm

此SQL代码使用浮点值作为主键。在SQL中,这通常是一个有问题的做法,但在当前上下文中效果很好。

在尝试使用任何这些功能之前,必须调用 openCacheConnection[]。完成后,您应该调用 closeCacheConnection[]。仅一次,您必须调用 createCache[]来初始化SQL数据库。提供 replaceCachedValueclearCacheshowCache用于手动干预。

关于wolfram-mathematica - 用内存构造函数的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5287817/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com