我有一个lisp文件,它在循环中进行大量的采样,文件I / O和算术运算。 (我在常见的lisp中做particle filtering。)我正在使用compile-file
命令编译我的lisp文件。我还在我的lisp文件的开头使用(declaim (optimize (speed 3) (debug 0) (safety 0)))
,因为我想尽快得到我的结果。
我使用(time (load "/....../myfile.lisp")
和(time (load "/......./myfile.dx64fsl")
来衡量速度。问题是编译不会给我带来任何好处。没有任何进步。我做错了吗?有办法改善事情吗?速度是最重要的标准,因此我可以牺牲很多,以获得快速响应。我不知道这类问题,所以任何帮助都会受到赞赏
此外,当我将粒子数量(每个粒子是大小约为40的矢量)增加到10000时,代码变得非常慢,因此也可能存在一些内存问题。
非常感谢你提前。
编辑:这是包含1000个粒子和50次迭代的分析结果。
(LOAD "/.../myfile.dx64fsl") took 77,488,810 microseconds (77.488810 seconds) to run
with 8 available CPU cores.
During that period, 44,925,468 microseconds (44.925470 seconds) were spent in user mode
32,005,440 microseconds (32.005440 seconds) were spent in system mode
2,475,291 microseconds (2.475291 seconds) was spent in GC.
1,701,028,429 bytes of memory allocated.
1,974 minor page faults, 0 major page faults, 0 swaps.
; Warning: Function CREATE-MY-DBN has been redefined, so times may be inaccurate.
; MONITOR it again to record calls to the new definition.
; While executing: MONITOR::MONITOR-INFO-VALUES, in process repl-thread(10).
Cons
% % Per Total Total
Function Time Cons Calls Sec/Call Call Time Cons
------------------------------------------------------------------------------------------
SAMPLE: 25.61 26.14 2550000 0.000005 174 13.526 443040000
DISCRETE-PARENTS: 19.66 3.12 4896000 0.000002 11 10.384 52800000
LINEAR-GAUSSIAN-MEAN: 8.86 3.12 1632000 0.000003 32 4.679 52800000
DISCRETE-PARENT-VALUES: 7.47 12.33 3264000 0.000001 64 3.946 208896000
LIST-DIFFERENCE: 6.41 25.69 6528000 0.000001 67 3.384 435392000
CONTINUOUS-PARENTS: 6.33 0.00 1632000 0.000002 0 3.343 0
PF-STEP: 5.17 0.23 48 0.056851 80080 2.729 3843840
CONTINUOUS-PARENT-VALUES: 4.13 7.20 1632000 0.000001 75 2.184 122048000
TABLE-LOOKUP: 3.85 8.39 2197000 0.000001 65 2.035 142128000
PHI-INVERSE: 3.36 0.00 1479000 0.000001 0 1.777 0
PHI-INTEGRAL: 3.32 1.38 2958000 0.000001 8 1.755 23344000
PARENT-VALUES: 2.38 10.65 1122000 0.000001 161 1.259 180528016
CONDITIONAL-PROBABILITY: 1.41 0.00 255000 0.000003 0 0.746 0
------------------------------------------------------------------------------------------
TOTAL: 97.96 98.24 30145048 51.746 1664819856
Estimated monitoring overhead: 21.11 seconds
Estimated total monitoring overhead: 23.93 seconds
10000个粒子和50次迭代:
(LOAD "/.../myfile.dx64fsl") took 809,931,702 microseconds (809.931700 seconds) to run
with 8 available CPU cores.
During that period, 476,627,937 microseconds (476.627930 seconds) were spent in user mode
328,716,555 microseconds (328.716550 seconds) were spent in system mode
54,274,625 microseconds (54.274624 seconds) was spent in GC.
16,973,590,588 bytes of memory allocated.
10,447 minor page faults, 417 major page faults, 0 swaps.
; Warning: Funtion CREATE-MY-DBN has been redefined, so times may be inaccurate.
; MONITOR it again to record calls to the new definition.
; While executing: MONITOR::MONITOR-INFO-VALUES, in process repl-thread(10).
Cons
% % Per Total Total
Function Time Cons Calls Sec/Call Call Time Cons
-------------------------------------------------------------------------------------------
SAMPLE: 25.48 26.11 25500000 0.000006 174 144.211 4430400000
DISCRETE-PARENTS: 18.41 3.11 48960000 0.000002 11 104.179 528000000
LINEAR-GAUSSIAN-MEAN: 8.61 3.11 16320000 0.000003 32 48.751 528000000
LIST-DIFFERENCE: 7.57 25.66 65280000 0.000001 67 42.823 4353920000
DISCRETE-PARENT-VALUES: 7.50 12.31 32640000 0.000001 64 42.456 2088960000
CONTINUOUS-PARENTS: 5.83 0.00 16320000 0.000002 0 32.980 0
PF-STEP: 5.05 0.23 48 0.595564 800080 28.587 38403840
TABLE-LOOKUP: 4.52 8.38 21970000 0.000001 65 25.608 1421280000
CONTINUOUS-PARENT-VALUES: 4.25 7.19 16320000 0.000001 75 24.041 1220480000
PHI-INTEGRAL: 3.15 1.38 29580000 0.000001 8 17.849 233440000
PHI-INVERSE: 3.12 0.00 14790000 0.000001 0 17.641 0
PARENT-VALUES: 2.87 10.64 11220000 0.000001 161 16.246 1805280000
CONDITIONAL-PROBABILITY: 1.36 0.00 2550000 0.000003 0 7.682 0
-------------------------------------------------------------------------------------------
TOTAL: 97.71 98.12 301450048 553.053 16648163840
Estimated monitoring overhead: 211.08 seconds
Estimated total monitoring overhead: 239.13 seconds
答案 0 :(得分:4)
首先,永远不要永远在顶层与(speed 3)
一起声明(safety 0)
,即全局。这个 迟早会回来咬你的头。在这些级别,大多数常见的lisp编译器比C编译器执行更少的安全检查。对于instnace,一些lisps会在(safety 0)
代码中检查中断信号。接下来,(safety 0)
很少给出显着的收益。我会在热门函数中声明(speed 3)(safety 1)(debug 1)
,如果这会带来明显的收益,可能会转到(debug 0)
。
否则,如果没有实际查看某些实际代码,很难提出建议。从时间()看,似乎GC压力有点高。确保在热门函数中使用开放式编码算法,并且不要随意使用浮点数或整数。使用(disassemble 'my-expensive-function)
仔细查看编译器生成的代码。在高速优先编译时,SBCL将提供大量有用的输出,并且尝试消除其中一些警告是值得的。
使用快速数据结构表示粒子,使用可实例化的数组和宏观(如果需要)也很重要。
答案 1 :(得分:4)
Common Lisp中的典型算术运算速度很慢。改善它是可能的,但需要一些知识。
原因:
您可以从分析输出中看到的一件事是生成1.7 GB的垃圾。这是您的号码操作缺点的典型提示。要摆脱这种情况往往并不那么容易。我只是猜测,这些是数字操作。
Ken Anderson(不幸的是,他几年前去世了)在他的网站上提出了一些改进数字软件的建议:http://openmap.bbn.com/~kanderso/performance/通常的解决方案是将代码提供给一些经验丰富的Lisp开发人员,后者对所使用的编译器和/或优化有所了解。
答案 2 :(得分:2)
如果“myfile.lisp”中包含的所有代码都是您进行计算的部分,则编译该文件不会显着改善您的运行时。两种情况之间的区别可能是“我们编译一些循环”,调用在两种情况下编译或解释的函数。
要从编译中获得改进,您还需要编译调用的代码。您可能还需要对代码进行类型化注释,以便让编译器更好地进行优化。对于错过的注释,SBCL具有相当好的编译器诊断功能(人们抱怨它在编译时过于冗长)。
就加载时间而言,实际情况可能是加载编译文件需要更长的时间(如果您不经常更改代码,那么会发生一大堆基本上动态链接的情况,但更改您处理的数据,准备一个新的核心文件可能是一个优势,您的粒子过滤代码已经在核心内。)
答案 3 :(得分:1)
有几点:
尽可能将文件I / O移出循环;在迭代之前将数据批量读入内存。文件I / O比内存访问慢几个档次。
如果执行速度对您很重要,请尝试SBCL。
输入增加十倍导致执行时间增加大约十倍,这是线性的,所以你的算法似乎很好;只需要处理你的常数因素。
利用Lisp工作流程:编辑功能,编译功能和测试运行而不是编辑文件,编译文件和测试。当您的项目变得更大时(或者当您尝试使用SBCL时,差异将变得明显,这需要更长时间来分析/优化您的程序以生成更快的代码)。
答案 4 :(得分:1)
Welcome to Clozure Common Lisp Version 1.7-r14925M (DarwinX8664)!
? (inspect 'print)
[0] PRINT
[1] Type: SYMBOL
[2] Class: #<BUILT-IN-CLASS SYMBOL>
Function
[3] EXTERNAL in package: #<Package "COMMON-LISP">
[4] Print name: "PRINT"
[5] Value: #<Unbound>
[6] Function: #<Compiled-function PRINT #x30000011C9DF>
[7] Arglist: (CCL::OBJECT &OPTIONAL STREAM)
[8] Plist: NIL
Inspect> (defun test (x) (+ x 1))
TEST
Inspect> (inspect 'test)
[0] TEST
[1] Type: SYMBOL
[2] Class: #<BUILT-IN-CLASS SYMBOL>
Function
[3] INTERNAL in package: #<Package "COMMON-LISP-USER">
[4] Print name: "TEST"
[5] Value: #<Unbound>
[6] Function: #<Compiled-function TEST #x302000C5EFFF>
[7] Arglist: (X)
[8] Plist: NIL
Inspect>
请注意,#'print和#'测试都列为'已编译'。这意味着加载.lisp文件和加载编译文件之间唯一的性能差异是编译时间。我假设这不是你的场景中的瓶颈。通常不会,除非您使用一堆宏,并且执行代码转换是您的程序的主要目的。
这是我不处理已编译的lisp文件的主要原因之一。我只是在我的核心文件中加载我需要的所有共享库/包,然后在我处理特定项目时加载一些特定的.lisp函数/文件。并且,至少对于SBCL和CCL来说,一切都被列为“已编译”。