限制Haskell计算的运行时间

我在Haskell中编写游戏AI,我想在指定的时间内搜索游戏状态树(例如,我希望AI始终花3秒钟来决定采取什么行动)

在像Haskell这样的纯语言中,我该如何实现这一点?我预计我需要深入研究线程等内容,但如果可以的话,我希望尽量减少这方面的使用。


回答:

一个想法:结合timeout(由@MathematicalOrchid建议)以及来自SafeSemaphore的可变变量,每次你的进程计算出部分结果时存储中间值:

import Control.Monadimport Control.Concurrent.MSampleVarimport System.Timeoutfac :: Integer -> Integerfac 0 = 1fac n = n * fac (n - 1)tmo :: Int -> ((a -> IO ()) -> IO ()) -> IO (Maybe a)tmo ms f = do    mvar <- newSV Nothing    timeout ms (f (writeSV mvar . (Just $!)))    readSV mvarlongComp :: (Integer -> IO ()) -> IO ()longComp save = let loop n = save (fac n) >> loop (n + 1)                in loop 0main :: IO ()main = tmo 10000 longComp >>= print

传递给tmo的函数将其第一个参数作为一个IO动作,用于保存中间结果。如果超时,最后保存的结果将被返回。结果被转换为WHNF,因此实际计算发生在保存结果的线程中,而不是在从tmo返回时处理它的线程中。

在这种变体中,传递给tmo的函数必须保存其输出,而不能返回它。但很容易修改它的签名,使其为(a -> IO ()) -> IO a

如果你想保持更纯净的代码,我建议你创建一个自己的单子(monad),来封装这个想法而不让IO泄露出来。


更新:请注意:

无法保证异常会立即被传递,尽管运行时会努力确保不会发生任意延迟。在GHC中,只有当线程到达安全点时才会引发异常,安全点是指发生内存分配的地方。有些循环在循环内部不执行任何内存分配,因此无法被throwTo中断。

(来自throwTo的文档)。在上面的例子中,fac不分配任何内存,因此对于大数它不会立即被中断。

更新:我基于这些想法创建了一个小型库,该库定义了可以返回部分结果的单子,在返回最终结果之前或在超时时终止。请参见https://github.com/ppetr/timeout-with-results

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注