Saya menulis sebuah program untuk dijalankan pada ATmega 328 yang berjalan pada 16Mhz (ini adalah Arduino Duemilanove jika Anda mengenal mereka, ini adalah chip AVR).
Saya memiliki proses interupsi yang berjalan setiap 100 mikrodetik. Tidak mungkin, saya akan mengatakan, untuk mengetahui berapa banyak "kode" yang dapat Anda jalankan dalam satu loop 100 mikrodetik (saya menulis dalam C yang mungkin dikonversi ke perakitan kemudian menjadi gambar biner?).
Juga ini akan tergantung pada kompleksitas kode (satu liner raksasa mungkin berjalan lebih lambat daripada beberapa baris pendek misalnya).
Apakah pemahaman saya benar, bahwa prosesor saya dengan clock rate atau 16Mhz melakukan 16 juta siklus per detik (ini berarti 16 siklus per mikrodetik 16.000.000 / 1.000 / 1.000); Jadi, jika saya ingin melakukan lebih banyak dalam loop 100 mikrodetik, membeli model yang lebih cepat seperti versi 72Mhz akan memberi saya 72 siklus per mikrodetik (72.000.000 / 1.000 / 1.000)?
Saat ini berjalan sedikit terlalu lambat, yaitu butuh sedikit lebih lama dari 100 mikrodetik untuk melakukan loop (berapa lama tepatnya terlalu sulit untuk dikatakan, tetapi secara bertahap tertinggal) dan saya ingin melakukannya sedikit lagi, adalah ini pendekatan yang waras mendapatkan chip yang lebih cepat atau saya sudah gila?
sumber
Jawaban:
Secara umum jumlah instruksi perakitan yang dapat dieksekusi perangkat per detik akan tergantung pada campuran instruksi dan berapa banyak siklus yang dibutuhkan oleh masing-masing tipe instruksi (CPI). Secara teori Anda dapat menghitung kode Anda dengan melihat file asm yang dibongkar dan melihat fungsi yang Anda khawatirkan, menghitung semua jenis instruksi yang berbeda di dalamnya, dan mencari hitungan siklus dari lembar data untuk prosesor target Anda.
Masalah dalam menentukan jumlah efektif instruksi per detik diperparah dalam prosesor yang lebih kompleks oleh kenyataan bahwa mereka disalurkan melalui pipa dan memiliki cache dan apa yang tidak. Ini bukan kasus untuk perangkat sederhana seperti ATMega328 yang merupakan instruksi tunggal dalam prosesor penerbangan.
Sedangkan untuk hal-hal praktis, untuk perangkat sederhana seperti AVR, jawaban saya akan lebih atau kurang "ya". Menggandakan kecepatan jam Anda seharusnya setengah dari waktu pelaksanaan fungsi yang diberikan. Untuk AVR, bagaimanapun, mereka tidak akan berjalan lebih cepat dari 20MHz, jadi Anda hanya bisa "overclock" Arduino Anda dengan 4MHz lain.
Saran ini tidak berlaku untuk prosesor yang memiliki fitur lebih canggih. Menggandakan kecepatan clock pada prosesor Intel Anda tidak akan dalam praktiknya menggandakan jumlah instruksi yang dieksekusi per detik (karena ramalan salah cabang, kesalahan cache, dan sebagainya).
sumber
@ vicatcu jawabannya cukup komprehensif. Satu hal tambahan yang perlu diperhatikan adalah bahwa CPU dapat mengalami kondisi tunggu (siklus CPU terhenti) saat mengakses I / O, termasuk memori program dan data.
Misalnya, kami menggunakan DSP TI F28335; beberapa area RAM adalah keadaan 0-tunggu untuk program dan memori data, jadi ketika Anda mengeksekusi kode dalam RAM, itu berjalan pada 1 siklus per instruksi (kecuali untuk instruksi yang membutuhkan lebih dari 1 siklus). Ketika Anda mengeksekusi kode dari memori FLASH (EEPROM bawaan, lebih atau kurang), namun, itu tidak dapat berjalan pada 150MHz penuh dan beberapa kali lebih lambat.
Sehubungan dengan kode interupsi berkecepatan tinggi, Anda harus mempelajari sejumlah hal.
Pertama, menjadi sangat akrab dengan kompiler Anda. Jika kompiler melakukan pekerjaan dengan baik, seharusnya tidak lebih lambat dari perakitan kode tangan untuk kebanyakan hal. (di mana "yang jauh lebih lambat": faktor 2 akan baik-baik saja bagi saya; faktor 10 akan tidak dapat diterima) Anda perlu belajar bagaimana (dan kapan) menggunakan bendera optimisasi kompiler, dan setiap kali sesekali Anda harus melihat di keluaran kompiler untuk melihat bagaimana hasilnya.
Beberapa hal lain yang dapat Anda lakukan pada kompiler untuk mempercepat kode:
gunakan fungsi sebaris (tidak ingat apakah C mendukung ini atau jika hanya C ++ - ism), baik untuk fungsi kecil maupun untuk fungsi yang akan dieksekusi hanya sekali atau dua kali. Kelemahannya adalah fungsi inline sulit untuk di-debug, terutama jika optimisasi kompiler dihidupkan. Tetapi mereka menyelamatkan Anda urutan panggilan / kembali tidak perlu, terutama jika abstraksi "fungsi" adalah untuk tujuan desain konseptual daripada implementasi kode.
Lihatlah manual kompiler Anda untuk melihat apakah ia memiliki fungsi intrinsik - ini adalah fungsi bawaan yang bergantung pada kompiler yang memetakan langsung ke instruksi perakitan prosesor; beberapa prosesor memiliki instruksi perakitan yang melakukan hal-hal berguna seperti min / max / bit mundur dan Anda dapat menghemat waktu melakukannya.
Jika Anda melakukan perhitungan numerik, pastikan Anda tidak memanggil fungsi perpustakaan matematika secara tidak perlu. Kami memiliki satu kasus di mana kode itu seperti
y = (y+1) % 4
untuk penghitung yang memiliki periode 4, mengharapkan kompiler untuk mengimplementasikan modulo 4 sebagai bitwise-AND. Sebaliknya itu disebut perpustakaan matematika. Jadi kami diganti dengany = (y+1) & 3
untuk melakukan apa yang kami inginkan.Biasakan diri dengan halaman hack bit-twiddling . Saya jamin Anda akan menggunakan paling tidak salah satunya.
Anda juga harus menggunakan periferal timer CPU Anda untuk mengukur waktu eksekusi kode - kebanyakan dari mereka memiliki timer / penghitung yang dapat diatur untuk dijalankan pada frekuensi clock CPU. Tangkap salinan penghitung di awal dan akhir kode kritis Anda, dan Anda dapat melihat berapa lama. Jika Anda tidak bisa melakukan itu, alternatif lain adalah menurunkan pin output di awal kode Anda, dan menaikkannya di akhir, dan lihat output ini pada osiloskop untuk menentukan waktu pelaksanaannya. Ada pengorbanan untuk setiap pendekatan: penghitung waktu internal / counter lebih fleksibel (Anda dapat mengatur waktu beberapa hal) tetapi lebih sulit untuk mendapatkan informasi, sedangkan pengaturan / kliring pin output segera terlihat pada ruang lingkup dan Anda dapat menangkap statistik, tetapi sulit untuk membedakan banyak acara.
Akhirnya, ada keterampilan yang sangat penting yang datang dengan pengalaman - baik umum dan dengan kombinasi prosesor / kompiler tertentu: mengetahui kapan dan kapan tidak mengoptimalkan . Secara umum jawabannya adalah jangan optimalkan. Kutipan Donald Knuth sering diposting di StackOverflow (biasanya hanya bagian terakhir):
Tetapi Anda berada dalam situasi di mana Anda tahu harus melakukan semacam optimasi, jadi inilah saatnya untuk menggigit peluru dan mengoptimalkan (atau mendapatkan prosesor yang lebih cepat, atau keduanya). Apakah TIDAK menulis seluruh ISR Anda dalam perakitan. Itu hampir merupakan bencana yang dijamin - jika Anda melakukannya, dalam beberapa bulan atau bahkan beberapa minggu Anda akan melupakan bagian dari apa yang Anda lakukan dan mengapa, dan kode ini cenderung sangat rapuh dan sulit untuk diubah. Namun, ada kemungkinan bagian-bagian kode Anda yang merupakan kandidat yang baik untuk perakitan.
Tanda-tanda bahwa bagian-bagian kode Anda sangat cocok untuk pengkodean perakitan:
Pelajari konvensi pemanggilan fungsi kompiler Anda (mis. Di mana ia menempatkan argumen dalam register, dan register mana yang disimpan / dipulihkan) sehingga Anda dapat menulis rutinitas perakitan yang dapat dipanggil-C.
Dalam proyek saya saat ini, kami memiliki basis kode yang cukup besar dengan kode kritis yang harus dijalankan dalam interupsi 10kHz (100usec - sound familiar?) Dan tidak ada banyak fungsi yang ditulis dalam perakitan. Yang ada, adalah hal-hal seperti perhitungan CRC, antrian perangkat lunak, ADC gain / kompensasi kompensasi.
Semoga berhasil!
sumber
Hal lain yang perlu diperhatikan - mungkin ada beberapa optimasi yang dapat Anda lakukan untuk membuat kode Anda lebih efisien.
Misalnya - Saya memiliki rutinitas yang berjalan dari dalam penghentian waktu. Rutin harus selesai dalam 52μS, dan harus melalui sejumlah besar memori saat melakukannya.
Saya mengelola peningkatan kecepatan besar dengan mengunci variabel penghitung utama ke register dengan (di µC & compiler saya - berbeda untuk Anda):
Saya tidak tahu format untuk kompiler Anda - RTFM, tetapi akan ada sesuatu yang dapat Anda lakukan untuk membuat rutinitas Anda lebih cepat tanpa harus beralih ke assembly.
Karena itu, Anda mungkin dapat melakukan pekerjaan yang jauh lebih baik dalam mengoptimalkan rutin Anda daripada kompiler, jadi beralih ke perakitan mungkin memberi Anda beberapa peningkatan kecepatan besar.
sumber