如何定位过度扩展目标的原因?

How can I localize the reasons for excessive goal expansion?

SICStus Prolog 4.5.1 的执行分析器给了我以下输出:

| ?- print_profile.
       insns   try/retry      called        name
----------------------------------------------------------------
                             4965857/4965857    prolog:wellformed_body_expand/11
   201383839     4965857     4965857        prolog:call_goal_expansion/6
                            *4860319/4860363    prolog:choice/0
                             4860319/9720726    prolog:in_hook_flag/2
                             4860319/9006266    prolog:prolog_catch/3
----------------------------------------------------------------
                             4965868/4965868    prolog:wellformed_body_iso/11
   178771039    19863439     4965868        prolog:wellformed_body_expand/11
                             4965857/4965857    prolog:call_goal_expansion/6
                             4965857/4965857    prolog:goal_exp/8
                             4965857/4965857    prolog:wf_source_module/2
----------------------------------------------------------------
   165399306     5469803     ...
----------------------------------------------------------------
                             3044459/3044459    prolog:dcg_translate_dcg_safe/8
   163441583    23688395     3044459        prolog:dcg_translate_dcg_atom/6
----------------------------------------------------------------
                             ...

很费解!似乎所有工作的 3/4(table 中的第 1 列)是由于目标扩展。

但是为什么呢? 如何本地化导致所有这些目标扩展的代码?请帮忙!


编辑:新的分析结果

@PerMildner 的回答和评论指出了解决问题的方法。使用 library(clpz) magic_square__no_sym(4) 的新执行分析结果(大小为 4x4 的魔方,角点之间有额外的约束以消除对称解决方案)看起来 很多 更合理:

| ?- print_profile.
       insns   try/retry      called        name
----------------------------------------------------------------
                             1197973/2041757    clpz:fd_put/3
                              843784/2041757    clpz:fd_put/5
   153514528     5339777     2041757        clpz:put_terminating_q/4
                               34012/8145271    clpz:domain_infimum/2
                               34012/8263457    clpz:domain_supremum/2
                                  16/1224480    clpz:new_queue/1
                               51821/51821      clpz:queue_goal_q/2
                              620022/620022     clpz:trigger_props_q/5
----------------------------------------------------------------
                             1197973/1224480    clpz:fd_put/3
                                  16/1224480    clpz:put_terminating_q/4
                               26357/1224480    clpz:trigger_once/1
                                 134/1224480    clpz:variables_same_queue/1
   113876576           0     1224480        clpz:new_queue/1
----------------------------------------------------------------
                             ...

这种情况下目标扩展变化的性能影响非常可观:2X !

当没有可用的目标扩展时,SICStus 试图变得聪明。在这种情况下,通常可以避免调用 call_goal_expansion。然而,如果有一个目标扩展可见(例如通过加载 clpz)并且该目标扩展的索引很差,那么将尝试完整的目标扩展处理。后者可能是因为 clpz:goal_expansion/5.

的 "defaulty" last clause 而发生的情况

请注意,在这种情况下,无法通过添加剪切来解决 "poor indexing"。在内部,SICStus 会查看 goal_expansion/5 谓词的索引数据结构,以确定其任何子句是否适用。包罗万象的子句,如链接的子句,会使此测试失败,并且将调用完整的、较慢的 call_goal_expansion