2012-03-05 34 views
9

Tôi có một tập tin lisp mà rất nhiều lấy mẫu, tập tin I/O và số học trong một vòng lặp. (Tôi làm particle filtering trong lisp thông thường.) Tôi đang biên dịch tệp lisp của mình bằng cách sử dụng lệnh compile-file. Tôi cũng sử dụng các (declaim (optimize (speed 3) (debug 0) (safety 0))) ở đầu của tập tin lisp của tôi như tôi muốn có kết quả của tôi càng nhanh càng tốt.
Tôi sử dụng (time (load "/....../myfile.lisp")(time (load "/......./myfile.dx64fsl") để đo tốc độ. Vấn đề là biên dịch không mang lại lợi ích gì cho tôi. Không có cải tiến. Tôi có làm gì sai không? Có cách nào để cải thiện mọi thứ không? Tốc độ là tiêu chí quan trọng nhất để tôi có thể hy sinh rất nhiều để có được phản ứng nhanh. Tôi không có ý tưởng về loại vấn đề này nên mọi sự giúp đỡ sẽ được đánh giá cao.
Hơn nữa, khi tôi tăng số lượng hạt (mỗi hạt là một vectơ có kích thước ~ 40) đến 10000 mã sẽ rất chậm, do đó có thể có một số vấn đề về bộ nhớ.
Cảm ơn bạn rất nhiều trước.Common Lisp Biên dịch và thực hiện thời gian

chỉnh sửa: Đây là kết quả lược tả với 1000 hạt và 50 lần lặp.

(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 

với 10000 hạt và 50 lần lặp:

(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

vì vậy, tệp của bạn không chỉ chứa các định nghĩa chức năng? tức là, nó thực sự thực hiện một trong các chức năng đúng không? –

+0

Tôi thực sự có rất nhiều chức năng được xác định trong một số thư mục.Lần đầu tiên tôi tải nó. Sau đó, trong tập tin của tôi, trong một vòng lặp, tôi gọi một trong các hàm được định nghĩa để nhận được kết quả, đó là giá trị trung bình và phương sai của các biến truy vấn mà tôi có. Tôi sử dụng các chức năng khác để xây dựng mạng Bayes của tôi lúc đầu, sau đó tôi gọi một hàm duy nhất mỗi lần trong một vòng lặp để làm suy luận. – YBE

+0

Bạn có nên biên dịch các tệp khác không? –

Trả lời

4

Công cụ số học điển hình trong Common Lisp có thể chậm. Cải thiện nó là có thể, nhưng cần một chút kiến ​​thức.

Lý do:

  • số Common Lisp là không phải những gì máy cung cấp (bignums, hợp lý, phức tạp, ...)
  • thay đổi tự động từ Fixnum để bignum và lưng
  • hoạt động toán học chung
  • gắn thẻ sử dụng các bit có kích thước từ
  • consing of numbers

Một điều bạn có thể thấy từ đầu ra hồ sơ là bạn tạo ra 1,7 GB rác. Đây là một gợi ý điển hình cho rằng số hoạt động của bạn bị khuyết điểm. Để thoát khỏi điều đó thường không phải là dễ dàng. Nó chỉ là một đoán về phía tôi, rằng đây là những hoạt động số.

Ken Anderson (tiếc là ông qua đời một vài năm trước đây) có một số lời khuyên trên trang web của mình để cải thiện phần mềm số: http://openmap.bbn.com/~kanderso/performance/

Một giải pháp thông thường là để cung cấp cho các mã để một số nhà phát triển Lisp có kinh nghiệm mà biết một chút về trình biên dịch được sử dụng và/hoặc tối ưu hóa.

1

số điểm:

  1. Cố gắng di chuyển tập tin I/O ra khỏi vòng lặp nếu có thể; đọc dữ liệu vào bộ nhớ theo lô trước khi lặp lại. File I/O có độ trễ lớn hơn nhiều so với truy cập bộ nhớ.

  2. Hãy thử SBCL nếu tốc độ thực thi quan trọng đối với bạn.

  3. Tăng gấp 10 lần kết quả đầu vào của bạn trong khoảng thời gian thực hiện tăng gấp 10 lần, là tuyến tính, vì vậy thuật toán của bạn có vẻ tốt; chỉ cần làm việc trên yếu tố không đổi của bạn.

  4. Tận dụng luồng công việc Lisp: chức năng chỉnh sửa, chức năng biên dịch và chạy thử thay vì chỉnh sửa tệp, biên dịch tệp và kiểm tra. Sự khác biệt sẽ trở nên rõ rệt khi các dự án của bạn trở nên lớn hơn (hoặc khi bạn thử SBCL, sẽ mất nhiều thời gian hơn để phân tích/tối ưu hóa các chương trình của bạn để tạo mã nhanh hơn).

+0

Tôi đã thay thế tệp I/O bằng cách gán kết quả đầu ra cho vectơ. Tuy nhiên, nó không thay đổi bất cứ điều gì đáng kể. Nếu bạn có thể kiểm tra cấu hình ở trên, bạn có thể thấy rằng hầu hết thời gian được thực hiện bởi 'sample' và' pf-step'. Tôi có thể cố gắng song song với 'mẫu'. Nếu bạn có thêm lời khuyên nào tôi muốn nghe họ. Cảm ơn rất nhiều cho câu trả lời. – YBE

4

Trước hết, không bao giờ bao giờ tuyên bố (speed 3) cùng với (safety 0) ở cấp cao nhất, ví dụ: trên toàn cầu. Điều này sẽ sớm sớm hay muộn trở lại và cắn đầu bạn. Ở các cấp độ này, hầu hết các trình biên dịch lisp phổ biến đều làm việc kiểm tra an toàn kém hơn so với các trình biên dịch C. Đối với instnace, một số kiểm tra thả lisps cho các tín hiệu ngắt trong mã (safety 0). Tiếp theo, (safety 0) rất hiếm khi đạt được mức tăng đáng chú ý. Tôi sẽ khai báo (speed 3)(safety 1)(debug 1) trong các chức năng nóng, có thể sẽ là (debug 0) nếu điều này mang lại mức tăng đáng chú ý.

Nếu không, không thực sự xem xét một số mã thực tế, thật khó để đưa ra đề xuất. Nhìn từ thời gian() nó có vẻ như áp lực GC là kinda cao. Hãy chắc chắn rằng bạn sử dụng số học được mã hóa mở trong các chức năng nóng và không cần hộp phao hoặc ints. Sử dụng (disassemble 'my-expensive-function) để xem xét kỹ mã mà trình biên dịch tạo ra. SBCL sẽ cung cấp rất nhiều đầu ra hữu ích khi biên dịch với ưu tiên cao về tốc độ và nó có thể đáng giá để cố gắng loại bỏ một số cảnh báo này.

Điều quan trọng là bạn sử dụng cấu trúc dữ liệu nhanh để biểu diễn các hạt, sử dụng mảng có thể truy cập tức thì và macrology nếu cần.

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> 

Lưu ý rằng cả thử nghiệm # 'in và #' đều được liệt kê là 'được biên dịch'. Điều này có nghĩa là hiệu suất duy nhất khác nhau giữa tải một tập tin .lisp, và tải một tập tin biên dịch, là thời gian biên dịch. Mà tôi giả định không phải là nút cổ chai trong kịch bản của bạn. Nó thường không, trừ khi bạn đang sử dụng một loạt các macro, và thực hiện một chuyển đổi mã là mục đích chính của chương trình của bạn.

Đây là một trong những lý do chính khiến tôi không bao giờ xử lý các tệp lisp được biên dịch. Tôi chỉ cần tải tất cả các thư viện/gói được chia sẻ mà tôi cần trong tệp lõi của mình và sau đó tải một vài hàm/tệp cụ thể .lisp trên đó khi tôi đang làm việc trên một dự án cụ thể. Và, ít nhất là cho SBCL và CCL cho tôi, mọi thứ được liệt kê là 'biên dịch'.

+0

Đó thực sự là trường hợp. Tệp .dx64fsl của tôi dẫn đến một chút thời gian hơn phiên bản .lisp. Sự khác biệt đó là thời gian biên dịch. Bạn có bất kỳ ý tưởng nào về việc làm cho mã của tôi nhanh hơn không? Tôi sẽ đánh giá cao nếu bạn có thể chia sẻ một số lời khuyên. – YBE

+0

Có bất kỳ chức năng nào được gọi lặp đi lặp lại, có nhiều lần nhập liệu giống nhau không? Nếu có, bạn có thể ghi nhớ các chức năng đó. Tôi đã sử dụng defun-memo của Norvig (tự động ghi nhớ) trước đây. –

+0

'pf-step' được gọi trong vòng lặp tại mỗi lần lặp. Nó sử dụng kết quả từ lần lặp cuối cùng để tự cập nhật. Tuy nhiên, nó gọi các hàm khác nhau như 'sample',' tuyến tính-gaussian-mean' chỉ là lấy mẫu ngẫu nhiên từ phân phối. Họ xem xét các giá trị của cha mẹ của một nút cụ thể và đưa ra những giá trị mà chúng tạo ra một mẫu. – YBE

2

Nếu tất cả các mã có trong "myfile.lisp" là các phần mà bạn tính toán, không, biên dịch tập tin đó sẽ không cải thiện đáng kể thời gian chạy của bạn. Sự khác biệt giữa hai trường hợp có lẽ sẽ là "chúng tôi biên dịch một vài vòng", gọi các hàm được biên dịch hoặc diễn giải trong cả hai trường hợp.

Để cải thiện việc biên dịch, bạn cũng cần phải biên dịch mã được gọi. Bạn cũng có thể cần phải nhập chú thích mã của bạn, để cho phép trình biên dịch của bạn tối ưu hóa tốt hơn. SBCL có chẩn đoán trình biên dịch khá tốt cho các chú thích bị bỏ sót (đến mức mọi người phàn nàn nó quá dài dòng trong khi biên dịch). Theo như thời gian tải, có thể thực sự là trường hợp tải một tệp đã biên dịch mất nhiều thời gian hơn (có một loạt các liên kết động cơ bản đang diễn ra, nếu bạn không thay đổi mã của mình thường xuyên, nhưng không phải lúc nào cũng vậy. thay đổi dữ liệu bạn xử lý, nó có thể là một lợi thế để chuẩn bị một tệp lõi mới với mã lọc hạt của bạn đã có trong lõi).

Các vấn đề liên quan