Menulis algoritma DSP langsung dalam C atau assembly? [Tutup]

18

Saya sedang mengerjakan proyek DSP (penyaringan IIR) pada prosesor sinyal digital Perangkat Analog (BF706) dengan rangkaian kompiler yang menyertainya, CrossCore Studio. Ini memiliki beberapa contoh untuk hal-hal DSP sederhana seperti filter FIR dan IIR dan fungsi perpustakaan untuk itu. Manual prosesor menjelaskan set instruksi perakitan dan tidak mengomentari C.

Pertanyaan saya muncul dari aplikasi khusus ini, tapi saya pikir ada praktik terbaik yang diikuti oleh pengembang DSP. Jadi saya akan membingkainya secara umum:

Apa yang saya sadari dengan contoh-contoh yang datang dengan DSP ini, adalah bahwa jika saya ingin menggunakan sirkuit yang dirancang untuk aplikasi DSP saya perlu memprogram dalam perakitan untuk langsung menjalankan instruksi-instruksi tersebut (seperti mengalikan dan menambah, dll.) Pertanyaan saya adalah apakah Saya hanya memprogram dalam C, bukankah kompiler (yang juga berasal dari perusahaan chip DSP) mengoptimalkannya untuk DSP itu dan menggunakan kemampuannya? Atau apakah saya benar-benar perlu menulis rutinitas DSP langsung dalam perakitan?

melipatgandakan
sumber
17
Saya menghabiskan bertahun-tahun menulis rakitan untuk ADSP-21xx (dan rakitan dan C untuk Blackfin, nanti.) Anda tidak mengungkapkan apa yang Anda gunakan, jadi jawaban apa pun akan lebih berupa dugaan dan pendapat daripada yang lainnya. Tetapi prosesor DSP AD adalah barang yang sangat bagus dan sangat sulit bagi penulis C compiler untuk mengisi pipa dengan benar, sehingga untuk berbicara. Saya memiliki pengalaman dua dekade dalam bidang ini (termasuk beberapa pengalaman yang sangat sederhana menulis kompiler C) dan sampai saat saya berhenti menulis kode (beberapa tahun yang lalu) kompiler C tidak dapat mendekati pengodean tangan. Tetapi apa yang Anda lakukan tergantung pada tujuan Anda.
Jonk
1
@jonk harap Anda akan menulis jawaban untuk yang ini - Saya hanya pernah melakukan satu proyek DSP Blackfin hardcore, tapi saya punya kenangan indah tentang beberapa peretasan kinerja yang diperlukan :)
pericynthion
6
@pericynthion Tidak, saya tidak bisa membayangkan menulis jawaban untuk itu kecuali OP berbicara BANYAK lebih banyak tentang DSP tertentu dan tujuan proyek. Kalau tidak, itu akan menjadi opini yang samar-samar dan tidak terarah yang bisa sangat benar atau sangat salah tergantung pada apa yang ditulis OP tentang hal itu. Jadi saya tunggu saja.
Jonk
1
Jika Anda ingin menjalankan tercepat, Anda mengoptimalkannya dalam perakitan. Itu adalah tradeoff waktu \ uang. Jika Anda tahu cara menulis C yang baik, Anda bisa mendapatkan sebagian besar jalan di sana.
Voltage Spike
2
Saya tidak yakin tentang DSP tetapi untuk sebagian besar mikroprosesor Anda dapat menggunakan intrinsik yang setengah jalan antara menulis assembler dan kode C.
Maciej Piechotka

Jawaban:

20

Itu selalu lebih baik untuk memiliki algoritma Anda diimplementasikan dalam bahasa tingkat yang lebih tinggi (yang C dibandingkan dengan perakitan), bahkan jika Anda berencana untuk mengimplementasikan semuanya dalam perakitan pada akhirnya.

  • kemungkinan besar, Anda bahkan tidak perlu perakitan . Jika kode yang dihasilkan oleh kompiler Anda memenuhi tujuan desain Anda, pekerjaan Anda selesai.

  • jika tidak, Anda tidak akan memulai pengkodean perakitan dari awal . Biarkan kompiler membuat kode awal untuk Anda, dan gunakan itu sebagai basis untuk versi perakitan yang dioptimalkan.

  • nanti, ketika Anda perlu menguji kode perakitan yang dioptimalkan , Anda akan senang memiliki versi C. Alih-alih menghitung secara manual output yang benar untuk data input pengujian Anda, Anda bisa memasukkan data input itu ke implementasi C Anda yang tidak dioptimalkan, kemudian memeriksa apakah perakitan menghasilkan output yang persis sama setelah optimasi yang Anda buat.

Jika, setelah beberapa tahun pengembang baru perlu melakukan modifikasi pada algoritme Anda dan yang mereka miliki hanyalah kode perakitan yang sangat dioptimalkan, ada kemungkinan besar mereka harus mulai dari awal.

Dmitry Grigoryev
sumber
23

Jika penulis kompiler berupaya mengoptimalkannya untuk target itu, setidaknya akan menggunakan beberapa instruksi / arsitektur DSP khusus. Tapi untuk performa terbaik, itu tidak akan sebagus perakitan yang disetel dengan tangan. Mungkin cukup banyak, tergantung - pada aplikasi Anda.

Alternatif lain termasuk:

  1. Tuliskan mayoritas program Anda dalam C, dan hanya bagian numerik yang paling penting dalam perakitan.
  2. Tulis program dalam C dan gunakan perpustakaan yang disediakan oleh pabrikan atau pihak ketiga - jika Anda melakukan tugas-tugas DSP umum seperti FFT, filter FIR / IIR dll. Seseorang mungkin telah menulis kode mesin yang disetel dengan tangan untuk melakukannya, jadi Anda dapat menggunakannya (Anda mungkin harus membayar untuk itu) dan menautkannya ke aplikasi Anda.
pericynthion
sumber
Biasanya, vendor DSP akan menyediakan kode sumber untuk fungsi-fungsi umum. Jika kode mereka "cukup baik", Anda bisa memasukkannya. Jika tidak benar, Anda harus mengubahnya. Saya harus melakukan layer FFT beberapa tahun yang lalu, untuk mendapatkan FFT nyata hanya-frekuensi. Ada trik yang memungkinkan Anda melakukan FFT nyata 2N-point sebagai FFT kompleks N-point, tetapi kemudian Anda harus melakukan umpan final atas output kompleks untuk memulihkan data frekuensi nyata. Perangkat Analog tidak memiliki case khusus dalam kode contohnya.
John R. Strohm
21

Optimalisasi prematur adalah akar dari semua kejahatan. - Donald Knuth

Ketika Anda menemukan bahwa Anda tidak mendapatkan kinerja yang cukup dari kode Anda, buat profil program Anda terlebih dahulu, cari kemacetan, analisis persyaratan kinerja Anda, dan baru kemudian mulai lakukan optimasi. Menulis kode perakitan adalah pilihan terakhir.

Pertanyaan saya adalah jika saya hanya memprogram dalam C, bukankah kompiler (yang juga berasal dari perusahaan chip DSP) mengoptimalkannya untuk DSP itu dan menggunakan kemampuannya?

Ya, kompiler C dapat melakukan optimasi dengan cukup baik. Tetapi ini tergantung pada kualitas kompiler. Seringkali, manusia dapat menulis kode perakitan lebih cepat daripada kode C yang dikompilasi. Dengan mengorbankan rasa sakit dan penderitaan manusia, yaitu.

Atau apakah saya benar-benar perlu menulis rutinitas DSP langsung dalam perakitan?

Pertama tulis di C, lalu profil, lalu putuskan apakah Anda perlu menulis dalam pertemuan. Semoga Anda tidak perlu perakitan.

Nick Alexeev
sumber
20
Dalam pemrograman umum ini tentu saja merupakan saran yang baik, tetapi DSP sedikit berbeda - jika OP benar-benar ingin menggunakan DSP secara efisien, mungkin perlu ada beberapa kode tulisan tangan di suatu tempat di sepanjang garis tersebut. Dan sebenarnya dengan proyek DSP kadang-kadang Anda bahkan ingin memulai dengan menulis kernel numerik inti, untuk memvalidasi bahwa prosesor akan sesuai untuk tugas yang sedang dihadapi.
pericynthion
11
Pernyataan penutup Anda adalah saran umum yang bagus. Tapi itu agak pucat ketika mempertimbangkan detail spesifik dari ALU DSP AD. Saya kira Anda tidak pernah memeriksanya.
Jonk
18

DSP Anda akan diiklankan dengan MAC berkelanjutan maksimum, dengan asumsi semua pipa terisi. Itu jelas batas atas apa yang bisa dicapai. Anda tahu berapa banyak MAC yang akan diambil oleh filter Anda dan pemrosesan lainnya, dari analisis Anda. Usahakan memiliki yang pertama setidaknya dua kali yang kedua, karena Anda tidak akan dapat menjaga inti DSP berjalan maksimal. Sama seperti Anda tidak akan mencoba untuk mengisi FPGA di atas 70% sumber daya (PAR menjadi sangat lambat di atas itu), pengembangan bisa menjadi sangat lambat mencoba untuk memeras beberapa MAC teoritis terakhir dari DSP.

Anda akan mengkode seluruh aplikasi Anda dalam C. Tidak praktis untuk menulis semua hal tambahan yang diperlukan dalam assembler, injeksi dan visibilitas tes, housekeeping dll. Tulis versi C dari filter uji. Tulis versi assembler dari filter yang sama, untuk memverifikasi Anda sebenarnya bisa menulis assembler untuk beast ini.

Sekarang lakukan beberapa pengaturan waktu. Gunakan RTOS yang disetujui oleh pemasok. Bandingkan waktu berjalan modul assembler tes Anda dengan versi C. Jika mereka dalam beberapa persen, lanjutkan. Jika triple, baca dokumentasi, kuis vendor, dan cari tahu mengapa kompiler tidak menyetelnya. Anda mungkin perlu belajar menulis rasa C sebanyak mengatur flag compiler yang benar, itu akan lebih cepat untuk mengetahui bagaimana menggerakkan compiler dengan benar daripada menulis ulang semua yang ada di assembler.

Anda telah melakukan semua ini sebelum berkomitmen ke DSP, ke rantai alat.

Setelah Anda memiliki toolchain yang dapat Anda gunakan, sebuah kompiler yang dapat Anda setel agar mendekati maksimum, sebuah DSP dengan beberapa ruang kepala waktu tersisa, maka Anda dapat cukup yakin bahwa sangat sedikit bagian dari rangkaian kode Anda yang perlu dimasukkan ke dalam assembler untuk menyelesaikan pekerjaan.

Neil_UK
sumber
7

Meskipun saya sudah menjawab pertanyaan ini, saya akan menambahkan jawaban lain untuk mengilustrasikan sudut pandang yang berbeda:

Tulis dalam C, baca dalam kumpulan!

Jadi, alih-alih menulis dalam rakitan, Anda akan menulis logika dalam C, dengan hati-hati memastikan bahwa output assembler dari kode C optimal. Anda sering dapat melakukan trik tertentu pada kode C untuk mempengaruhi output assembler. Gunakan fungsi inline statis saat itu masuk akal. Jika Anda perlu menggunakan beberapa instruksi khusus yang didukung DSP, buat abstraksi fungsi inline statis dari instruksi khusus, dan panggil instruksi khusus menggunakan abstraksi.

Meskipun saya harus mengatakan saya tidak pernah memprogram DSP, pendekatan penulisan kode C ini sambil mengamati perakitan yang telah dikompilasi telah bekerja dengan baik untuk saya pada mesin x86 dengan sangat baik. Sebetulnya saya tidak perlu menulis apa pun dalam pertemuan untuk mendapatkan kinerja terbaik. Saya bukannya akan mengoptimalkan kode rakitan memodifikasi kode C sedemikian rupa sehingga rakitan optimal.

Tentu saja, ini tergantung pada kompiler C yang baik yang tersedia. Untuk x86, kompiler semacam itu tersedia (Anda sering harus menentukan level optimisasi yang lebih tinggi daripada default). Untuk DSP, saya terus terang tidak tahu apakah kompilernya sama bagusnya.

Manfaat dari pendekatan ini adalah bahwa Anda memiliki basis kode portabel tunggal, dioptimalkan untuk menghasilkan perakitan optimal untuk DSP yang diberikan, tetapi ini juga berfungsi jika DSP diubah menjadi sesuatu yang lain. Tentu saja Anda mungkin harus sedikit menyesuaikan kode C untuk mendapatkan kinerja terbaik pada DSP baru.

ahli hukum agama
sumber
Saya punya pertanyaan tentang ini: Saya bekerja pada prosesor STM32F4 Cortex-M4 dan saya menggunakan perpustakaan CMSIS / Cube. Saya juga menggunakan flag -O3 kompiler, karena terbukti cara yang lebih efisien daripada apa pun yang bisa saya hasilkan. Masalahnya adalah bahwa majelis yang dikompilasi selalu terlalu kacau untuk analisis yang tepat. Apakah Anda selalu mengkompilasi tanpa optimasi kompiler? Atau apakah Anda berhasil memahami pertemuan itu, jika semuanya sudah berakhir?
Florent
2
@FlorentEcochard: Jika assembler compiler tidak dapat dipahami oleh seorang programmer, mungkin itu lebih baik daripada assembler yang dapat ditulis oleh programmer ini. Sebagai jawaban langsung untuk pertanyaan Anda: gunakan optimalisasi maksimum dan analisis manual assembler, bagian-bagian yang sulit bisa menjadi edukatif.
pasaba por aqui
4

Secara umum, tidak perlu menulis sumber assembler jika:

  • Anda mengoptimalkan C di bagian penting: penggunaan kata kunci "daftar" yang baik, fungsi sebaris, ...
  • bisa beberapa fungsi dari program C menggunakan blok asm

Itu berarti meninjau secara manual assembler yang dihasilkan oleh kompiler C (untuk bagian-bagian penting) dan memodifikasi sumber hingga tingkat optimisasi yang cukup.

pas por aqui
sumber
Hampir semua kompiler modern mengabaikan kata kunci "daftar", apa pun platformnya. Menggunakannya sangat tidak mungkin menghasilkan kode yang lebih baik.
Kef Schecter
@KefSchecter: tidak hanya mereka memperhitungkan petunjuk register, saat ini mereka bahkan memperbolehkan untuk memilih register yang akan digunakan: gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/…
pasaba por aqui
1
@KefSchecter: kecuali untuk kompiler yang ditulis untuk perangkat yang disematkan, di mana ini adalah kata kunci yang sangat penting jika Anda memprogram pada bare metal.
vsz
@pasabaporaqui: Saya lupa sedikit sintaks itu. Tetapi jika Anda tidak menentukan nama register - dengan kata lain, jika Anda menggunakannya dengan cara standar ISO - saya yakin GCC akan mengabaikannya.
Kef Schecter
3

Saya akan mengatakan di sini bahwa jika Anda melakukan filter FIR / IIR, jauh lebih penting algoritma mana yang Anda gunakan (algoritma trivial versus fast Fourier transform (FFT)) daripada bahasa yang Anda gunakan (C versus assembly).

Apakah saya akan menulis FFT dalam perakitan? Mungkin tidak.

Apakah saya akan menulis FFT sendiri? Jawabannya mungkin juga tidak, karena FFT telah diterapkan berkali-kali. Jadi kemungkinan Anda akan menemukan beberapa perpustakaan yang sudah menerapkan FFT. Mempertimbangkan bahwa C adalah bahasa portabel sedangkan assembly tidak, Anda akan jauh lebih mungkin menemukan perpustakaan yang sudah ada diimplementasikan dalam C.

Jika Anda menginginkan kinerja yang paling ekstrem, Anda dapat dengan jelas menyetel algoritma FFT agar bekerja secepat mungkin dalam bahasa assembly. Tapi saya tidak benar-benar percaya itu masuk akal untuk melakukan itu kecuali dalam keadaan yang sangat luar biasa.

ahli hukum agama
sumber
2

Pandangan saya sendiri FWIW adalah bahwa setiap kali Anda menginginkan kecepatan / efisiensi / throughput / maksimum apa pun, assembler adalah teman Anda, selama Anda mahir. Kompilator bodoh; ia "tahu" hanya apa yang dipikirkan oleh penulisnya untuk diprogramkan ke dalamnya, dan penulisnya tidak mengetahui aplikasi Anda sama sekali.

Harus saya akui, saya suka assembler sejak awal 80-an 8 bit micros (tidak berbeda sama sekali dengan MCU modern dalam banyak hal) di mana belajar "kode mesin" adalah prasyarat untuk mendapatkan kinerja yang berguna dari mereka, tapi saya pikir perannya tetap sebagai yang cara untuk program efisiensi maksimum. Selain itu, ini sangat bermanfaat karena Anda dapat memasukkan semua jenis pintasan optimal yang tidak akan dipikirkan oleh kompiler, karena kompiler tidak dapat berpikir sama sekali.

C tidak apa-apa kurasa. Tetapi jika Anda benar-benar tahu apa yang Anda ingin mesin Anda lakukan di tingkat perangkat keras, pergilah assembler.

Ian Bland
sumber