我有一个基于规则的系统,有几个100K的事实,而且我用PyCLIPS获得的性能很差,只是为了加载事实。
我已将其缩小为一个简单的示例,其中包含两个模板和一个连接它们的规则(并且不做任何其他操作):
import clips
import timeit
env = clips.Environment()
env.BuildTemplate('F1', '(slot x (type INTEGER))')
env.BuildTemplate('F2', '(slot x (type INTEGER))')
env.BuildRule('Rule1', '(F1 (x ?val)) (F2 (x ?val))', '')
N = 20000
with open('F1.txt', 'w') as f1:
with open('F2.txt', 'w') as f2:
for n in xrange(N):
print >>f1, '(F1 (x {}))'.format(n)
print >>f2, '(F2 (x {}))'.format(n)
print timeit.timeit(lambda : env.LoadFacts('F1.txt'), number=1)
print timeit.timeit(lambda : env.LoadFacts('F2.txt'), number=1)
输出:
0.0951321125031
14.6272768974
因此第二批20K事实需要14.6秒才能加载。从CLIPS控制台加载相同的事实文件是即时的。检查N
的不同值表明加载时间大致与sqr(N)
成比例(使得这对于大量事实完全无法使用)。
切换操作的顺序,并在加载事实后定义规则并不能使事情变得更好(显然最后的操作总是很慢)。
是否有人熟悉此问题?我是否以错误的方式使用PyCLIPS?
我正在运行PyCLIPS v1.0.7.348
和CLIPS v6.3
。
答案 0 :(得分:1)
CLIPS 6.3在连接中使用散列来比较从一种模式到另一种模式的变量。当存在大量与您的示例中的事实和规则类似的事实和规则时,这可以显着提高性能。在CLIPS的先前版本中,当断言新的F1事实时,将在匹配第二模式的所有F2事实上发生迭代(并且对于每个新的F2事实将发生类似的迭代)。在版本6.3中,迭代仅发生在散列到同一存储桶的事实中,其值为?val。 PyCLIPS网站上的自述文件页面表明它是用CLIPS 6.24编译的,所以这可以解释性能上的差异。我不记得6.24和6.3之间存在任何重大的API差异,因此可以使用较新版本的CLIPS重新编译PyCLIPS以获得性能改进。