Các chức năng thời gian trong R [đã đóng]


36
  1. Tôi muốn đo thời gian cần thiết để lặp lại hoạt động của một chức năng. Được replicate()và sử dụng vòng lặp for tương đương? Ví dụ:

    system.time(replicate(1000, f()));
    system.time(for(i in 1:1000){f()});

    Đó là phương pháp ưa thích.

  2. Trong đầu ra của system.time(), sys+userthời gian CPU thực tế để chạy chương trình? Là elapsedmột thước đo tốt về hiệu suất thời gian của chương trình?


3
Chỉ để ghi lại, vì rõ ràng tôi đã quá muộn để thay đổi tiến trình của câu hỏi này: đây là loại vấn đề mà tôi nghĩ là phù hợp nhất với StackOverflow.
Matt Parker

2
@Matt Tôi đồng ý rằng các câu hỏi về cách một lần chương trình phù hợp với SO. Tôi cũng đồng ý rằng một cách giải thích theo nghĩa đen của câu hỏi này (như được đưa ra bởi một số câu trả lời) sẽ đặt nó ngoài chủ đề ở đây trên CV. Dường như có một số lợi ích thống kê trong việc thiết kế một thử nghiệm thời gian và trong việc phân tích kết quả của một thử nghiệm như vậy mặc dù.
whuber

Câu trả lời:


19

Để tính thời gian hiệu quả của các chương trình, đặc biệt là khi bạn quan tâm đến việc so sánh các giải pháp thay thế, bạn cần có một sự kiểm soát! Một cách tốt là đặt thủ tục bạn định thời vào một hàm. Gọi hàm trong một vòng lặp thời gian. Viết một thủ tục sơ khai, về cơ bản bằng cách tước bỏ tất cả mã từ hàm của bạn và chỉ trả về từ đó (nhưng để lại tất cả các đối số trong). Đặt sơ khai vào vòng lặp thời gian của bạn và thời gian lại. Điều này đo tất cả các chi phí liên quan đến thời gian. Trừ thời gian còn sơ khai từ thời gian thủ tục để lấy mạng: đây phải là thước đo chính xác về thời gian thực tế cần thiết.

Bởi vì hầu hết các hệ thống hiện nay có thể bị gián đoạn một cách đáng tiếc, điều quan trọng là phải thực hiện một số lần chạy thời gian để kiểm tra tính biến đổi. Thay vì thực hiện một lần chạy dài giây, hãy thực hiện lần chạy khoảng giây. Nó giúp để làm điều này trong một vòng lặp tất cả trong một lần. Không chỉ dễ xử lý hơn, nó còn giới thiệu một chút tương quan tiêu cực trong mỗi chuỗi thời gian, điều này thực sự cải thiện các ước tính.NmN/m

Bằng cách sử dụng các nguyên tắc cơ bản này của thiết kế thử nghiệm, về cơ bản, bạn sẽ kiểm soát mọi khác biệt do cách bạn triển khai mã (ví dụ: sự khác biệt giữa vòng lặp for và sao chép ()). Điều đó làm cho vấn đề của bạn biến mất.


25

Về hai điểm của bạn:

  1. Đó là phong cách. Tôi thích replicate()vì nó là chức năng.
  2. Tôi có xu hướng tập trung vào elapsed, tức là số thứ ba.

Những gì tôi thường làm là

N <- someNumber
mean(replicate( N, system.time( f(...) )[3], trimmed=0.05) )

để có được mức trung bình 90% của N lần lặp lại của cuộc gọi f().

(Đã chỉnh sửa, cảm ơn Hadley vì đã bắt được một thinko.)


2
Ý bạn là mean(replicate(N, system.time(f(...))[3]), trim = 0.05)sao?
hadley

2
Nếu cuộc gọi f () dài thì không sao. Tuy nhiên, nếu cuộc gọi f () ngắn thì mọi chi phí cuộc gọi thời gian sẽ có khả năng tăng lỗi đo. Với một lệnh gọi system.time () qua nhiều lần lặp lại của f (), người ta sẽ phân chia lỗi cho cuộc gọi cho đến khi nó có giá trị vô hạn (và nó trả về nhanh hơn).
John

@ John: Cảm ơn nhưng tôi không hiểu lắm những gì bạn nói. Tôi vẫn đang tự hỏi cái nào tốt hơn, lặp lại f () bên trong hay bên ngoài system.time ()?
Tim

Mỗi lệnh gọi đến lệnh system.time () có một số thời gian khác nhau để gọi gây ra một số lỗi đo lường. Đây là một lượng nhỏ. Nhưng nếu f () là một cuộc gọi rất ngắn thì sao? Sau đó, lỗi này có thể được giải thích với thời gian thực hiện để gọi f (). Vì vậy, khi bạn gọi f () 1e5 lần trong một lệnh system.time (), lỗi sẽ được chia thành các khối 1e5. Khi bạn gọi system.time () cho mọi f (), tác động của nó có thể có ý nghĩa nếu thời gian cho f () nhỏ. Tất nhiên, nếu tất cả những gì bạn cần là thời gian tương đối thì không vấn đề gì.
Giăng

Ồ, và phần thứ hai là sẽ nhanh hơn nếu chỉ gọi system.call () một lần.
Giăng

10

Bạn cũng có thể thời gian với dấu thời gian được trả về bởi Sys.time; điều này tất nhiên đo thời gian treo tường, vì vậy thời gian tính toán thời gian thực. Mã ví dụ:

Sys.time()->start;
replicate(N,doMeasuredComputation());
print(Sys.time()-start);

3

Về việc sử dụng số liệu thời gian nào, tôi không thể thêm vào những người phản hồi khác.

Về chức năng sử dụng, tôi thích sử dụng? Điểm chuẩn từ gói rbenchmark .


1

Họ làm những việc khác nhau. Thời gian những gì bạn muốn làm. Nhân rộng () trả về một vectơ kết quả của mỗi lần thực hiện hàm. Vòng lặp for không. Do đó, chúng không phải là báo cáo tương đương.

Ngoài ra, thời gian một số cách bạn muốn một cái gì đó được thực hiện. Sau đó, bạn có thể tìm thấy phương pháp hiệu quả nhất.


mod-tip: đăng phần thứ hai dưới dạng bình luận cho câu trả lời của Dirk.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.