问题描述
我想找到一种方法来分析我在 prolog 中编写的谓词(一个巨大的)的内存使用情况.我目前正在使用 swi 和 yap 我可以从这些进程的内存消耗中看到分配了大量内存.
I'd like to find a way to profile the memory usage of a predicate (a huge one) I've written in prolog. I'm currently running it with swi and yap and I can see from those processes memory consumption that a big chunk of memory gets allocated.
问题是当谓词终止时它没有被释放/释放/垃圾收集(我必须停止解释器才能看到它)加上内存量只会保持增长而谓词正在运行(不管它不会因为尾递归优化应该在每次迭代中缓解这个问题).
The problem is that it does not get deallocated/freed/garbage collected when the predicate terminates (I have to halt the interpreter to see it back) plus the amount of memory only keeps growing while the predicate is running (wheather it shall not since tail recursion optimization should mitigate the issue, I guess, at each iteration).
有没有办法发现增加内存使用的子谓词/调用并检查尾递归优化是否被有效调用?
Is there a way to spot the subpredicate/call that increases the memory used and check if the tail recursion optimization is effectively being called?
关于如何优化问题的任何其他建议将不胜感激.如果有必要,我将提供有关谓词正在做什么的更多详细信息.
Any other suggestion on how to optimize the issue will be very appreciated. I will give more details about what the predicate is doing if those are necessary.
推荐答案
在 SWI-Prolog 中,一种查看递归谓词是否真正进行尾优化的简单方法是使用 prolog_current_frame
(
In SWI-Prolog, one easy way to see if your recursive predicate is actually getting tail-optimization is using prolog_current_frame
(look here):
foo :-
prolog_current_frame(F), format('~d~n',[F]),
do_something,
foo.
如果执行了尾部优化,则每次您通过递归调用输入谓词时,它都会返回相同的整数.我遇到了一个问题,我没有意识到我正在使用的谓词是创建选择点并阻止尾部优化.
If tail-optimization was performed, it will return the same integer each time you enter your predicate with a recursive call. I have had the problem that I do not realize that a predicate I am using is creating choice points and preventing tail-optimization.
如果没有尾部优化是实际问题,那么您可以做的其他事情就是在递归调用之前简单地进行切割:
If no tail optimization is the actual problem, then something else you could do is simply put a cut before the recursive call:
foo :-
do_something,
!, foo.
这将删除由 do_something
创建的任何选择点.如果您的内存使用量仍在增长,那么问题可能出在其他地方.您的谓词是否创建了大型数据结构?还是使用很多中间列表?
This will remove any choice points created by do_something
. If your memory use is still growing then the problem might be somewhere else. Is your predicate creating a large data structure? or using a lot of intermediate lists?
这篇关于Prolog 内存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!