Saya memiliki program C yang bertujuan untuk dijalankan secara paralel pada beberapa prosesor. Saya harus dapat mencatat waktu eksekusi (yang bisa di mana saja dari 1 detik hingga beberapa menit). Saya telah mencari jawaban, tetapi semuanya sepertinya menyarankan untuk menggunakan clock()
fungsi ini, yang kemudian melibatkan penghitungan jumlah jam yang diambil oleh program dibagi dengan Clocks_per_second
nilainya.
Saya tidak yakin bagaimana Clocks_per_second
nilai dihitung?
Di Jawa, saya hanya mengambil waktu saat ini dalam milidetik sebelum dan sesudah eksekusi.
Apakah ada hal serupa di C? Saya sudah melihat-lihat, tapi sepertinya saya tidak bisa menemukan cara untuk mendapatkan sesuatu yang lebih baik daripada resolusi kedua.
Saya juga tahu profiler akan menjadi pilihan, tetapi saya ingin mengimplementasikan timer sendiri.
Terima kasih
sumber
Jawaban:
CLOCKS_PER_SEC
adalah konstanta yang dideklarasikan dalam<time.h>
. Untuk mendapatkan waktu CPU yang digunakan oleh tugas dalam aplikasi C, gunakan:Perhatikan bahwa ini mengembalikan waktu sebagai tipe titik mengambang. Ini bisa lebih tepat daripada satu detik (misalnya Anda mengukur 4,52 detik). Ketepatan tergantung pada arsitektur; pada sistem modern Anda dengan mudah mendapatkan 10 ms atau lebih rendah, tetapi pada mesin Windows yang lebih lama (dari era Win98) lebih dekat ke 60 ms.
clock()
adalah standar C; ini bekerja "di mana-mana". Ada fungsi spesifik sistem, sepertigetrusage()
pada sistem mirip Unix.Java
System.currentTimeMillis()
tidak mengukur hal yang sama. Ini adalah "jam dinding": ini dapat membantu Anda mengukur berapa banyak waktu yang diperlukan untuk menjalankan program, tetapi tidak memberi tahu Anda berapa banyak waktu CPU yang digunakan. Pada sistem multitasking (yaitu semuanya), ini bisa sangat berbeda.sumber
clock()
mengembalikan waktu dalam skala internal yang disebut "jam", danCLOCKS_PER_SEC
merupakan jumlah jam per detik, jadi bagilah denganCLOCKS_PER_SEC
menghasilkan waktu dalam detik. Dalam kode di atas, nilainya adalahdouble
jadi Anda dapat mengaturnya sesuka hati.CLOCKS_PER_SEC
adalahlong int
dengan nilai1000000
, memberikan waktu dalam mikrodetik saat tidak dibagi; bukan siklus jam CPU. Oleh karena itu, tidak perlu memperhitungkan frekuensi dinamis karena jam di sini dalam mikrodetik (mungkin siklus jam untuk CPU 1 MHz?) Saya membuat program C pendek yang mencetak nilai dan itu adalah 1000000 pada laptop i7-2640M saya, dengan frekuensi dinamis yang memungkinkan 800 MHz hingga 2,8 GHz, bahkan menggunakan Turbo Boost setinggi 3,5 GHz.Jika Anda menggunakan shell Unix untuk menjalankan, Anda dapat menggunakan perintah waktu.
perbuatan
dengan asumsi a.out sebagai executable akan memberi Anda waktu yang dibutuhkan untuk menjalankan ini
sumber
perf stat ./a.out
untuk mendapatkan penghitung kinerja HW untuk kesalahan cache dan mispredict cabang, dan IPC.Dalam vanila C sederhana:
sumber
Anda secara fungsional menginginkan ini:
Perhatikan bahwa ini mengukur dalam mikrodetik, bukan hanya dalam hitungan detik.
sumber
gettimeofday
sudah usang dan tidak disarankan untuk kode baru. Halaman manual POSIX-nya merekomendasikan clock_gettime sebagai gantinya, yang memungkinkan Anda memintaCLOCK_MONOTONIC
hal itu tidak terpengaruh oleh perubahan pada jam sistem, dan karenanya lebih baik sebagai interval waktu. (Lihat jawaban Johnll ). Pada sistem Linux modern, misalnya, gettimeofday pada dasarnya adalah pembungkus untuk clock_gettime yang mengubah nanodetik menjadi mikrodetik.Sebagian besar program sederhana memiliki waktu komputasi dalam mili detik. Jadi, saya kira, Anda akan menemukan ini berguna.
Jika Anda ingin menghitung runtime seluruh program dan Anda berada di sistem Unix, jalankan program Anda menggunakan perintah waktu seperti ini
time ./a.out
sumber
Banyak jawaban telah menyarankan
clock()
dan kemudianCLOCKS_PER_SEC
daritime.h
. Ini mungkin ide yang buruk, karena ini yang dikatakan/bits/time.h
file saya :Jadi
CLOCKS_PER_SEC
mungkin didefinisikan sebagai 1000000, tergantung pada opsi apa yang Anda gunakan untuk mengkompilasi, dan dengan demikian itu tidak tampak seperti solusi yang baik.sumber
CLOCK_PER_SEC==1000000
, tetapi pada saat yang sama, mereka semua menggunakan presisi 1-μs untuk implementasi clock mereka (); omong-omong, ini memiliki properti yang bagus untuk mengurangi masalah berbagi. Jika Anda ingin mengukur peristiwa yang berpotensi sangat cepat, katakan di bawah 1 ms, maka Anda harus terlebih dahulu khawatir tentang keakuratan (atau resolusi) dari fungsi clock (), yang tentu lebih kasar dari 1μs di Posix, tetapi juga sering lebih kasar; solusi yang biasa adalah dengan menjalankan tes berkali-kali; pertanyaan yang diajukan sepertinya tidak membutuhkannya.clock()
, jika Anda membagi nilai itu denganCLOCK_PER_SEC
Anda dijamin mendapatkan waktu dalam hitungan detik cpu ambil. Tanggung jawab mengukur kecepatan clock aktual adalah tanggung jawabclock()
fungsi, bukan tanggung jawab Anda.Jawaban Thomas Pornin sebagai makro:
Gunakan seperti ini:
Keluaran:
sumber
Anda harus memperhitungkan bahwa mengukur waktu yang diperlukan untuk menjalankan suatu program sangat tergantung pada beban yang dimiliki mesin pada saat itu.
Mengetahui bahwa, cara memperoleh waktu saat ini di C dapat dicapai dengan cara yang berbeda, yang lebih mudah adalah:
Semoga ini bisa membantu.
Salam!
sumber
(Semua jawaban di sini kurang, jika sysadmin Anda mengubah waktu sistem, atau zona waktu Anda memiliki waktu musim dingin dan musim dingin yang berbeda. Karena itu ...)
Pada penggunaan linux:
clock_gettime(CLOCK_MONOTONIC_RAW, &time_variable);
Tidak terpengaruh jika admin sistem mengubah waktu, atau Anda tinggal di negara dengan waktu musim dingin berbeda dari waktu musim panas, dll.man clock_gettime
menyatakan:sumber
(end.tv_nsec - begin.tv_nsec) / 1000000000.0
menghasilkan0
selalu?double
pemicu literal int ataulong
untukdouble
konversi sebelum divisi. Tentu saja Anda bisa tetap berpegang pada bilangan bulat dan mencetaktv_sec
bagian dan kemudian bagian pecahan dengan nol seperti%ld.%09ld
, tetapi mengkonversi menjadi dua kali lebih mudah dan presisi 53 bit biasanya banyak untuk waktu benchmark.timespec_subtract
seperti yangtimeval_subtract
disarankan dalam manual glibc : gnu.org/software/libc/manual/html_node/Elapsed-Time.html )ANSI C hanya menentukan fungsi waktu presisi kedua. Namun, jika Anda menjalankan dalam lingkungan POSIX Anda dapat menggunakan gettimeofday () yang memberikan resolusi mikrodetik waktu yang berlalu sejak UNIX Epoch.
Sebagai catatan, saya tidak akan merekomendasikan menggunakan clock () karena ini diimplementasikan dengan buruk pada banyak (jika tidak semua?) Sistem dan tidak akurat, selain itu hanya merujuk pada berapa lama program Anda menghabiskan pada CPU dan bukan total umur program, yang menurut pertanyaan Anda adalah apa yang saya asumsikan ingin Anda ukur.
sumber
Setiap solusi tidak berfungsi di sistem saya.
Saya bisa menggunakannya
sumber
time_t
nilai sebagai nilai ganda. Karenatime_t
nilai hanya akurat hingga sedetik, nilai itu terbatas dalam mencetak waktu yang dibutuhkan oleh program yang berjalan singkat, meskipun mungkin berguna untuk program yang berjalan untuk jangka waktu lama.clock_t
sdifftime
sepertinya bekerja untuk saya hingga seperseratus detik. Ini ada di linux x86. Saya juga tidak bisa mendapatkan penguranganstop
danstart
untuk bekerja.difftime()
clock() / CLOCKS_PER_SEC
, seperti yang diharapkan detik.sumber
Saya telah menemukan bahwa jam biasa (), semua orang merekomendasikan di sini, untuk beberapa alasan menyimpang dari menjalankan untuk menjalankan, bahkan untuk kode statis tanpa efek samping, seperti menggambar ke layar atau membaca file. Bisa jadi karena CPU mengubah mode konsumsi daya, OS memberikan prioritas yang berbeda, dll ...
Jadi satu-satunya cara untuk secara andal mendapatkan hasil yang sama setiap kali dengan clock () adalah dengan menjalankan kode terukur dalam satu loop beberapa kali (selama beberapa menit), mengambil tindakan pencegahan untuk mencegah kompiler mengoptimalkannya: kompiler modern dapat melakukan precode kode tanpa efek samping berjalan dalam satu lingkaran, dan memindahkannya keluar dari loop., seperti menggunakan input acak untuk setiap iterasi.
Setelah cukup sampel dikumpulkan ke dalam array, satu macam array itu, dan mengambil elemen tengah, yang disebut median. Median lebih baik daripada rata-rata, karena itu membuang penyimpangan ekstrim, seperti mengatakan antivirus mengambil semua CPU atau OS melakukan beberapa pembaruan.
Berikut ini adalah utilitas sederhana untuk mengukur kinerja eksekusi kode C / C ++, rata-rata nilai dekat median: https://github.com/saniv/gauge
Saya sendiri masih mencari cara yang lebih kuat dan lebih cepat untuk mengukur kode. Seseorang mungkin dapat mencoba menjalankan kode dalam kondisi terkendali pada bare metal tanpa OS apa pun, tetapi itu akan memberikan hasil yang tidak realistis, karena pada kenyataannya OS memang terlibat.
x86 memiliki penghitung kinerja perangkat keras ini, yang termasuk jumlah instruksi aktual yang dijalankan, tetapi mereka sulit diakses tanpa bantuan OS, sulit ditafsirkan dan memiliki masalah sendiri ( http://archive.gamedev.net/archive/reference/articles /article213.html ). Tetap mereka bisa membantu menyelidiki sifat leher botol (akses data atau perhitungan aktual pada data itu).
sumber
performance
) atau puluhan milidetik. en.wikipedia.org/wiki/Dynamic_frequency_scaling . Dan ya, kinerja median biasanya merupakan pilihan yang baik; kelas atas biasanya memiliki beberapa paku dari gangguan.main
yang mengambil argumen dan mengembalikan hasil, dan jangan gunakan optimasi waktu tautan. Maka kompiler tidak bisa memasukkannya ke pemanggil. Hanya berfungsi jika fungsinya sudah termasuk semacam loop, jika tidak panggilan / ret overhead terlalu tinggi.Beberapa mungkin menemukan jenis input yang berbeda berguna: Saya diberikan metode ini untuk mengukur waktu sebagai bagian dari program universitas tentang pemrograman GPGPU dengan NVidia CUDA ( deskripsi kursus ). Ini menggabungkan metode yang terlihat di posting sebelumnya, dan saya hanya mempostingnya karena persyaratan memberikan kredibilitas:
Saya kira Anda bisa mengalikan dengan mis
1.0 / 1000.0
untuk mendapatkan unit pengukuran yang sesuai dengan kebutuhan Anda.sumber
clock_gettime
sebagai gantinya merekomendasikan , yang memungkinkan Anda memintaCLOCK_MONOTONIC
yang tidak terpengaruh oleh perubahan jam sistem, dan karenanya lebih baik sebagai penghitung waktu jeda. Pada sistem Linux modern, misalnya,gettimeofday
pada dasarnya adalah pembungkus untukclock_gettime
yang mengkonversi nanodetik ke mikrodetik. (Lihat jawaban Johnll).timeval_subtract
.Perbandingan waktu eksekusi semacam gelembung dan jenis pilihan Saya memiliki program yang membandingkan waktu pelaksanaan jenis gelembung dan jenis pilihan. Untuk mengetahui waktu eksekusi suatu blok kode hitung waktu sebelum dan sesudah blok dengan
Kode contoh:
sumber