我有一个函数,它接受一个参数并产生一个结果.不幸的是,函数产生结果需要很长时间.使用相同的输入经常调用该函数,这就是为什么我可以方便地缓存结果.就像是
let cachedFunction = createCache slowFunction
in (cachedFunction 3.1) + (cachedFunction 4.2) + (cachedFunction 3.1)
Run Code Online (Sandbox Code Playgroud)
我正在研究Data.Array,虽然数组是懒惰的,但我需要用一对对象(使用listArray)初始化它 - 这是不切实际的.如果'key'是例如'Double'类型,我根本无法初始化它,即使理论上我可以为每个可能的输入分配一个Integer,我有几万个可能的输入,我实际上只使用了少数几个.我需要使用函数而不是列表初始化数组(或者,最好是哈希表,因为只使用少量的resutls).
更新:我正在阅读备忘录文章,据我所知,MemoTrie可以按我想要的方式工作.也许.有人可以尝试生成'cachedFunction'吗?对于一个需要2个Double参数的慢函数?或者,或者,在〜[0..1亿]的域中采用一个不会占用所有内存的Int参数?
我在Haskell中寻找一个可变(平衡)树/ map/hash表,或者在函数内部如何模拟它.即,当我多次调用相同的函数时,结构将被保留.到目前为止,我已经尝试了Data.HashTable(可以,但有点慢)并尝试了Data.Array.Judy,但我无法使其与GHC 6.10.4一起使用.还有其他选择吗?
这段代码泄漏了内存(非常快,如果你尝试的话,准备很快杀死它):
import Control.Monad (forever)
main = do
forever $ forever $ return ()
Run Code Online (Sandbox Code Playgroud)
(编译-O2,-O,-O0 ......,ghc 7.0.3)我不明白为什么要泄漏 - 我使用了很多这样的代码与异常处理程序之间的永远和我不很明白为什么这应该泄漏记忆..
我只是查看了Control.Monad的源代码,发现了这个:
{- Note [Make forever INLINABLE]
If you say x = forever a
you'll get x = a >> a >> a >> a >> ... etc ...
and that can make a massive space leak (see Trac #5205)
In some monads, where (>>) is expensive, this might be the right
thing, but not in the IO monad. We want to specialise …Run Code Online (Sandbox Code Playgroud) 我想我有点理解应用程序仿函数在Haskell中是如何工作的,我将它们用于基本数据类型(Maybe,Either ......).但是,我通过以下示例找到了这个问题:
withPool pool = bracket (takeConn pool) (putConn pool)
Run Code Online (Sandbox Code Playgroud)
可以用应用风格重写:
withPool = bracket <$> takeConn <*> putConn
Run Code Online (Sandbox Code Playgroud)
我很惊讶它编译,确实它按预期工作,但有人可以告诉我哪个Applicative Functor用于此以及如何定义?
更新:我想我弄清楚它是如何工作的,但我不知道它在哪里定义.
我试图用最少的策略在Haskell中编写负载均衡器(部分是为了好玩......).我需要一个优先级队列,其中只需要以下操作"快速":
如果我有一个带指针的命令式语言,我可能会带来:
Head
|
Priority 0 -> Item <-> Item <-> Item <-> Item
|
Priority 1 -> Item <-> Item
|
Priority 4 -> Item <-> Item <-> Item
Run Code Online (Sandbox Code Playgroud)
优先级使用双向链表连接,每个优先级的项目也是如此.每个都Item包含指向头部优先级的链接.这种结构会有复杂性:
是否存在一些行为大致相同的(功能?)数据结构?物品数量最多约为几百个.
我正在编写一些'类似openvpn'的东西,并认为它将是一个很好的候选人来提高我的Haskell知识.但是,我遇到了相当严重的性能问题.
它的作用:它打开一个TUN设备; 它将自己绑定在UDP端口上,启动2个线程(forkIO,但是由于fdRead而使用-thaded编译).我没有使用过tuntap软件包,而是在Haskell中自己完成了.
线程1:从tun设备读取数据包(fdRead).使用UDP套接字发送它.
线程2:从UDP套接字读取数据包(recv); 将它发送到tun设备(fdWrite)
问题1:在这个配置中,fdRead返回String,我使用了接受String的Network.Socket函数.我在本地系统(一些iptables魔术)上进行了配置,我可以在localhost上运行15MB/s,程序基本上在100%CPU上运行.那很慢.我有什么办法可以改善表现吗?
问题2:我必须在我发送的数据包之前添加一些内容; 但是sendMany网络函数只接受ByteString; 从Fd读取返回String.转换速度很慢.使用TUN设备转换为Handle似乎效果不佳....
问题3:我想在Data.Heap(功能堆)中存储一些信息(我需要使用'takeMin',虽然对于3个项目来说太过分了,但很容易做到:)).所以我创建了一个MVar,并且在每个接收到的数据包上我从MVar中取出了Heap,用新信息更新了Heap并将它放回到init的MVar现在,它只是开始吃大量的内存.可能是因为旧的堆不会很快/经常收集垃圾......?
有没有办法解决这些问题,还是我必须回到C ......?我正在做的应该主要是zerocopy操作 - 我使用错误的库来实现它吗?
==================
我做了什么: - 当放到MVar时,做了:
a `seq` putMVar mvar a
Run Code Online (Sandbox Code Playgroud)
这完全有助于内存泄漏.
我有代码根据指定的规则进行一些文件解析.整个解析发生在monad中,它是ReaderT/STTrans/ErrorT的堆栈.
type RunningRule s a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String Identity)) a
Run Code Online (Sandbox Code Playgroud)
因为在代码中运行一些IO会很方便(例如查询外部数据库),我想我会概括解析,这样它就可以在Identity或IO base monad中运行,具体取决于我想要的功能.这将签名更改为:
type RunningRule s m a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String m)) a
Run Code Online (Sandbox Code Playgroud)
在更改了适当的类型签名(并使用一些扩展来绕过类型)之后,我再次在Identity monad中运行它,它的速度慢了约50%.虽然基本没什么变化,但速度要慢得多.这是正常的行为吗?有一些简单的方法可以让它更快吗?(例如,将ErrorT和ReaderT(以及可能的STT)堆栈组合成一个monad变换器?)
要添加代码示例 - 基于解析的输入(以类C语言给出)构建解析器是一件事.代码如下所示:
compileRule :: forall m. (Monad m, Functor m) =>
-> [Data -> m (Either String Data)] -- For tying the knot
-> ParsedRule -- This is the rule we are compiling
-> Data -> m (Either String Data) -- The …Run Code Online (Sandbox Code Playgroud) 我正在考虑为我想解决的一个问题利用并行性.问题大致如下:给定输入(点序列)找到最佳输出(由这些点组成的最大三角形,最长线等).在点序列中有3种不同的"形状",但我只对"最佳得分"(通常是某种形式的"长度"倍数系数)感兴趣.我们称之为形状S1,S2,S3.
我有2种不同的算法来解决S1 - 'S1a'在O(n 2)中,'S1b'大多表现得更好,但最坏的情况是O(n 4).
第一个问题:是否有一些简单的方法可以并行运行S1a和S1b,使用先完成并停止另一个的方法?至于我正在阅读文档,这可以使用一些forkIO编程并在获得结果时杀死线程 - 只是询问是否有更简单的东西?
第二个问题 - 更加困难:我以这种方式调用优化函数:
optimize valueOfSx input
Run Code Online (Sandbox Code Playgroud)
valueOfSx特定于每个形状,并返回"得分"(或得分的猜测)可能的解决方案.优化调用此函数以找出最佳解决方案.我感兴趣的是:
s1 = optimize valueOfS1 input
s2 = optimize valueOfS2 input
s3 = optimize valueOfS3 input
<- maximum [s1,s2,s3]
Run Code Online (Sandbox Code Playgroud)
但是,如果我知道S1的结果,我可以丢弃所有较小的解决方案,从而使s2和s3收敛得更快,如果不存在更好的解决方案(或者至少丢弃最差的解决方案,从而提高空间效率).我现在在做的是:
zeroOn threshold f = decide .f
where decide x = if (x < threshold) then 0 else x
s1 = optimize valueOfS1 input
s2 = optimize (zeroOn s1 valueOfS2) input
s3 = optimize (zeroOn (max s1 s2) valueOfS3) input
Run Code Online (Sandbox Code Playgroud)
现在的问题是:我能以这样的方式如运行S2和S3并行,无论哪完成第一次将更新其他线程运行的得分功能的"门槛"参数?在某种意义上的东西:
threshold = 0 …Run Code Online (Sandbox Code Playgroud) parallel-processing concurrency haskell speculative-execution
我正在编写一个多线程程序,它充分利用了mvars; 在这种情况下,我有一个线程,周期性地更改mvar内的列表.不幸的是,有一个thunk内存泄漏.似乎有一种问题是'map id'(在实际程序中我使用的不是id的东西)函数泄漏.我只是找不到如何避免这种情况的方法 - 我正在使用'seq'而没有结果.什么是修复泄漏的正确方法?
upgraderThread :: MVar [ChannelInfo] -> IO ()
upgraderThread chanMVar = forever job
where
job = do
threadDelay 1000
vlist <- takeMVar chanMVar
let reslist = map id vlist
putMVar chanMVar reslist
Run Code Online (Sandbox Code Playgroud) 我正在Haskell中编写一些优化应用程序,我只是通过profiler运行它.我可以看到许多功能和一个奇怪的符号"== _ a3JO"(有时候不同的数字和字母).它代表什么?
样本输出:
maxDistanceRaw Igc 360 471912 5.2 5.7 19.8 20.3
distance Igc 364 30143010 1.3 1.0 14.6 14.6
distanceRad Igc 365 30143010 10.4 8.8 13.3 13.6
==_a3JO Igc 366 30143010 2.9 4.9 2.9 4.9
==_a3JO Igc 350 233432454 35.3 36.9 35.3 36.9
Run Code Online (Sandbox Code Playgroud) haskell ×10
memory-leaks ×2
performance ×2
applicative ×1
caching ×1
concurrency ×1
ghc ×1
hashtable ×1
memoization ×1
mutable ×1
networking ×1
profiling ×1