Operasi pemfilteran gambar seperti pengaburan, SSAO, bloom dan sebagainya biasanya dilakukan menggunakan pixel shader dan operasi "kumpulkan", di mana setiap pemanggilan shader pixel mengeluarkan sejumlah tekstur yang diambil untuk mengakses nilai-nilai piksel tetangga, dan menghitung nilai satu pixel dari hasil. Pendekatan ini memiliki inefisiensi teoretis di mana banyak pengambilan berlebihan dilakukan: doa shader terdekat akan mengambil ulang banyak dari texels yang sama.
Cara lain untuk melakukannya adalah dengan komputasi shader. Ini memiliki potensi keuntungan karena dapat berbagi sejumlah kecil memori di sekelompok doa shader. Misalnya, Anda dapat meminta setiap doa mengambil satu texel dan menyimpannya dalam memori bersama, lalu menghitung hasilnya dari sana. Ini mungkin atau mungkin tidak lebih cepat.
Pertanyaannya adalah dalam keadaan apa (jika pernah) apakah metode compute-shader sebenarnya lebih cepat daripada metode pixel-shader? Apakah ini tergantung pada ukuran kernel, operasi penyaringan seperti apa, dll? Jelas jawabannya akan bervariasi dari satu model GPU ke yang lain, tapi saya tertarik mendengar jika ada tren umum.
sumber
Jawaban:
Keuntungan arsitektural dari komputasi shader untuk pemrosesan gambar adalah mereka melewatkan langkah ROP . Sangat mungkin bahwa menulis dari pixel shaders melewati semua perangkat keras pencampuran biasa bahkan jika Anda tidak menggunakannya. Komputasi shaders secara umum melewati jalur yang berbeda (dan seringkali lebih langsung) ke memori, sehingga Anda dapat menghindari kemacetan yang seharusnya Anda miliki. Saya pernah mendengar tentang kemenangan kinerja yang cukup besar yang dikaitkan dengan ini.
Kerugian arsitektural dari komputasi shader adalah bahwa GPU tidak lagi tahu item pekerjaan yang dipensiunkan ke piksel mana. Jika Anda menggunakan pixel shading pipeline, GPU memiliki peluang untuk mengemas pekerjaan ke warp / wavefront yang menulis ke area target render yang bersebelahan dalam memori (yang mungkin berupa ubin Z-order atau sesuatu seperti itu untuk kinerja alasan). Jika Anda menggunakan jalur komputasi, GPU mungkin tidak lagi bekerja dalam batch yang optimal, yang mengarah ke penggunaan bandwidth yang lebih banyak.
Anda mungkin dapat mengubah pengemasan warp / wavefront yang diubah menjadi keuntungan lagi, meskipun, jika Anda tahu bahwa operasi khusus Anda memiliki substruktur yang dapat Anda manfaatkan dengan mengemas pekerjaan terkait ke dalam grup utas yang sama. Seperti yang Anda katakan, secara teori Anda dapat memberikan contoh perangkat keras sampling dengan mengambil sampel satu nilai per lajur dan menempatkan hasilnya dalam memori bersama grup untuk jalur lain untuk diakses tanpa pengambilan sampel. Apakah ini kemenangan tergantung pada seberapa mahal memori grup Anda: jika lebih murah daripada cache tekstur tingkat terendah, maka ini mungkin menang, tetapi tidak ada jaminan untuk itu. GPU sudah menangani cukup baik dengan mengambil tekstur yang sangat lokal (karena kebutuhan).
Jika Anda memiliki tahap perantara dalam operasi di mana Anda ingin berbagi hasil, mungkin lebih masuk akal untuk menggunakan memori grup (karena Anda tidak dapat kembali ke perangkat keras pengambilan sampel tekstur tanpa benar-benar menuliskan hasil antara Anda ke memori). Sayangnya, Anda juga tidak dapat bergantung pada hasil dari grup utas lainnya, sehingga tahap kedua harus membatasi diri hanya pada apa yang tersedia di ubin yang sama. Saya pikir contoh kanonik di sini adalah menghitung pencahayaan rata-rata layar untuk eksposur otomatis. Saya juga bisa membayangkan menggabungkan upampling tekstur dengan beberapa operasi lain (karena upampling, tidak seperti downsampling dan kabur, tidak tergantung pada nilai di luar ubin yang diberikan).
sumber
John sudah menulis jawaban yang bagus jadi pertimbangkan jawaban ini sebagai perpanjangan dari jawabannya.
Saya saat ini banyak bekerja dengan komputasi shader untuk algoritma yang berbeda. Secara umum, saya telah menemukan bahwa komputasi shader dapat jauh lebih cepat daripada pixel shader yang setara atau mengubah alternatif berbasis umpan balik.
Setelah Anda membungkus kepala Anda di sekitar cara menghitung shader bekerja, mereka juga jauh lebih masuk akal dalam banyak kasus. Menggunakan pixel shaders untuk memfilter suatu gambar memerlukan pengaturan framebuffer, mengirim simpul, menggunakan beberapa tahapan shader, dll. Mengapa ini diperlukan untuk memfilter gambar? Digunakan untuk merender paha depan layar penuh untuk pemrosesan gambar tentu saja merupakan satu-satunya alasan "sah" untuk terus menggunakannya menurut saya. Saya yakin bahwa seorang pendatang baru di bidang grafik komputasi akan menemukan komputasi bayangan lebih cocok secara alami untuk pemrosesan gambar daripada rendering ke tekstur.
Pertanyaan Anda mengacu pada pemfilteran gambar secara khusus sehingga saya tidak akan menguraikan terlalu banyak pada topik lain. Dalam beberapa pengujian kami, hanya menyiapkan umpan balik transformasi atau mengalihkan objek framebuffer untuk dirender menjadi tekstur dapat menimbulkan biaya kinerja sekitar 0,2 ms. Ingatlah bahwa ini tidak termasuk render apa pun! Dalam satu kasus, kami menyimpan algoritma yang sama persis untuk porting shader dan melihat peningkatan kinerja yang nyata.
Saat menggunakan compute shaders, lebih banyak silikon pada GPU dapat digunakan untuk melakukan pekerjaan yang sebenarnya. Semua langkah tambahan ini diperlukan saat menggunakan rute pixel shader:
Anda bisa berargumen bahwa semua keunggulan kinerja yang disebutkan sebelumnya dapat dinegasikan oleh driver pintar. Anda benar. Driver seperti itu dapat mengidentifikasi bahwa Anda membuat quad-screen penuh tanpa pengujian mendalam, dll. Dan mengonfigurasi "jalur cepat" yang melompati semua pekerjaan tidak berguna yang dilakukan untuk mendukung pixel shaders. Saya tidak akan terkejut jika beberapa driver melakukan ini untuk mempercepat pass post-processing di beberapa game AAA untuk GPU spesifik mereka. Tentu saja Anda bisa melupakan perawatan seperti itu jika Anda tidak mengerjakan game AAA.
Apa yang tidak bisa dilakukan pengemudi adalah menemukan peluang paralelisme yang lebih baik yang ditawarkan oleh jalur pipa penghitung komputasi. Ambil contoh klasik dari filter gaussian. Menggunakan compute shaders, Anda dapat melakukan sesuatu seperti ini (memisahkan filter atau tidak):
Langkah 1 adalah kuncinya di sini. Dalam versi pixel shader, gambar sumber disampel beberapa kali per piksel. Dalam versi komputasi shader, setiap sumber texel dibaca hanya sekali di dalam kelompok kerja. Pembacaan tekstur biasanya menggunakan cache berbasis ubin, tetapi cache ini masih jauh lebih lambat daripada memori bersama.
Filter gaussian adalah salah satu contoh sederhana. Algoritma penyaringan lainnya menawarkan peluang lain untuk berbagi hasil perantara di dalam kelompok kerja menggunakan memori bersama.
Namun ada tangkapan. Compute shaders membutuhkan penghalang memori eksplisit untuk menyinkronkan outputnya. Ada juga lebih sedikit perlindungan untuk melindungi terhadap akses memori yang salah. Untuk programmer dengan pengetahuan pemrograman paralel yang baik, compute shaders menawarkan lebih banyak fleksibilitas. Namun fleksibilitas ini berarti bahwa lebih mudah untuk memperlakukan penghitung bayangan seperti kode C ++ biasa dan menulis kode lambat atau salah.
Referensi
sumber
Saya tersandung di blog ini: Hitung Optimasi Shader untuk AMD
Mengingat trik apa yang dapat dilakukan dalam menghitung shader (yang khusus hanya untuk menghitung shader) saya ingin tahu apakah pengurangan paralel pada komputasi shader lebih cepat daripada pada pixel shader. Saya mengirim email ke penulis, Wolf Engel, untuk menanyakan apakah dia telah mencoba pixel shader. Dia menjawab bahwa ya dan kembali ketika dia menulis posting blog, versi shader komputasi jauh lebih cepat daripada versi pixel shader. Dia juga menambahkan bahwa hari ini perbedaannya bahkan lebih besar. Jadi ternyata ada kasus di mana menggunakan compute shader bisa menjadi keuntungan besar.
sumber