Fungsi pengaturan waktu dalam R [ditutup]

36
  1. Saya ingin mengukur waktu yang diperlukan untuk mengulangi menjalankan suatu fungsi. Apakah replicate()dan menggunakan for-loop setara? Sebagai contoh:

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

    Yang merupakan metode yang disukai.

  2. Dalam output system.time(), apakah sys+userwaktu CPU sebenarnya untuk menjalankan program? Apakah elapsedukuran kinerja waktu program yang baik?

Tim
sumber
3
Sebagai catatan, karena saya jelas sudah sangat terlambat untuk mengubah jalannya pertanyaan ini: ini adalah jenis masalah yang menurut saya paling cocok untuk StackOverflow.
Matt Parker
2
@ Matt Saya setuju bahwa pertanyaan tentang bagaimana satu kali program cocok untuk SO. Saya juga setuju bahwa interpretasi literal dari pertanyaan ini (seperti yang diambil oleh beberapa jawaban) akan menempatkannya di luar topik di CV. Tampaknya ada beberapa kepentingan statistik dalam merancang percobaan waktu dan menganalisis hasil percobaan semacam itu.
whuber

Jawaban:

19

Untuk penentuan waktu program yang efektif, terutama ketika Anda tertarik untuk membandingkan solusi alternatif, Anda perlu kontrol! Cara yang baik adalah dengan menempatkan prosedur yang Anda timing ke dalam suatu fungsi. Panggil fungsi dalam loop waktu. Tulis prosedur rintisan, pada dasarnya dengan menghapus semua kode dari fungsi Anda dan baru saja kembali darinya (tetapi tinggalkan semua argumen). Masukkan rintisan ke loop waktu Anda dan ulang waktu. Ini mengukur semua overhead yang terkait dengan waktu. Kurangi waktu rintisan dari waktu prosedur untuk mendapatkan jaring: ini harus menjadi ukuran akurat dari waktu aktual yang dibutuhkan.

Karena sebagian besar sistem saat ini dapat terputus secara permanen, penting untuk melakukan beberapa pengaturan waktu untuk memeriksa variabilitas. Alih-alih melakukan satu jangka panjang detik, lakukan berjalan masing-masing sekitar detik. Ini membantu untuk melakukan ini dalam satu lingkaran ganda sekaligus. Tidak hanya itu lebih mudah untuk ditangani, itu memperkenalkan sedikit korelasi negatif di setiap seri waktu, yang sebenarnya meningkatkan perkiraan.m N / mNmN/m

Dengan menggunakan prinsip-prinsip dasar desain eksperimental ini, Anda pada dasarnya mengontrol setiap perbedaan karena cara Anda menggunakan kode (misalnya, perbedaan antara loop untuk dan replikasi ()). Itu membuat masalah Anda hilang.

whuber
sumber
25

Mengenai dua poin Anda:

  1. Ini gaya. Saya suka replicate()karena fungsional.
  2. Saya cenderung fokus elapsed, yaitu angka ketiga.

Yang sering saya lakukan adalah

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

untuk mendapatkan rata-rata dipangkas dari 90% dari N pengulangan menelepon f().

(Diedit, dengan terima kasih kepada Hadley karena telah menangkap thinko.)

Dirk Eddelbuettel
sumber
2
Bukankah maksud Anda mean(replicate(N, system.time(f(...))[3]), trim = 0.05)?
Hadley
2
Jika panggilan f () panjang, maka tidak masalah. Namun, jika panggilan f () pendek maka setiap panggilan waktu overhead kemungkinan akan meningkatkan pengukuran kesalahan. Dengan satu panggilan untuk system.time () atas banyak pengulangan f () seseorang dapat membagi kesalahan panggilan sampai beberapa nilai sangat kecil (dan kembali lebih cepat).
John
@ John: Terima kasih, tetapi saya tidak mengerti apa yang Anda katakan. Saya masih bertanya-tanya mana yang lebih baik, mengulangi f () di dalam atau di luar system.time ()?
Tim
Setiap panggilan ke perintah system.time () memiliki beberapa waktu variabel yang diperlukan untuk memanggil yang menyebabkan sejumlah kesalahan pengukuran. Ini jumlah yang kecil. Tetapi bagaimana jika f () adalah panggilan yang sangat singkat? Maka kesalahan ini dapat diatasi dengan waktu yang dibutuhkan untuk memanggil f (). Jadi, ketika Anda memanggil f () 1e5 kali di dalam satu system.time () panggilan kesalahan akan dibagi menjadi potongan 1e5. Ketika Anda memanggil system.time () untuk setiap f () dampaknya bisa bermakna jika waktu untuk f () kecil. Tentu saja, jika yang Anda butuhkan adalah waktu yang relatif, itu tidak masalah.
Yohanes
Oh, dan bagian kedua adalah lebih cepat memanggil system.call () sekali.
Yohanes
10

Anda juga dapat mengatur waktu dengan timesteps yang dikembalikan oleh Sys.time; ini tentu saja mengukur walltime, jadi waktu perhitungan real time. Kode contoh:

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

sumber
3

Mengenai metrik waktu yang digunakan, saya tidak bisa menambahkan ke responden lain.

Mengenai fungsi yang digunakan, saya suka menggunakan benchmark dari paket rbenchmark .

Tal Galili
sumber
1

Mereka melakukan hal yang berbeda. Waktu apa yang ingin Anda lakukan. replicate () mengembalikan vektor hasil dari setiap eksekusi fungsi. Untuk loop tidak. Karena itu, itu bukan pernyataan yang setara.

Selain itu, tentukan sejumlah cara agar Anda ingin sesuatu dilakukan. Maka Anda dapat menemukan metode yang paling efisien.

John
sumber
mod-tip: posting bagian kedua sebagai komentar untuk jawaban Dirk.