DirectX 10 gölgelendiricilerdeki ifadelerden kaçının?


14

İfadelerin gölgelendiricilerden kaçınılması gerektiğini duydum, çünkü ifadelerin her iki kısmı da yürütülecek ve yanlıştan (performansa zarar verecek) düşülecektir.

DirectX 10'da hala bir sorun mu var? Birisi bana, içinde sadece doğru dalın infaz edileceğini söyledi.

Gösterim için kod var:

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;
}

Daha hızlı yapmanın başka bir yolu var mı?

Eğer öyleyse, nasıl?

Her iki dal benzer görünür, tek fark "sabit" değeridir ( y1, y2, b1, b2Piksel Gölgelendiricideki tüm pikseller için aynıdır).


1
Dürüst olmak gerekirse, bu çok erken bir optimizasyon, kodunuzu kıyaslayana ve gölgelendiricinin bir darboğaz olduğunu% 100 olana kadar bunları değiştirmeyin.
pwny

Yanıtlar:


17

Mikro optimizasyonlu gölgelendiriciler için birçok kural, vektör uzantılarına sahip geleneksel CPU'larla aynıdır. İşte birkaç ipucu:

  • dahili test fonksiyonları vardır ( test, lerp/ mix)
  • iki vektör eklemek iki float eklemekle aynı maliyete sahiptir
  • dolandırıcılık ücretsiz

Dalların modern donanımda eskisinden daha ucuz olduğu doğrudur, ancak mümkünse onlardan kaçınmak daha iyidir. Swizzling ve test fonksiyonlarını kullanarak gölgelendiricinizi testler olmadan yeniden yazabilirsiniz:

/* y1, y2, b1, b2 */
float4 constants = float4(5, 6, 2, 3);

float2 tmp = 10 * constants.xy + constants.zw;
x = lerp(tmp[1], tmp[0], step(x, 0.5));

Kullanılması stepve lerpiki değer arasındaki seçtiğiniz için çok yaygın bir deyim olduğunu.


6

Genellikle sorun değil. Gölgelendiriciler köşeler veya piksel grupları halinde yürütülür (farklı satıcılar bunlar için farklı terminolojiye sahiptir, bu yüzden bundan uzak duruyorum) ve bir gruptaki tüm köşeler veya pikseller aynı yolu izlerse dallanma maliyeti göz ardı edilebilir.

Ayrıca gölgelendirici derleyicisine güvenmeniz gerekir. Yazdığınız HLSL kodu, derleyeceği bayt kodun veya hatta derlemenin doğrudan bir temsili olarak görülmemelidir ve derleyici bunu eşdeğer olan bir şeye dönüştürmek için mükemmel bir şekilde ücretsizdir (örneğin, bir lerp bazen olabilir) tercih edilen bir dönüşüm). Öte yandan, derleyici bir dal gerçekleştirmenin aslında daha hızlı bir yol olduğunu belirlerse, bir dalda derleyecektir. Oluşturulan montajın PIX veya benzeri bir araçta görüntülenmesi burada çok yardımcı olabilir.

Son olarak, eski bilgelik hala burada - profil yapın, bunun sizin için bir performans sorunu olup olmadığını belirleyin ve daha önce değil, o zaman mücadele edin. O şey varsayarsak olabilir performans sorunu olabilir ve hareket varsayımına göre sadece daha sonra daha büyük sorunların büyük bir risk tabidir.


4

Robert Rouhani tarafından yayınlanan bağlantıdan / makaleden alıntı:

"Koşul kodları (tahmin), eski mimarilerde gerçek dallanmayı taklit etmek için kullanılır. If-then bu mimarilere derlenen ifadelerin tüm fragmanlarda alınan ve alınmayan dal talimatlarını değerlendirmesi gerekir. Dal koşulu değerlendirilir ve bir koşul kodu ayarlanır. Sonuçların kayıtlara yazılmadan önce koşulun her bir bölümündeki talimatlar koşul kodunun değerini kontrol etmelidir Sonuç olarak, sadece alınan branşlardaki talimatlar çıktılarını yazmaktadır Bu nedenle, bu mimarilerde tüm branşların maliyeti şube, artı şube durumunu değerlendirme maliyeti. Dallanma bu tür mimarilerde çok az kullanılmalıdır. NVIDIA GeForce FX Serisi GPU'lar parça işlemcilerinde koşul kodu şube öykünmesini kullanır. "

Mh01'in önerdiği gibi ("Oluşturulan montajı PIX veya benzeri bir araçta görüntülemek burada çok yardımcı olabilir."), Çıktıyı incelemek için bir derleyici aracı kullanmalısınız. Deneyimlerime göre, nVidia'nın Cg aracı (çapraz platform yetenekleri nedeniyle günümüzde hala yaygın olarak kullanılmaktadır ) GPU mücevher durum kodlarında ( ) belirtilen davranışın mükemmel bir örneğini verdi paragrafında . Bu nedenle, tetikleyici değerine bakılmaksızın, her iki dal da parça başına bazda değerlendirildi ve sadece sonunda doğru olan çıktı kayıt defterine yerleştirildi. Bununla birlikte, hesaplama süresi boşa gitmiştir. O zamanlar, bu dallanma irade yardım performansını düşünce özellikle çünkü tümbu gölgelendiricideki parçalar, doğru dalda karar vermek için tekdüze bir değere dayanıyordu - bu amaçlandığı gibi olmadı. Yani, burada büyük bir uyarı (örneğin ubershader'lardan kaçının - muhtemelen en büyük dallanma cehennemi kaynağı).


2

Performans sorunları yaşamıyorsanız, sorun değil. Bir sabit ile karşılaştırma maliyeti hala son derece ucuzdur. GPU dallanma hakkında iyi bir okuma: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html

Ne olursa olsun, burada if ifadesinden çok daha kötü bir kod parçası (ve çok daha az okunabilir / bakımı yapılabilir), ancak yine de ondan kurtulur:

int fx = floor(x);
int y = (fx * y2) + ((1- fx) * y1);
int b = (fx * b2) + ((1 -fx) * b1);

x = 10 * y + b;

Not: x'in aralıkla sınırlı olduğunu varsayıyorum [0, 1]. X> = 2 veya x <0 ise bu çalışmaz.

Kesilen şey x'i ya ikisine dönüştürmek ya 0da 1yanlış olanı 0 ile diğerini 1 ile çarpmaktır.


Orijinal test if(x<0.5)için değer olması fxgerektiği için round(x)veya olmalıdır floor(x + 0.5).
sam hocevar

1

Dallanma olmadan koşullar yapabilen çoklu talimatlar vardır;

vec4 when_eq(vec4 x, vec4 y) {
  return 1.0 - abs(sign(x - y));
}

vec4 when_neq(vec4 x, vec4 y) {
  return abs(sign(x - y));
}

vec4 when_gt(vec4 x, vec4 y) {
  return max(sign(x - y), 0.0);
}

vec4 when_lt(vec4 x, vec4 y) {
  return max(sign(y - x), 0.0);
}

vec4 when_ge(vec4 x, vec4 y) {
  return 1.0 - when_lt(x, y);
}

vec4 when_le(vec4 x, vec4 y) {
  return 1.0 - when_gt(x, y);
}

Ayrıca bazı mantıksal operatörler;

vec4 and(vec4 a, vec4 b) {
  return a * b;
}

vec4 or(vec4 a, vec4 b) {
  return min(a + b, 1.0);
}

vec4 xor(vec4 a, vec4 b) {
  return (a + b) % 2.0;
}

vec4 not(vec4 a) {
  return 1.0 - a;
}

kaynak: http://theorangeduck.com/page/avoiding-shader-conditionals

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.