Saya telah mendengar bahwa jika pernyataan harus dihindari dalam bayangan, karena kedua bagian dari pernyataan akan dieksekusi, dan daripada yang salah akan dijatuhkan (yang merusak kinerja).
Masih menjadi masalah di DirectX 10? Seseorang mengatakan kepada saya, bahwa di dalamnya hanya cabang yang tepat yang akan dieksekusi.
Sebagai ilustrasi saya punya kode:
float y1 = 5; float y2 = 6; float b1 = 2; float b2 = 3;
if(x>0.5){
x = 10 * y1 + b1;
}else{
x = 10 * y2 + b2;
}
Apakah ada cara lain untuk membuatnya lebih cepat?
Jika demikian, bagaimana caranya?
Kedua cabang terlihat serupa, satu-satunya perbedaan adalah nilai-nilai "konstanta" ( y1, y2, b1, b2
sama untuk semua piksel dalam Pixel Shader).
Jawaban:
Banyak aturan untuk shader yang mengoptimalkan mikro sama dengan CPU tradisional dengan ekstensi vektor. Berikut ini beberapa petunjuk:
test
,lerp
/mix
)Memang benar bahwa cabang lebih murah pada perangkat keras modern daripada sebelumnya, tetapi masih lebih baik untuk menghindarinya jika memungkinkan. Dengan menggunakan fungsi swizzling dan tes Anda dapat menulis ulang shader Anda tanpa tes:
Menggunakan
step
danlerp
merupakan ungkapan yang sangat umum untuk memilih antara dua nilai.sumber
Secara umum tidak masalah. Shader akan dieksekusi dalam kelompok simpul atau piksel (vendor yang berbeda memiliki terminologi berbeda untuk ini jadi saya menjauhi itu) dan jika semua simpul atau piksel dalam grup mengambil jalur yang sama maka biaya percabangan diabaikan.
Anda juga perlu mempercayai kompiler shader. Kode HLSL yang Anda tulis tidak boleh dilihat sebagai representasi langsung dari bytecode atau bahkan rakitan yang akan dikompilasi, dan kompiler bebas untuk mengubahnya menjadi sesuatu yang setara tetapi menghindari cabang (misalnya lerp kadang-kadang mungkin konversi yang disukai). Di sisi lain, jika kompiler menentukan bahwa melakukan cabang sebenarnya adalah jalur yang lebih cepat, ia akan mengkompilasinya ke cabang. Melihat perakitan yang dihasilkan di PIX atau alat serupa bisa sangat membantu di sini.
Akhirnya, kearifan lama masih berlaku di sini - profil itu, tentukan apakah itu benar-benar masalah kinerja untuk Anda, dan atasi itu, bukan sebelumnya. Dengan asumsi bahwa sesuatu mungkin merupakan masalah kinerja dan bertindak sesuai dengan asumsi itu hanya akan menimbulkan risiko besar masalah yang lebih besar di kemudian hari.
sumber
Kutipan dari tautan / artikel yang diposting oleh Robert Rouhani:
Seperti yang disarankan mh01 ("Melihat rakitan yang dihasilkan dalam PIX atau alat serupa bisa sangat membantu di sini."), Anda harus menggunakan alat kompiler untuk memeriksa hasilnya. Dalam pengalaman saya, alat CV nVidia (Cg masih banyak digunakan saat ini karena kemampuan lintas platformnya) memberikan ilustrasi sempurna tentang perilaku yang disebutkan dalam paragraf kode kondisi permata (predikasi) paragraf GPU . Dengan demikian, terlepas dari nilai pemicu, kedua cabang dievaluasi berdasarkan per fragmen, dan hanya pada akhirnya, yang tepat ditempatkan dalam registri keluaran. Namun demikian, waktu perhitungan terbuang sia-sia. Saat itu, saya berpikir bahwa percabangan akan membantu kinerja, terutama karena semuanyafragmen dalam shader itu bergantung pada nilai yang seragam untuk memutuskan cabang yang tepat - yang tidak terjadi seperti yang dimaksudkan. Jadi, peringatan utama di sini (misalnya, hindari ubershaders - mungkin sumber neraka percabangan terbesar).
sumber
Jika Anda belum mengalami masalah kinerja, ini tidak masalah. Biaya perbandingan dengan konstanta masih sangat murah. Berikut ini bacaan yang bagus tentang percabangan GPU: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html
Bagaimanapun juga, ini adalah potongan kode yang akan terbentuk lebih buruk daripada pernyataan if (dan jauh lebih mudah dibaca / dikelola), tetapi masih menghilangkannya:
Perhatikan bahwa saya membuat asumsi bahwa x terbatas pada rentang
[0, 1]
. Ini tidak akan berfungsi jika x> = 2 atau x <0.Apa yang dilakukan potongan adalah mengonversi x menjadi salah satu
0
dan1
dan mengalikan yang salah dengan 0 dan yang lainnya dengan 1.sumber
if(x<0.5)
nilaifx
seharusnyaround(x)
ataufloor(x + 0.5)
.Ada banyak instruksi yang dapat melakukan kondisi tanpa bercabang;
Ditambah beberapa operator logis;
sumber: http://theorangeduck.com/page/avoiding-shader-conditionals
sumber