Słyszałem, że jeśli należy unikać instrukcji w modułach cieniujących, ponieważ obie części instrukcji zostaną wykonane, a następnie niewłaściwe zostaną usunięte (co szkodzi wydajności).
To wciąż problem w DirectX 10? Ktoś mi powiedział, że w nim zostanie wykonana tylko odpowiednia gałąź.
Do ilustracji mam kod:
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;
}
Czy istnieje inny sposób na przyspieszenie?
Jeśli tak, jak to zrobić?
Obie gałęzie wyglądają podobnie, jedyną różnicą są wartości „stałych” ( y1, y2, b1, b2
są takie same dla wszystkich pikseli w module Pixel Shader).
Odpowiedzi:
Wiele reguł dotyczących mikromoptymalizujących shaderów jest takich samych, jak w przypadku tradycyjnych procesorów z rozszerzeniami wektorowymi. Oto kilka wskazówek:
test
,lerp
/mix
)To prawda, że gałęzie są tańsze na nowoczesnym sprzęcie niż kiedyś, ale nadal lepiej jest ich unikać, jeśli to możliwe. Korzystając z funkcji zamiatania i testowania, możesz przepisać shader bez testów:
Używanie
step
ilerp
jest bardzo powszechnym idiomem do wybierania między dwiema wartościami.źródło
Ogólnie jest OK. Shadery będą działać w grupach wierzchołków lub pikseli (różni dostawcy mają dla nich różną terminologię, więc trzymam się od tego z daleka), a jeśli wszystkie wierzchołki lub piksele w grupie idą tą samą ścieżką, koszt rozgałęzienia jest znikomy.
Musisz także zaufać kompilatorowi modułu cieniującego. Kod HLSL, który piszesz, nie powinien być postrzegany jako bezpośrednia reprezentacja kodu bajtowego lub nawet zestawu, do którego będzie się kompilował, a kompilator ma całkowitą swobodę konwersji na coś równoważnego, ale omija gałąź (np. Lerp może być czasem preferowana konwersja). Z drugiej strony, jeśli kompilator stwierdzi, że wykonanie gałęzi jest w rzeczywistości szybszą ścieżką, skompiluje ją do gałęzi. Przeglądanie wygenerowanego zestawu w PIX lub podobnym narzędziu może być bardzo pomocne.
Wreszcie, stara mądrość wciąż tu jest - profiluj ją, określ, czy to rzeczywiście problem z wydajnością, i rozwiąż ją wtedy, a nie wcześniej. Zakładając, że coś może być problemem związanym z wydajnością, i postępowanie zgodnie z tym założeniem będzie wiązało się z dużym ryzykiem wystąpienia większych problemów w przyszłości.
źródło
Cytat z linku / artykułu opublikowanego przez Roberta Rouhani:
Jak sugerował mh01 („Przeglądanie wygenerowanego zestawu w PIX lub podobnym narzędziu może być bardzo pomocne tutaj.”), Powinieneś użyć narzędzia kompilatora do zbadania danych wyjściowych. Z mojego doświadczenia wynika, że narzędzie Cg nVidii (Cg jest nadal szeroko stosowane ze względu na jego możliwości wieloplatformowe) dało doskonałą ilustrację zachowania wymienionego w paragrafie kodów predykcji (predykcji) klejnotów GPU . Tak więc, niezależnie od wartości wyzwalacza, obie gałęzie były oceniane na podstawie fragmentów i tylko na końcu prawą umieszczono w rejestrze wyjściowym. Niemniej jednak czas obliczeń został zmarnowany. Wtedy myślałem, że rozgałęzienie pomoże wydajności, zwłaszcza że wszystkofragmenty w tym module cieniującym opierały się na jednolitej wartości przy podejmowaniu decyzji o właściwej gałęzi - co nie działało zgodnie z przeznaczeniem. Tak więc główne zastrzeżenie tutaj (np. Unikaj ubershaderów - być może największego źródła rozgałęzienia piekła).
źródło
Jeśli nie masz już problemów z wydajnością, w porządku. Koszt porównania z wartością stałą jest nadal niezwykle tani. Oto dobry artykuł na temat rozgałęziania GPU: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html
Niezależnie od tego, oto fragment kodu, który będzie działał znacznie gorzej niż instrukcja if (i jest znacznie mniej czytelny / możliwy do utrzymania), ale wciąż się go pozbywa:
Zauważ, że zakładam, że x jest ograniczony do zakresu
[0, 1]
. To nie zadziała, jeśli x> = 2 lub x <0.To, co wycina, to konwersja x na jeden
0
lub1
pomnożenie niewłaściwego przez 0, a drugiego przez 1.źródło
if(x<0.5)
wartość dla,fx
powinno byćround(x)
lubfloor(x + 0.5)
.Istnieje wiele instrukcji umożliwiających wykonanie warunków bez rozgałęziania;
Plus niektóre operatory logiczne;
źródło: http://theorangeduck.com/page/avoiding-shader-conditionals
źródło