Kreuz- und Skalarprodukt, welcher Operator?
-
hustbaer schrieb:
Vermutlich ist es aber mittlerweile schlauer sich an bestehende Dinge wie HLSL/Cg zu halten... und dort ist * ja glaube ich immer komponentenweise.
In HLSL ja, in GLSL ist * bei zwei Vektoren komponentenweise, wenn mindestens ein Operand eine Matrix ist, dann ist es eine Matritzenmultiplikation...
-
hustbaer schrieb:
Natürlich gibt es bei Farb-Berechnungen auch Fälle wo man wirklich zwei Vektoren (Farben) komponentenweise multiplizieren will (muss). Daran hatte ich nicht gedacht.
Ich bin ja ein starker verfechter für * als das Hadamard product (da sheißt komponntenweise multiplizieren). Es kommt wesntlich häufiger vor, als nur Farben zu multiplizieren und macht mehr sinn als * für dot oder skalarprodukt:Der ergebnistyp ist der selbe wie der Typ der Vektoren/matrizen und es gelten sogut wie alle mathematischen Axiome aus der Algebra. Afaik ist das Einzige, das nicht gilt a*b = 0 <=> a= 0 oder b= 0. Insofern ist es dem Kreuzprodukt oder dem äußeren Produkt klar zu bevorzugen. Was das Punktprodukt angeht: In C++ kriegt man ja beides gleichzeitig hin, wenn man es unbedingt will. ich halte aber inner_prod(a,b) schon für besser. Oder trans(a)*b für inneres und b*trans(a) für äußeres produkt, dann emuliert man die a^T b Notation (kriegt aber probleme mit der matrixmultiplikation, welche ich unter gar keinen Umständen als Operator defineiren würde)
-
otze schrieb:
[...] und b*trans(a) für äußeres produkt [...]
Das ist dann aber das dyadische Produkt und nicht das Kreuzprodukt, oder!?
-
hustbaer schrieb:
OK, jetzt verstehe ich was du meinst.
Wobei ich das Beispiel schlecht finde.
Das Ergebnis von nem dot ist ein Skalar, kein Vektor.zudem, auch wenn es nicht offensichtlich erscheint erstmal, wuerde ich bei vector operatoren auch immer nur vector parameter akzeptieren und zurueckgeben, weil man dann durchgaengig auf SIMD arbeiten kann, ansonsten kann es oefter vorkommen dass man aus simd zu float konvertiert nur um dann wieder auf simd zu konvertieren
hustbaer schrieb:
Also tut man es auch in einen Skalar reinmachen:
vec4 Radiosity=Lightmap... vec4 Normal=Normalmap... vec4 Color=Texture... float Diffuse=Light*Normal; vec4 FinalColor=Radiosity*Color*Diffuse;
Und schon passt es wieder nicht.
Vermutlich ist es aber mittlerweile schlauer sich an bestehende Dinge wie HLSL/Cg zu halten... und dort ist * ja glaube ich immer komponentenweise.
was schade ist, ist dass es nur diese primitiven operatoren gibt, eigentlich sollten ein paar mehr mathematische funktionen als operatoren definiert sein.
frueher hab ich ein wenig "profan" programmiert, bis version 4.2 oder so, gab es keine operatoren, ein dot war sowas wie
declare foo; foo=@add(@add(@mul(x0,x1),@mul(y0,y1)),@mul(z0,z1));
das hat mich ein wenig gelehrt, dass man fuer simple dinge die oft verwendet eher operatoren statt funktionen macht. und dot, cross, normalize, inverse finde ich zu gaengig fuer funktionen
-
rapso schrieb:
was schade ist, ist dass es nur diese primitiven operatoren gibt, eigentlich sollten ein paar mehr mathematische funktionen als operatoren definiert sein.
Meinst du Dinge wie z.B. symbolische Differentiation!?
-
rapso schrieb:
hustbaer schrieb:
OK, jetzt verstehe ich was du meinst.
Wobei ich das Beispiel schlecht finde.
Das Ergebnis von nem dot ist ein Skalar, kein Vektor.zudem, auch wenn es nicht offensichtlich erscheint erstmal, wuerde ich bei vector operatoren auch immer nur vector parameter akzeptieren und zurueckgeben, weil man dann durchgaengig auf SIMD arbeiten kann, ansonsten kann es oefter vorkommen dass man aus simd zu float konvertiert nur um dann wieder auf simd zu konvertieren
Ist v/vec4(x, x, x, x) wirklich schneller als v/x?
Ich meine v/x wird gerne mal zutemp = 1.0/x; v * vec4(temp, temp, temp, temp)
und das sollte doch eigentlich schneller sein.
Und durchgängig auf SIMD arbeiten... können aktuelle Compiler keinen Code erzeugen der SSE2 auch für einzelne floats verwendet? Ich dachte nämlich dass die das können, und dann wäre es ziemlich schnuppe ... bzw. sogar besser wenn man einzelne floats nimmt wo man nur einzelne floats braucht.Und auf GPUs ist es ja, soweit ich weiss, auch mittlerweile zur Sünde geworden mehr Komponenten zu verwenden als man eigentlich braucht. Skalare Shader Units und so...
Oder hab' ich da was falsch mitbekommen?
-
hustbaer schrieb:
Ist v/vec4(x, x, x, x) wirklich schneller als v/x?
Ich meine v/x wird gerne mal zutemp = 1.0/x; v * vec4(temp, temp, temp, temp)
und das sollte doch eigentlich schneller sein.
MSVC sollte das tun...
hustbaer schrieb:
Und durchgängig auf SIMD arbeiten... können aktuelle Compiler keinen Code erzeugen der SSE2 auch für einzelne floats verwendet? Ich dachte nämlich dass die das können, und dann wäre es ziemlich schnuppe ... bzw. sogar besser wenn man einzelne floats nimmt wo man nur einzelne floats braucht.
Unter x64 kann man mehr oder weniger davon ausgehen, dass der Compiler auch für skalare Operationen SSE verwendet. Unter x86 nicht unbedingt, zumindest MSVC scheint mir dort immer noch zumindest meistens die FPU zu verwenden, vermutlich vor allem aus Kompatibilitätsgründen.
hustbaer schrieb:
Und auf GPUs ist es ja, soweit ich weiss, auch mittlerweile zur Sünde geworden mehr Komponenten zu verwenden als man eigentlich braucht. Skalare Shader Units und so...
Oder hab' ich da was falsch mitbekommen?Auf NVIDIA Hardware >= GeForce 8 prinzipiell wohl ja, bei ATI schaut's dagegen anders aus, die verwenden afaik zumindest bis vor kurzem noch VLIW Vektorhardware, wobei iirc zumindest eine ihrer allerletzten Architekturen auch eher in die skalare Richtung ging...
-
dot schrieb:
hustbaer schrieb:
Und durchgängig auf SIMD arbeiten... können aktuelle Compiler keinen Code erzeugen der SSE2 auch für einzelne floats verwendet? Ich dachte nämlich dass die das können, und dann wäre es ziemlich schnuppe ... bzw. sogar besser wenn man einzelne floats nimmt wo man nur einzelne floats braucht.
Unter x64 kann man mehr oder weniger davon ausgehen, dass der Compiler auch für skalare Operationen SSE verwendet. Unter x86 nicht unbedingt, zumindest MSVC scheint mir dort immer noch zumindest meistens die FPU zu verwenden, vermutlich vor allem aus Kompatibilitätsgründen.
MSVC verwendet im x86 Mode SSE2 nur wenn man es ihm erlaubt. Hast du bei deinen Experimenten auch den nötigen Switch mitgegeben? Wäre dann schade, aber OK, wegen eines einzigen Compilers werd ich jetzt auch nicht Code schreiben der komisch riecht und auf anderen Compilern im Falle des Falles sogar langsamer ist.
hustbaer schrieb:
Und auf GPUs ist es ja, soweit ich weiss, auch mittlerweile zur Sünde geworden mehr Komponenten zu verwenden als man eigentlich braucht. Skalare Shader Units und so...
Oder hab' ich da was falsch mitbekommen?Auf NVIDIA Hardware >= GeForce 8 prinzipiell wohl ja, bei ATI schaut's dagegen anders aus, die verwenden afaik zumindest bis vor kurzem noch VLIW Vektorhardware, wobei iirc zumindest eine ihrer allerletzten Architekturen auch eher in die skalare Richtung ging...
Auch interessant, danke.
Wobei... wenn es auf NIVEA Karten pöse ist, dann ist es pöse und aus
(Und nicht pöse zu sein wird einem auf ATI Karten vermutlich auch keine Probleme machen, oder etwa doch?)
-
hustbaer schrieb:
dot schrieb:
hustbaer schrieb:
Und durchgängig auf SIMD arbeiten... können aktuelle Compiler keinen Code erzeugen der SSE2 auch für einzelne floats verwendet? Ich dachte nämlich dass die das können, und dann wäre es ziemlich schnuppe ... bzw. sogar besser wenn man einzelne floats nimmt wo man nur einzelne floats braucht.
Unter x64 kann man mehr oder weniger davon ausgehen, dass der Compiler auch für skalare Operationen SSE verwendet. Unter x86 nicht unbedingt, zumindest MSVC scheint mir dort immer noch zumindest meistens die FPU zu verwenden, vermutlich vor allem aus Kompatibilitätsgründen.
MSVC verwendet im x86 Mode SSE2 nur wenn man es ihm erlaubt. Hast du bei deinen Experimenten auch den nötigen Switch mitgegeben? Wäre dann schade, aber OK, wegen eines einzigen Compilers werd ich jetzt auch nicht Code schreiben der komisch riecht und auf anderen Compilern im Falle des Falles sogar langsamer ist.
MSVC < VS 2012 generiert auch mit /arch:SSE meiner Erfahrung nach sehr oft FPU Code und offenbar bin ich mit dieser Beobachtung nicht allein: http://www.zfx.info/viewtopic.php?f=4&t=2410&p=31678&hilit=arch%3ASSE#p31678
Es sieht so aus, als ob sich mit VS 2012 da was geändert hätte, vermutlich im Zuge der Einführung des Vectorizers...hustbaer schrieb:
hustbaer schrieb:
Und auf GPUs ist es ja, soweit ich weiss, auch mittlerweile zur Sünde geworden mehr Komponenten zu verwenden als man eigentlich braucht. Skalare Shader Units und so...
Oder hab' ich da was falsch mitbekommen?Auf NVIDIA Hardware >= GeForce 8 prinzipiell wohl ja, bei ATI schaut's dagegen anders aus, die verwenden afaik zumindest bis vor kurzem noch VLIW Vektorhardware, wobei iirc zumindest eine ihrer allerletzten Architekturen auch eher in die skalare Richtung ging...
Auch interessant, danke.
Wobei... wenn es auf NIVEA Karten pöse ist, dann ist es pöse und aus
(Und nicht pöse zu sein wird einem auf ATI Karten vermutlich auch keine Probleme machen, oder etwa doch?)Naja, ich denke, es wäre wohl sinnvoller, Code einfach vektoriell zu halten, wo es Sinn macht and ansonsten skalar. Vektorieller Code ist sicherlich leichter in skalaren Code zu transformieren als umgekehrt...
-
fuer msvc sind float-sse und intrinsic-sse register unterschiedliche dinge, meistens sehe ich store und loads der daten in ein und dasselbe register, nur weil es quasi einen context-switch im compiler gab.
erstaunlicherweise erkannte der compiler manchmal dass ich von einer vector operation nur ein splat gemacht habe und auf SIMD 4mal dasselbe berechnete und hat das eigenwillig auf float umgebogen, weil es theoretische weniger cycles braucht, aber bei vielen cpus das umschaltet doch penalty ist.