Dampak loop panjang variabel pada GPU shader

9

Sangat populer untuk membuat konten prosedural di dalam GPU misalnya dalam demoscene (menggambar quad tunggal untuk mengisi layar dan membiarkan GPU menghitung piksel).

Ray marching populer:

masukkan deskripsi gambar di sini

Ini berarti GPU sedang mengeksekusi sejumlah iterasi loop yang tidak diketahui per piksel (walaupun Anda dapat memiliki batas atas seperti maxIterations).

Bagaimana cara memiliki loop panjang variabel memengaruhi kinerja shader?

Bayangkan psuedocode ray-marching sederhana:

t = 0.f;
while(t < maxDist) {
    p = rayStart + rayDir * t;
    d = DistanceFunc(p);
    t += d;
    if(d < epsilon) {
       ... emit p
       return;
    }
}

Bagaimana berbagai keluarga GPU arus utama (Nvidia, ATI, PowerVR, Mali, Intel, dll) terpengaruh? Vertex shaders, tetapi terutama shader fragmen?

Bagaimana cara dioptimalkan?

Akan
sumber
Sayangnya, pertanyaan ini terlalu sulit untuk dijawab dengan benar di sini. Meskipun satu jawaban sudah memberikan poin ke sumber yang layak dibaca (melibatkan percabangan dinamis). +1 untuk "topik" ..
teodron
1
@teodron jangan menjadi pengalah! Saya berharap seseorang akan mengatakan bahwa pada kartu NVidia, piksel layar dalam blok 8x8 semua akan terulang sejauh kebutuhan terdalam, dan bahwa blok 8x8 piksel dapat dilakukan dalam urutan apa pun, atau sesuatu seperti itu; itu tidak benar, itu hanya jenis kebijaksanaan yang saya harap orang-orang akan dapat bagikan. Tautan di Larrabee, hmm, cukup tidak langsung.
Will
Kelihatannya dia tidak membahas Larrabee, tetapi pria Stanford itu memberikan ceramah yang sama dua tahun setelahnya, pada tahun 2010 ( Anda dapat melihatnya di sini ). Dari angka-angkanya, mempertimbangkan loop sementara, saya tidak mengerti apakah piksel yang "mengakhiri" perhitungan mereka lebih cepat menebus kinerja apa pun. Di CUDA, utas menunggu di penghalang. Dalam analogi, apa yang terjadi dengan utas shader?
teodron
@teodron ya, saya telah mengambil pemahaman saya tentang CUDA dan diterapkan ke GPU; Saya yakin mereka berbaris, tetapi saya ingin seseorang yang memiliki pengetahuan untuk berpadu; lagi pula, inilah sesuatu yang terkait williamedwardscoder.tumblr.com/post/26628848007/rod-marching
Will

Jawaban:

8

Ada pembicaraan yang baik di GDC 2012 tentang jarak-ray lapangan GPU (dan topik lainnya): http://directtovideo.wordpress.com/2012/03/15/get-my-slides-from-gdc2012/

Sejauh kinerja berjalan, kartu grafis (kelas DX11) terbaru mengeksekusi shader pada unit SIMD yang menjalankan 32 "NVIDIA" atau 64 "AMD" berbaris. Kelompok-kelompok ini dikenal sebagai warps atau wavefronts. Untuk pixel shaders, setiap utas sama dengan satu piksel, jadi saya berharap bahwa unit SIMD memproses sesuatu seperti 8x4 (NVIDIA) atau 8x8 (AMD) blok piksel secara bersamaan. Kontrol percabangan dan aliran dilakukan per-muka gelombang, sehingga semua utas di muka gelombang harus berulang sebanyak piksel individual terdalam di muka gelombang itu. Topeng jalur SIMD akan mematikan eksekusi untuk piksel yang telah selesai, tetapi mereka masih harus diam-diam mengikuti kontrol aliran muka gelombang keseluruhan. Ini berarti, tentu saja, bahwa sistem ini jauh lebih efisien ketika percabangannya koheren,

Dalam pengalaman saya, overhead cabang masih cukup tinggi bahkan jika semua utas di cabang muka gelombang dengan cara yang sama. Saya telah melihat peningkatan kinerja dalam beberapa kasus dengan membuka gulungan untuk mengamortisasi beberapa overhead cabang. Namun, itu tergantung pada seberapa banyak pekerjaan yang Anda lakukan di setiap perulangan, tentu saja. Jika loop body memiliki cukup "barang" di dalamnya, membuka gulungan tidak akan menang.

Nathan Reed
sumber
0

Berkenaan dengan percabangan dinamis, satu catatan tambahan (mungkin jelas, tetapi masih perlu diperhatikan untuk beberapa orang): itu dapat sangat mempengaruhi kinerja loop yang tidak gulungan (Anda jelas tidak dapat membuka gulungan loop jika ada jumlah iterasi yang tidak konstan) .

Gavan Woolery
sumber
-4

int s = 0;

sekarang untuk (int k = 1; k <= n; k ++) {s + = k;} sama seperti s = n * (n + 1) / 2

jadi itu tidak benar secara umum: D

Gimp
sumber
1
Anda mungkin akan banyak dipilih karena tidak ada yang yakin apa yang ingin Anda sampaikan di sini atau apa hubungannya dengan pertanyaan itu.
doppelgreener