- Tim pengembang FFmpeg mengumumkan peningkatan performa hingga 100 kali lipat melalui kode assembly yang ditulis langsung
- Patch kali ini tidak mempercepat seluruh program, melainkan hanya memberikan peningkatan pada fungsi tertentu
- Saat CPU terbaru mendukung AVX512, peningkatan mencapai 100x, sedangkan pada dukungan AVX2 terkonfirmasi ada peningkatan performa 64%
- Fitur peningkatan tersebut terutama diterapkan pada filter yang kurang dikenal
- Optimasi otomatis compiler masih menunjukkan kesenjangan performa dibanding kode assembly yang ditulis langsung
Peningkatan performa FFmpeg: makna sebenarnya dari akselerasi 100x
Patch terbaru dan poin perbaikan utama
- Tim proyek FFmpeg menyoroti capaian "peningkatan kecepatan 100x" pada alat transcoding media open source lintas platform tersebut setelah menerapkan kode assembly yang ditulis manual
- Namun, tim pengembang juga menjelaskan dengan tegas bahwa klaim tersebut berlaku bukan untuk seluruh FFmpeg, melainkan hanya satu fungsi
- Optimalisasi luar biasa ini diterapkan pada fungsi
rangedetect8_avx512, dengan peningkatan hingga 100x pada prosesor yang mendukung AVX512 terbaru, dan sekitar 64% pada jalur AVX2
- Fitur ini diterapkan pada filter yang tidak begitu dikenal, yang sebelumnya tidak diprioritaskan dalam pengembangan, tetapi kali ini berhasil dioptimalkan untuk pemrosesan paralel dengan pendekatan SIMD (single instruction, multiple data)
Penjelasan pengembang dan latar belakang teknis
- Melalui Twitter, tim FFmpeg dengan jelas menyampaikan, "hanya fungsi ini yang menjadi 100x lebih cepat, bukan seluruh FFmpeg"
- Dalam penjelasan tambahan, mereka menyebut fitur tersebut bergantung pada sistem dan berpotensi meningkatkan kecepatan hingga 100%
- Peningkatan performa ini merupakan hasil dari teknologi SIMD, yang secara signifikan meningkatkan efisiensi pemrosesan paralel pada chip modern
Pentingnya menulis langsung bahasa assembly
Pendekatan optimasi dulu dan sekarang
- Pada era 1980-an hingga 1990-an, kode assembly yang ditulis langsung merupakan alat utama untuk meningkatkan kecepatan game dan berbagai perangkat lunak dalam lingkungan hardware yang terbatas
- Saat ini, sebagian besar compiler modern memang mengubah kode bahasa tingkat tinggi menjadi kode assembly, tetapi karena keterbatasan optimasi compiler, seperti alokasi register, kode assembly yang ditulis manual masih dapat menghasilkan performa lebih tinggi
- FFmpeg adalah salah satu dari sedikit proyek yang tetap mempertahankan filosofi optimasi ini, dan bahkan menyediakan kursus assembly sendiri
Pengaruh FFmpeg dalam ekosistem
- Library dan tool FFmpeg berjalan di berbagai lingkungan seperti Linux, Mac OS X, Microsoft Windows, BSD, dan Solaris
- Program pemutar video populer seperti VLC juga memanfaatkan library FFmpeg seperti libavcodec dan libavformat
- Ini menunjukkan besarnya arti teknis FFmpeg dalam ekosistem open source untuk encoding/decoding media yang luas
Penutup
- Peningkatan performa kali ini memang terbatas pada sebagian fungsi, bukan keseluruhan fitur inti, tetapi tetap menjadi contoh yang menunjukkan upaya menembus batas performa
- Kombinasi optimasi khusus hardware modern dan semangat open source terus menjadikan FFmpeg sebagai teladan teknis di bidang pemrosesan media
3 komentar
Ini memang berlaku dulu maupun sekarang
Dengan cara yang mirip, saat mem-porting library codec ke ARM saya juga mulai dari mengurai kernel berbasis SSE satu per satu, dan setelah semuanya selesai diurai hingga hanya menyisakan versi skalar lalu menjalankan benchmark dunia nyata, perbedaan performanya terasa signifikan.
Seorang engineer yang bisa menulis kode yang lebih teroptimasi daripada GCC... luar biasa sekali.
Komentar Hacker News
Selama 10 tahun saya mengerjakan optimasi SIMD untuk HEVC dan semacamnya, membandingkan versi assembly dengan versi C biasa nyaris jadi bahan lelucon, karena kadang keluar angka luar biasa seperti perbedaan 100x. Sebenarnya hasil seperti ini berarti efisiensi awalnya sangat rendah. Dalam penggunaan nyata, lingkungannya bukan seperti microbenchmark yang memanggil fungsi yang sama jutaan kali terus-menerus saat cache penuh. Sebaliknya, dalam situasi nyata fungsi itu bisa saja hanya dipanggil sekali di tengah banyak pekerjaan lain. Untuk mengurangi efek cache, pengujian seharusnya memakai area memori uji yang sangat besar, dan saya ragu apakah itu benar-benar dilakukan.
Saya penasaran apakah perangkat lunak transcoding video seperti FFmpeg juga menjalankan "macro benchmark" terpisah. Rasanya mereka akan mengukur performa, kualitas, penggunaan CPU, dan sebagainya dalam jangka waktu lama pada beragam video dan kombinasi transcode, dan menurut saya itu membutuhkan perangkat keras khusus yang konsisten.
Ini agak melenceng, tapi karena Anda tampaknya berpengalaman dengan SIMD, saya ingin bertanya apakah Anda pernah memakai ISPC dan bagaimana pendapat Anda tentangnya. Rasanya agak aneh bahwa sampai sekarang kita masih harus menulis kode SIMD sendiri dan compiler umum masih lemah dalam auto-vectorization, sangat kontras dengan kernel GPU yang sejak dulu selalu mendapat vectorization otomatis.
Saya rasa ffmpeg sendiri juga tidak jauh berbeda dari microbenchmark. Pada dasarnya strukturnya seperti
while (read(buf)) write(transform(buf)).Sayangnya, selain soal cache, para pengembang kadang menyebut peningkatan 100%, padahal sebenarnya itu hanya berlaku untuk filter yang sangat terbatas. Meski begitu, mereka biasanya cukup transparan dalam menyampaikan informasinya.
Soal interpretasi "awalnya tidak efisien", menurut saya yang penting adalah angka apa yang keluar dan hasilnya sendiri.
Di artikel itu ada bagian yang menyebut 100x, sementara bagian lain menyebut peningkatan kecepatan 100%, jadi membingungkan. Misalnya tertulis "performa
rangedetect8_avx512meningkat 100,73%", tetapi screenshot-nya menunjukkan 100,73x. Kalau 100x berarti peningkatan 9900%, sedangkan peningkatan kecepatan 100% berarti 2x lebih cepat. Saya penasaran mana yang benar.Seperti yang terlihat di screenshot, jelas yang benar adalah 100x (atau 100,73x), yang berarti peningkatan kecepatan 9973%. Tampaknya penulisan % di isi artikel salah.
Untuk satu fungsi itu 100x, untuk keseluruhan filter 100% (2x).
Klaim dari pihak ffmpeg adalah 100x. Yang 100% sepertinya typo di artikel.
Nama fungsinya terkait dengan '8', dan jika operasinya memang pada nilai 8-bit, maka bila implementasi sebelumnya bersifat skalar, AVX512 bisa memproses 128 elemen sekaligus, jadi peningkatan 100x menurut saya memang mungkin.
Ada juga panduan resmi dari ffmpeg tentang penulisan assembly, saya tinggalkan di sini sebagai referensi: https://news.ycombinator.com/item?id=43140614
Dari artikel itu, masih terasa kurang jelas
rangedetect8_avx512sebenarnya dipakai dalam situasi apa dan seberapa besar peningkatan performa real-time pada keseluruhan proses transcode. Saya penasaran apakah ini benar-benar punya arti praktis yang terlihat.Dulu ketika sinyal video masih analog, sinyal kontrol diproses dengan dikodekan di dalam band. Bahkan setelah DVD, karena sinyal digital tetap dikeluarkan sebagai analog, nilai warna di bawah 16 (dari 0~255) dipakai sebagai sinyal "lebih hitam dari hitam", dan BluRay serta HDMI juga sama. Belakangan ada pergeseran untuk memakai seluruh rentang 0~255. Namun sampai sekarang pembedaan rentang sinyal ini sering masih salah sehingga video jadi gelap dan rusak. Fungsi ini tampaknya dipakai untuk menentukan apakah nilai piksel berada di 16~255 atau 0~255. Jika jelas itu 16~255, informasi bisa dihemat saat encoding. Tapi ini hanya dugaan. Saya juga bekerja dengan video, dan agak memalukan karena saya sendiri masih sering salah menangani level hitam.
Filter ini tidak dipakai dalam proses transcode, melainkan untuk menentukan informasi metadata seperti rentang warna atau apakah alpha bersifat premultiplied. Fungsi yang dimaksud termasuk bagian untuk mendeteksi rentang warna.
Saya ingin menyebut pengalaman menarik: satu-satunya alasan saya pernah menulis kode assembly juga karena SIMD. Baru-baru ini saya membicarakan hal itu, dan saya sempat lupa bahwa waktu itu memang harus pakai assembly. Sebenarnya karena masalah aliasing di compiler, optimasi yang saya inginkan tidak terjadi. Setelah saya menjelaskan dengan tegas bahwa data tidak akan diakses dengan cara lain dan memakai keyword non-standar, compiler otomatis memanfaatkan instruksi SIMD. Akhirnya assembly yang saya tulis sendiri pun saya hapus.
Agak ironis bahwa optimasi kali ini hanya berlaku untuk x86/x86-64 (AVX2, AVX512). Dulu ketika semua orang memakai x86, ada peluang besar optimasi SIMD diterapkan luas, tetapi arsitektur ekstensi baru benar-benar buruk atau kurang kompatibel. Dan sekarang saat SIMD x86 akhirnya jadi bagus, x86 sudah bukan lagi standar mutlak sehingga makin sulit untuk bergantung padanya.
Terus terang saya terkejut bahwa assembly bisa lebih cepat daripada C yang sudah dioptimalkan. Compiler modern sekarang begitu bagus sehingga saya kira menulis assembly sendiri hanya akan memberi peningkatan yang sangat kecil, tapi jelas saya keliru. Saya jadi memutuskan suatu hari nanti benar-benar harus belajar assembly.
Setelah melihat patch terkait, baseline yang ada (
ff_detect_range_c) adalah kode C skalar yang sangat umum, dan peningkatan kecepatan datang dari versi AVX-512 untuk operasi yang sama (ff_detect_rangeb_avx512). Para pengembang FFmpeg cenderung suka menulis assembly langsung dengan macro yang tidak bergantung pada lebar vektor, tetapi menurut saya hal yang hampir sama juga bisa diekspresikan dengan intrinsics dari Intel (pada dasarnya perbedaannya hanya di alokasi register, jadi secara praktis tidak banyak beda). Inti perbedaan kecepatan ada pada seberapa baik vectorization dilakukan. Dengan compiler modern, vectorization untuk loop yang tidak sepenuhnya trivial hampir mustahil, dan itu pun baru dicoba jika diberi opsi sepertigcc -O3. Jadi pada operasi unit kecil seperti 8-bit ini, vectorization manual dengan AVX/AVX2/AVX-512 bisa memberi selisih performa setidaknya puluhan kali. Pada CPU modern, kadang kode skalar yang sangat dioptimalkan juga bisa ditulis lebih cepat daripada hasil compiler, tetapi itu sangat jarang dan perlu perhatian besar (dependency chain, beban execution port, dan sebagainya). Saya sendiri pernah mengalami peningkatan 40%. Tautan terkait: baseline C, versi AVX512Begitu Anda mendekati optimasi level rendah, Anda akan mengalami kasus compiler C tiba-tiba berperilaku aneh dalam waktu kurang dari satu jam. Jika itu benar-benar kode yang dipanggil sangat sering, isu optimasi memang jadi sangat penting dalam praktik. Contoh: https://stackoverflow.com/questions/71343461/how-does-gcc-not-clang-make-this-optimization-deciding-that-a-store-to-one-str
Bahkan hanya turun ke SIMD intrinsics saja sudah bisa meningkatkan performa jauh lebih mudah dibanding menyerahkannya ke compiler. Saya pernah menulis panduan tentang itu dalam beberapa bagian: https://scallywag.software/vim/blog/simd-perlin-noise-i
Hampir semua bagian yang menentukan performa di pustaka C/C++ memakai assembly yang ditulis manual (bahkan fungsi sederhana seperti
strlenjuga demikian). Compiler memang menghasilkan keluaran yang lumayan dalam banyak kasus, tetapi hanya sedikit perangkat lunak yang cukup penting hingga layak diberi investasi sebesar ini.Peningkatan performa yang sebenarnya bukan karena assembly, melainkan karena AVX512. Kernel ini sangat sederhana, jadi jika ditulis dengan intrinsics AVX512, perbedaan antara kode C dan assembly hampir tidak ada. Alasan selisih 100x adalah a)
min/maxdi SIMD diproses sebagai satu instruksi, sedangkan di skalar terpecah menjadicmp+cmov; b) karena presisinya 8-bit, tiap instruksi AVX512 bisa menangani 64 elemen sekaligus. Akibatnya, bandwidth cache L1 dan L2 pun bisa sampai jenuh (pada Zen 5: 128B, 64B/cycle). Namun jika memproses satu frame penuh, keuntungan itu akan berkurang jika ukuran memorinya memaksa akses ke L3, dan jika bahkan tidak muat di L3, keuntungannya akan lebih kecil lagi.Ini mengingatkan saya pada Sound Open Firmware (SOF), yang juga bisa dibangun dengan memilih antara gcc dan compiler komersial Cadence XCC (mendukung Xtensa HiFi SIMD intrinsics): https://thesofproject.github.io/latest/introduction/index.html#toolchain-faq
Itu 100x, bukan 100% x.