Toon posts:

[C#] Managed code te snel!?

Pagina: 1
Acties:
  • 309 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Hallo,

Ik ben aan het werk aan een klein bij-projectje voor mijn grote project (een RTS game in managed code, voor de lol, niks serieus op dit moment) en ben een beetje aan het benchmarken geweest in de richting van wiskunde en matrices...

Managed DirectX bevat classes voor matrices, vectors, quaternions en al dat soort spul en gebruikt intern d3dx om dat voor elkaar te krijgen. Mijn projectje moet natuurlijk op meerdere platformen kunnen draaien, maar wel zo snel mogelijk als dat kan (dus door gebruik te maken van de snelste libraries die er zijn voor dat platform). Nu heb ik een matrix vermenigvuldiging gebenchmarkt en ik krijg daar opmerkelijke resultaten uit...

De makkelijkste manier, via de methods op het MDX matrix object
code:
1
2
3
4
5
public bool Execute()
{
    o = Matrix.Multiply(m, n);
    return true;
}


................!
Took: 0h, 0m, 1.656s. for 8000000 iterations.
Iters per ms: 4830,18867924528 - Ms per iter: 0,00020703125

De iets minder makkelijke manier, via MDX' unsafe native methods:
code:
1
2
3
4
5
6
7
8
9
10
11
public bool Execute()
{
    unsafe
    {
        fixed (Matrix* pm = &m) fixed (Matrix* pn = &n) fixed (Matrix* po = &o)
        {
            UnsafeNativeMethods.Matrix.Multiply(po, pm, pn);
        }
    }
    return true;
}


................!
Took: 0h, 0m, 0.750s. for 8000000 iterations.
Iters per ms: 10666,6666666667 - Ms per iter: 9,375E-05

En de .net manier, met een heel simpel matrix classje wat ik in elkaar gedraaid heb:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public bool Execute()
{
    Multiply(ref o, ref m, ref n);
    return true;
}

private void Multiply(ref DNMatrix o, ref DNMatrix m, ref DNMatrix n)
{
    o.m11 = m.m11 * n.m11 + m.m12 * n.m21 + m.m13 * n.m31 + m.m14 * n.m41;
    o.m12 = m.m11 * n.m12 + m.m12 * n.m22 + m.m13 * n.m32 + m.m14 * n.m42;
    o.m13 = m.m11 * n.m13 + m.m12 * n.m23 + m.m13 * n.m33 + m.m14 * n.m43;
    o.m14 = m.m11 * n.m14 + m.m12 * n.m24 + m.m13 * n.m34 + m.m14 * n.m44;
    o.m21 = m.m21 * n.m11 + m.m22 * n.m21 + m.m23 * n.m31 + m.m24 * n.m41;
    o.m22 = m.m21 * n.m12 + m.m22 * n.m22 + m.m23 * n.m32 + m.m24 * n.m42;
    o.m23 = m.m21 * n.m13 + m.m22 * n.m23 + m.m23 * n.m33 + m.m24 * n.m43;
    o.m24 = m.m21 * n.m14 + m.m22 * n.m24 + m.m23 * n.m34 + m.m24 * n.m44;
    o.m31 = m.m31 * n.m11 + m.m32 * n.m21 + m.m33 * n.m31 + m.m34 * n.m41;
    o.m32 = m.m31 * n.m12 + m.m32 * n.m22 + m.m33 * n.m32 + m.m34 * n.m42;
    o.m33 = m.m31 * n.m13 + m.m32 * n.m23 + m.m33 * n.m33 + m.m34 * n.m43;
    o.m34 = m.m31 * n.m14 + m.m32 * n.m24 + m.m33 * n.m34 + m.m34 * n.m44;
    o.m41 = m.m41 * n.m11 + m.m42 * n.m21 + m.m43 * n.m31 + m.m44 * n.m41;
    o.m42 = m.m41 * n.m12 + m.m42 * n.m22 + m.m43 * n.m32 + m.m44 * n.m42;
    o.m43 = m.m41 * n.m13 + m.m42 * n.m23 + m.m43 * n.m33 + m.m44 * n.m43;
    o.m44 = m.m41 * n.m14 + m.m42 * n.m24 + m.m43 * n.m34 + m.m44 * n.m44;
}


................!
Took: 0h, 0m, 0.750s. for 8000000 iterations.
Iters per ms: 10666,6666666667 - Ms per iter: 9,375E-05
(nee, dit is geen copy/paste fout)

Mijn vraag is nu, gezien deze resultaten, ben ik iets verkeerd aan het doen met de managed directx calls? Een heel eenvoudige implementatie in .net lijkt haast net zo snel te zijn als gebruik maken van de geoptimaliseerde d3dx calls. Ik had verwacht dat de .net code toch wel iets langzamer zou zijn...

Verwijderd

1) Is de MDX een wrapper voor unmanaged DX; waardoor er mogelijk wat vertraging in zit? Bijvoorbeeld door conversie van datastructuren.
2) Misschien zit er een optimalisatie in om een optimale nesting te krijgen van matrices? Dit is overigens zeer onwaarschijnlijk bij meerdere procedurecalls...

[ Voor 66% gewijzigd door Verwijderd op 27-06-2006 12:18 ]


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 15:23

Gerco

Professional Newbie

Die managed code van jou wordt natuurlijk meteen geJIT naar native code en aangezien de code nogal erg simpel is, kan hij erg goed geoptimaliseerd worden. Ik denk dat MDX/DX hetzelfde doen en dat het dus even snel draait.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Topicstarter
MDX is een wrapper rond de native direct X componenten. Ik heb met reflector aan de binnenkant van de matrix code gekeken en zo weet ik dat de MDX wrapper gebruik maakt van d3dx (de direct 3d utility library) voor z'n matrix operaties.
De matrix struct die gedefinieerd wordt in de managed wrapper is 1-op-1 hetzelfde als DirectX' eigen matrix struct, dus van een conversie is geen sprake in dit geval.

Dit geldt bijna overal in managed directx... het is echt een minuscuul dunne wrapper rond de native directx componenten. Het is dus redelijk aan te nemen dat de meeste tijd in native code wordt doorgebracht. Voor mijn .net matrix classje geldt dat natuurlijk niet, en lijkt de JIT compiler wel heel erg goed z'n best te doen...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Gerco schreef op dinsdag 27 juni 2006 @ 12:17:
Die managed code van jou wordt natuurlijk meteen geJIT naar native code en aangezien de code nogal erg simpel is, kan hij erg goed geoptimaliseerd worden. Ik denk dat MDX/DX hetzelfde doen en dat het dus even snel draait.
d3dx zal SSE muls gebruiken, ik vraag me af of de jitter slim genoeg is om het ook naar SSE instructies te compileren.

Het zou natuurlijk wel kunnen, maar ik denk dat de fout ergens anders ligt, namelijk bij de verkeerde aannames die vaak gedaan worden bij benchmarks. Dat iets snel performt, zeker in een VM, wil helemaal niet zeggen dat je code snel is of naar snelle machine-code wordt geJIT. Er zijn duizenden factoren die invloed kunnen hebben op hoe snel iets performt, waarvan cache, globale cpu load en VM optimalisaties de belangrijksten zijn. Wellicht ziet de VM dat je helemaal niets met het resultaat doet, waardoor er gewoon eigenlijk niets uitgevoerd wordt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

(Ik werk samen met Qlone aan dit projectje)
.oisyn schreef op dinsdag 27 juni 2006 @ 12:47:
[...]

d3dx zal SSE muls gebruiken, ik vraag me af of de jitter slim genoeg is om het ook naar SSE instructies te compileren.
Ik zal zo 'ns met een assembly-level debugger proberen na te gaan of dat in beide gevallen het geval is.

Op zich zijn onze resultaten niet heel vreemd te noemen overigens. Ik heb een linpack benchmark gevonden waarin .net 1.1 toch wel hele mooie resultaten haalt tegenover C++. Wij gebruiken .net 2.0, dus die zou alleen maar sneller moeten zijn.
Wellicht ziet de VM dat je helemaal niets met het resultaat doet, waardoor er gewoon eigenlijk niets uitgevoerd wordt.
Daar heb je wel een punt. Om jouw hypothese te testen heb ik voor alle tests de code veranderd naar de volgende operatie (pseudo-code):
code:
1
2
o = m * n;
m = o * n;

Dat zou d'r voor moeten zorgen dat onze multiplicatie niet weggeoptimaliseerd wordt. Ook heb ik 't aantal tests verdubbeld, om te compenseren voor beperkte timer-resolutie. Het resultaat is als volgt (op m'n Athlon64 1,8GHz/1GB RAM):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
D3DXSafe:
Took: 0h, 0m, 5.0s. for 16000000 iterations.
Iters per ms: 3200 - Ms per iter: 0,0003125

D3DXNative:
Took: 0h, 0m, 3.171s. for 16000000 iterations.
Iters per ms: 5044,33497536946 - Ms per iter: 0,0001982421875

DotNetNative:
Took: 0h, 0m, 2.453s. for 16000000 iterations.
Iters per ms: 6522,29299363057 - Ms per iter: 0,0001533203125

DotNetNativeStatic:
Took: 0h, 0m, 2.375s. for 16000000 iterations.
Iters per ms: 6736,84210526316 - Ms per iter: 0,0001484375

(DotNetNativeStatic is overigens DotNetNative maar dan met een static Multiply() method)

Nu is .net code ineens consequent een flink stuk sneller dan d3dx aanroepen.

Mijn theorie is dat de .net jit-compiler zelf ook best fancy vectorisatie doet, en daarbij rekening houdt met de processor waarop 't geheel draait (wat voor iets statisch gecompileerds als d3dx natuurlijk niet kan). Dat is de enige manier waarop kan verklaren dat .net sneller is dan d3dx op m'n Athlon64.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 15:23

Gerco

Professional Newbie

Ik ben er niet helemaal van overtuigd dat je multiplicatie niet weggeoptimaliseerd wordt door die twee vermenigvuldigingen eigenlijk. Er staat me iets bij dat de .NET compiler erg slim is in dit soort dingen. Kijk anders eens met reflector in je assembly of je multiplicaties aanwezig zijn in de IL.

Misschien is het nog beter om een dummy functie in een andere assembly aan te roepen met je resultaatmatrix, dan lijkt het me wel heel erg sterk dat het nog weggeoptimized kan worden.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Gerco schreef op dinsdag 27 juni 2006 @ 13:23:
Er staat me iets bij dat de .NET compiler erg slim is in dit soort dingen. Kijk anders eens met reflector in je assembly of je multiplicaties aanwezig zijn in de IL.
Maar alle optimalisatie in .net vindt run-time plaats. De C# compiler is een heel simpel geval wat vrij ongeoptimaliseerde IL genereerd.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 15:23

Gerco

Professional Newbie

Dan kun je helaas niet met reflector kijken, jammer, want het zou wel handig geweest kunnen zijn :) MS geeft nogal hoog op van hun JITer/compiler als ik het me goed herinner, dus ik zou het niet geheel onwaarschijnlijk vinden als hij je truuckje doorziet.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Topicstarter
Gerco schreef op dinsdag 27 juni 2006 @ 13:23:
Ik ben er niet helemaal van overtuigd dat je multiplicatie niet weggeoptimaliseerd wordt door die twee vermenigvuldigingen eigenlijk. Er staat me iets bij dat de .NET compiler erg slim is in dit soort dingen. Kijk anders eens met reflector in je assembly of je multiplicaties aanwezig zijn in de IL.

Misschien is het nog beter om een dummy functie in een andere assembly aan te roepen met je resultaatmatrix, dan lijkt het me wel heel erg sterk dat het nog weggeoptimized kan worden.
In de reflector is alle code aanwezig voor de multiply. Het lijkt er op dat die dus inderdaad uitgevoerd wordt.

Als ik vanavond tijd heb zal ik de test eens uitbreiden met wat extra berekeningen om zo te kijken of er grotere verschillen optreden.

Verwijderd

Topicstarter
Gerco schreef op dinsdag 27 juni 2006 @ 13:31:
Dan kun je helaas niet met reflector kijken, jammer, want het zou wel handig geweest kunnen zijn :) MS geeft nogal hoog op van hun JITer/compiler als ik het me goed herinner, dus ik zou het niet geheel onwaarschijnlijk vinden als hij je truuckje doorziet.
Maar... de benchmark is snel uitgebreid met een lege implementatie van dezelfde class. Daarmee is meteen de overhead van het framework om de matrix vermenigvuldigingen heen te meten. Dan komt er het volgende uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Benchmarking: MathPerf.NoImplementation
Initializing...
... succes.
................................!
Took: 0h, 0m, 0.312s. for 16000000 iterations.
Iters per ms: 51200 - Ms per iter: 1,953125E-05
................................!
Took: 0h, 0m, 0.203s. for 16000000 iterations.
Iters per ms: 78769,2307692308 - Ms per iter: 1,26953125E-05


Benchmarking: MathPerf.D3DXNative
Initializing...
... succes.
................................!
Took: 0h, 0m, 1.500s. for 16000000 iterations.
Iters per ms: 10666,6666666667 - Ms per iter: 9,375E-05
................................!
Took: 0h, 0m, 1.484s. for 16000000 iterations.
Iters per ms: 10778,9473684211 - Ms per iter: 9,27734375E-05

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 15:23

Gerco

Professional Newbie

hm, ik ben natuurlijk geen expert op dit gebied, maar het lijkt wel alsof .net echt sneller is dan native DirectX. Nu heb ik dit soort benchmarks ook weleens van Java / C++ gezien, maar die werden dan direct met hoongelach begroet en van scheef testen beschuldigd.

Zou het dan echt zo zijn dat managed code (goed gejit) sneller is dan precompiled native code? Trouwens vreemd dat DirectXNative deze keer andere cijfers geeft dan vorige keer? Eerst 5k per iter en nu 10+k ??

[ Voor 15% gewijzigd door Gerco op 27-06-2006 13:46 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 27 juni 2006 @ 13:20:
Daar heb je wel een punt. Om jouw hypothese te testen heb ik voor alle tests de code veranderd naar de volgende operatie (pseudo-code):
code:
1
2
o = m * n;
m = o * n;
Dat zal niet helpen. Als de compiler slim genoeg is om te zien dat die multiply niets doet, zal hij ook zien dat bovenstaande code geen interessante side-effects heeft die de rest van je programma kan beïnvloeden. Je zal echt iets met het resultaat moeten doen - accumuleer bijvoorbeeld eens alle floats in de matrix naar een global en print die op het eind. Dit maakt het geheel wel ietwat langzamer, maar als je het voor alle benchmarks doet zou dat niet uit moeten maken.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
[b][message=26030121,noline]Eerst 5k per iter en nu 10+k ??
Dat komt omdat zowel tabsels als ik een iets andere versie van de benchmark hebben (mijne doet nog niet het heen-en-weer multiplyen waar tabsels het net over had), dus de resultaten zouden ongeveer 2x zo hoog moeten liggen. En mijn hardware hier is iets anders (pentium-m@2Ghz)...

Verwijderd

Zou het kunnen zijn dat de unmanaged C(++) code niet gecompileerd is met /Ox opties? Dit kan namelijk bijzonder veel schelen. Overigens heeft C# ook zo'n optie voor z'n compiler.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

d3dx is een al gecompileerde library, geen custom C++ code die je nog moet compileren :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op dinsdag 27 juni 2006 @ 13:46:
[...]

Dat zal niet helpen. Als de compiler slim genoeg is om te zien dat die multiply niets doet, zal hij ook zien dat bovenstaande code geen interessante side-effects heeft die de rest van je programma kan beïnvloeden. Je zal echt iets met het resultaat moeten doen - accumuleer bijvoorbeeld eens alle floats in de matrix naar een global en print die op het eind.
Ik heb de volgende code toegevoegd aan elk van de tests:
C#:
1
2
3
4
sum+=m.M11+m.M12+m.M13+m.M14+
    m.M21+m.M22+m.M23+m.M24+
    m.M31+m.M32+m.M33+m.M34+
    m.M41+m.M42+m.M43+m.M44;

Ik krijg hiermee de volgende resultaten:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
D3DXSafe:
Took: 0h, 0m, 5.671s. for 16000000 iterations.
Iters per ms: 2820,93663911846 - Ms per iter: 0,0003544921875
Sum is 3,60288E+16

D3DXNative:
Took: 0h, 0m, 3.218s. for 16000000 iterations.
Iters per ms: 4970,87378640777 - Ms per iter: 0,000201171875
Sum is 3,60288E+16

DotNetNative:
Took: 0h, 0m, 2.937s. for 16000000 iterations.
Iters per ms: 5446,8085106383 - Ms per iter: 0,00018359375
Sum is 3,60288E+16

DotNetNativeStatic:
Took: 0h, 0m, 3.15s. for 16000000 iterations.
Iters per ms: 5305,69948186528 - Ms per iter: 0,0001884765625
Sum is 3,60288E+16

(Voor degenen die hier meerekenen: ik doe altijd 2 passes en post 't resultaat van de 2de pass. De sum wordt echter voor beide passes berekend)

Wat overigens wel vreemd is is dat DotNetNativeStatic hierbij consequent trager is dan DotNetNative.
Dit maakt het geheel wel ietwat langzamer, maar als je het voor alle benchmarks doet zou dat niet uit moeten maken.
Nou, wat hier wel bijgezegd moet worden is dat voor d3dx de matrix-velden via properties gelezen worden, terwijl voor de .net-native code direct de variabelen worden uitgelezen. Maar ik denk dat dat allemaal weinig uitmaakt.

Ik kan helaas niet controleren wat voor code de JIT-compiler genereerd (dat snapt visual c# express edition niet), maar gezien de resultaten moet ik aannemen dat 'ie d'r iets heel behoorlijks van maakt, vergelijkbaar met de d3dx code (en waarschijnlijk dus gevectoriseerd). De verschillen tussen D3DXNative en DotNetNative/DotNetNativeStatic zijn waarschijnlijk te verklaren door de overhead die een library call onder win32 geeft.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het pinnen van de pointers en de unsafe context zal ook wel wat overhead met zich meebrengen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:55
Wat ik vooral raar vind is dat DXNative zo veel sneller is dan DXSafe; als ik het verhaal goed begrijp zouden die dezelfde functie moeten aanroepen? Misschien dat er in het eerste geval ergens gesynchroniseerd moet worden, wat natuurlijk funest is voor zo'n snelle functieaanroep.

Is het overigens zo dat die DirectX functie willekeurige matrices accepteert? Dan verbaast het me helemaal niets dat je handmatig ge-unrollde code voor 4x4 matrices sneller is. De functie voor algemene matrices is veel complexer, zeker als 'ie Strassen's algoritme toepast.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een d3dx functie wil 4x4 16byte aligned matrices ;). Het is een d3d functie, daar heb je over het algemeen geen algemene matrixfunctionaliteit voor nodig.

[ Voor 51% gewijzigd door .oisyn op 27-06-2006 17:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Soultaker schreef op dinsdag 27 juni 2006 @ 17:23:
Wat ik vooral raar vind is dat DXNative zo veel sneller is dan DXSafe; als ik het verhaal goed begrijp zouden die dezelfde functie moeten aanroepen? Misschien dat er in het eerste geval ergens gesynchroniseerd moet worden, wat natuurlijk funest is voor zo'n snelle functieaanroep.
Met reflector kijken in de managed directx wrapper levert het volgende op.
Dit is de aanroep in 'DXSafe':
C#:
1
2
3
4
5
6
7
public static unsafe Matrix Multiply(Matrix left, Matrix right)
{
      Matrix matrix1 = new Matrix();
      matrix1 = new Matrix();
      D3DXMatrixMultiply((D3DXMATRIX*) &matrix1, (D3DXMATRIX modopt(IsConstModifier)*) &left, (D3DXMATRIX modopt(IsConstModifier)*) &right);
      return matrix1;
}


Dit is de unsafe aanroep intern:
C#:
1
2
3
4
5
[CLSCompliant(false)]
public static unsafe Matrix* Multiply(Matrix* pOut, Matrix* left, Matrix* right)
{
      return D3DXMatrixMultiply((D3DXMATRIX*) pOut, (D3DXMATRIX modopt(IsConstModifier)*) left, (D3DXMATRIX modopt(IsConstModifier)*) right);
}


Het in-place werken van de unsafe aanroep en het niet 'new'-en van een matrix object zal best wat performance schelen. En het voorkomt onnodige belasting van de garbage collector.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een matrix is toch gewoon een struct, geen class? Dus er hoeft niets genewd te worden, het is gewoon een kwestie van je data initialiseren (en waarschijnlijk gebeurt er niets in de constructor omdat je floats al met 0.f worden geinitialiseerd)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op dinsdag 27 juni 2006 @ 18:00:
Een matrix is toch gewoon een struct, geen class? Dus er hoeft niets genewd te worden, het is gewoon een kwestie van je data initialiseren (en waarschijnlijk gebeurt er niets in de constructor omdat je floats al met 0.f worden geinitialiseerd)
Maar d'r moet wel geheugen voor gealloceerd worden. Da's nog best een dure operatie om 8 of 16 miljoen keer te doen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, structs staan op de stack. Dat was juist m'n hele punt :)
(of denk je dat elke int die je gebruikt ook gealloceerd wordt met een dure heap operatie?)

[ Voor 80% gewijzigd door .oisyn op 27-06-2006 18:52 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op dinsdag 27 juni 2006 @ 18:51:
Nee, structs staan op de stack. Dat was juist m'n hele punt :)
(of denk je dat elke int die je gebruikt ook gealloceerd wordt met een dure heap operatie?)
Als je C# niet snapt, waarom reageer je hier dan?

Ik stel voor dat je de definitie van new nog 'ns naleest. En dan eens goed kijkt naar de code die Qlone hierboven pastte.

[ Voor 28% gewijzigd door Verwijderd op 27-06-2006 19:24 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:55
@Tabsels: wat wil je nu precies stellen? Dat value types (zoals structs) wél op de heap gealloceerd worden? Dat is niet zo, zoals op de pagina die je zelf net aanhaalt ook staat:
Value-type objects such as structs are created on the stack, while reference-type objects such as classes are created on the heap.

.oisyn schreef op dinsdag 27 juni 2006 @ 17:32:
Een d3dx functie wil 4x4 16byte aligned matrices ;). Het is een d3d functie, daar heb je over het algemeen geen algemene matrixfunctionaliteit voor nodig.
Ah, my bad. (Dat bleek niet echt uit de code.)
Het in-place werken van de unsafe aanroep en het niet 'new'-en van een matrix object zal best wat performance schelen. En het voorkomt onnodige belasting van de garbage collector.
Als het inderdaad zo is dat in het eerste geval de argumenten/return values heen en weer gekopieerd worden en in de andere gevallen niet, dan zou dat een goede verklaring zijn. Maar het verklaart die keuze van de compiler nog niet.

[ Voor 22% gewijzigd door Soultaker op 27-06-2006 19:39 ]


Verwijderd

Soultaker schreef op dinsdag 27 juni 2006 @ 19:38:
@Tabsels: wat wil je nu precies stellen? Dat value types (zoals structs) wél op de heap gealloceerd worden? Dat is niet zo, zoals op de pagina die je zelf net aanhaalt ook staat:

[...]
Oeps, sorry, iets te snel geflamed. Had even een (slechte) flashback naar 'n keer dat ik iemand een half uur lang de and-operator heb moeten uitleggen.

Maar of 't new'en van een struct (en Microsoft.DirectX.Matrix is dat idd., nog even nagegaan) nu wel of niet resulteert in een allocatie op de heap, 't moge duidelijk zijn dat 't trager is dan alles in-place doen.
Als het inderdaad zo is dat in het eerste geval de argumenten/return values heen en weer gekopieerd worden en in de andere gevallen niet, dan zou dat een goede verklaring zijn. Maar het verklaart die keuze van de compiler nog niet.
Wat ik overigens wel vreemd vind: Ik zie twee new's staan, waarbij het resultaat van de eerste wordt weggegooit. Dus ofwel de decompiler is niet helemaal lekker, ofwel dat managed directx is wel erg slordig in elkaar gegooit.

Verwijderd

Topicstarter
Soultaker schreef op dinsdag 27 juni 2006 @ 19:38:
Als het inderdaad zo is dat in het eerste geval de argumenten/return values heen en weer gekopieerd worden en in de andere gevallen niet, dan zou dat een goede verklaring zijn. Maar het verklaart die keuze van de compiler nog niet.
Al met al vond ik de resultaten verrassend genoeg om er een topicje over te openen :) .

Het is goed om te weten dat ik zo op het eerste gezicht niet iets enorm fout aan het doen ben, wat het performance verschil in dit geval zou veroorzaken. In dat opzicht ben ik dus al enorm geholpen met alle bovenstaande reakties :) .

Ook geven deze eerste benchmark resultaten me een beetje hoop dat het hele project misschien gewoon haalbaar blijkt qua performance. (Al zal ik vast nog wel een paar valkuilen tegen komen die leiden tot topic met de titel '[C#] Managed code veel te langzaam!?', maar dat zien we dan wel :) )

@tabsels: .oisyn begrijpt C# wel degelijk. Er zijn er maar een paar op dit forum wiens posts ik bijna zondermeer voor waar aan neem, en .oisyn is daar 1 van...

Verwijderd

Topicstarter
Verwijderd schreef op dinsdag 27 juni 2006 @ 19:52:
Wat ik overigens wel vreemd vind: Ik zie twee new's staan, waarbij het resultaat van de eerste wordt weggegooit. Dus ofwel de decompiler is niet helemaal lekker, ofwel dat managed directx is wel erg slordig in elkaar gegooit.
De decompiler van reflector is niet in staat alles wat je in IL code kan uitdrukken terug om te zetten naar geldige C#. De werkelijke IL code reserveert ruimte voor een matrix en roept daarna expliciet z'n constructor aan. Dat wordt kennelijk vertaald naar 2 new statements...

Hij is echter zondermeer wel goed genoeg om te kijken wat er ongeveer onder de kap gebeurt in managed directx, en wat ik tot nog toe gezien heb ziet er gewoon goed uit. Het is een redelijke no-nonsense wrapper rond de 'echte' DX9 API's.

Verwijderd

Verwijderd schreef op dinsdag 27 juni 2006 @ 20:00:
.oisyn begrijpt C# wel degelijk. Er zijn er maar een paar op dit forum wiens posts ik bijna zondermeer voor waar aan neem, en .oisyn is daar 1 van...
Weet ik veel dat microsoft leugens in z'n documentatie verstopt. Eerst vertellen ze vrolijk dat new op de heap alloceert, en midden in de tekst beginnen ze over structs en andere 'value types' die daar dan weer een uitzondering op vormen...

@.oisyn: sorry dat ik zo snel uit m'n slof schoot. Ik had niet moeten aannemen dat C# net zoals Java werkt (en ik had wat meer geduld moeten tonen).

[ Voor 7% gewijzigd door Verwijderd op 27-06-2006 20:14 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 27 juni 2006 @ 20:12:
Weet ik veel dat microsoft leugens in z'n documentatie verstopt. Eerst vertellen ze vrolijk dat new op de heap alloceert
Ik denk dat je die documentatie ietwat verkeerd interpreteert. Er staat
The new operator is used to create objects and invoke constructors
En dat is zonder meer waar. De new operator wordt gebruikt om objecten op de heap te alloceren, en ook om constructors aan te roepen. Er staat nergens dat het altijd beide doet :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Helemaal bovenaan in dat document (bold tags door mij toegevoegd):
In C#, the new keyword can be used as an operator or as a modifier.
  • new operator: Used to create objects on the heap and invoke constructors.
  • new modifier: Used to hide an inherited member from a base class member.
Even later lees ik inderdaad:
It is also used to invoke the default constructor for value types, for example:
C#:
1
int myInt = new int();
Ik ben (wat OO-talen betreft) C++ en Java gewend, en dan is dat toch wel erg verwarrend. Onder C++ roep je constructoren van on-stack variabelen (zoals ongetwijfeld bekend) als volgt aan:
C++:
1
Foo blaat(42);

En onder Java zijn scalars by-value en objecten by-reference en is new enkel verantwoordelijk voor de heap-allocatie van objecten (de 'gebruikelijke' manier).

Het type-systeem van Java is bizar (imnsho), maar dat van C# is vooral door dit soort hergebruik van taalconstructies niet veel duidelijker. Vandaar de verwarring.

[ Voor 3% gewijzigd door Verwijderd op 27-06-2006 22:34 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

My bad, ik copypastte de verkeerde regel. Ik bedoelde idd dat stukje waar "on the heap" bij staat. Mijn punt blijft staan. Laten we echter niet verzanden in technicalities, dat is niet interessant ;)

Als C++ zealot heb ik me altijd al geërgerd aan Java, juist met name als ik met computer graphics gerelateerde zaken bezig was. Ik had een eigen Vector en Matrix klasse, maar wat performance betreft is het een ramp om die steeds te newen elke keer als je een nieuwe berekening doet. Uiteindelijk ga je daar omheen werken door grote pools met van tevoren gealloceerde objecten op te zetten, allerminst een prettig werkbare situatie. Ik was dan ook blij om te horen dat .Net wel value-type objects ging ondersteunen, en wat dat betreft heeft .Net ook echt een streepje voor op Java.

Maar niets kan tippen aan C++ though ;), als ik iets voor het .Net platform moet ontwikkelen kies ik voor C++/CLI

[ Voor 7% gewijzigd door .oisyn op 27-06-2006 22:41 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Dat je new kunt gebruiken voor value types is inderdaad verwarrend, maar als ik het goed heb is dat een bijwerking van de impliciete boxing/unboxing die C# aanbiedt. In C# wordt een value type als een object behandeld als het een object moet zijn en als een value type als het een value type moet zijn. Keerzijde van de medaille is dat boxing/unboxing kan leiden tot performance issues die vrij lastig op te sporen zijn, als je werkt met Arraylists bijvoorbeeld.
Ik was dan ook blij om te horen...
Vergeet de out parameters niet ;)

Verwijderd

.oisyn schreef op dinsdag 27 juni 2006 @ 22:39:
Ik was dan ook blij om te horen dat .Net wel value-type objects ging ondersteunen, en wat dat betreft heeft .Net ook echt een streepje voor op Java.
Maar wat dus blijkt is dat operands by-reference doorgeven toch alsnog sneller is (DXSafe vs. DXNative). Nu ik doorheb hoe dat onder C# zit vind ik dat toch wel erg vreemd.

Ik zit trouwens nog steeds te wachten op een taal die gewoon alles by-value doet (semantisch gezien dan) en in de achtergrond netjes autoboxing en dergelijke voor je doet (zeg maar zoals PHP maar dan wel vooruit te branden).
Maar niets kan tippen aan C++ though ;), als ik iets voor het .Net platform moet ontwikkelen kies ik voor C++/CLI
Als UNIX-zeloot laat ik me zelden waarderend uit over Redmondiaanse waren, maar ik vind C# toch wel een stuk minder rommelig dan C++. Maargoed, da's een kwestie van smaak. :)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

websjwans: Ik denk niet dat het met boxing te maken heeft, maar gewoon met het feit dat ze een eenduidige syntax willen hebben om objecten te construeren (of dat nou op de heap of op de stack is). Vooral in generic types of functies is dit uiteraard nodig, omdat je anders nooit een object goed kunt initialiseren zonder je implementatie te binden aan óf classes óf structs.

De verwarring komt van het feit dat in C++ en Java new altijd wordt gebruikt om een object op de heap te alloceren (niet helemaal waar overigens, zie de placement new van C++, maar dat is iets voor gevorderden). Maar feitelijk is waar het object geconstrueerd wordt natuurlijk helemaal niet inherent aan het new keyword, het zegt slechts dat er een nieuwe instance gemaakt moet worden, ongeacht waar hij staat.
Verwijderd schreef op dinsdag 27 juni 2006 @ 23:14:

Maar wat dus blijkt is dat operands by-reference doorgeven toch alsnog sneller is (DXSafe vs. DXNative).
Logisch, het scheelt het maken van een kopie. Zeker voor matrices is dat belangrijk, want die is minstens 16*sizeof(float) = 64 bytes groot. Het is niet voor niets dat je dergelijke objecten in C++ beter als const reference kunt passen :)
Als UNIX-zeloot laat ik me zelden waarderend uit over Redmondiaanse waren
Toch jammer dat je niet voorbij die barrière kunt kijken. Je hoeft het niet eens te zijn met hun business model, maar dat is nog geen reden om een product niet te kunnen waarderen :) (het komt een beetje over als: het is van MS, dus is het slecht. En dat is, quite frankly, niet erg rationeel :))

[ Voor 36% gewijzigd door .oisyn op 27-06-2006 23:26 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 19:55

RayNbow

Kirika <3

Verwijderd schreef op dinsdag 27 juni 2006 @ 22:33:
En onder Java zijn scalars by-value en objecten by-reference en is new enkel verantwoordelijk voor de heap-allocatie van objecten (de 'gebruikelijke' manier).
Slightly off-topic, maar goed...
Object-variabelen zijn referenties, maar ze worden (de referenties) by value doorgegeven in Java. (info)
Verder hoeft new de objecten niet op de heap te zetten. (Toekomstige) JVMs kunnen objecten ook aanmaken op de stack als ze dat willen en slim achten.

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Verwijderd

Ik denk niet dat het met boxing te maken heeft, maar gewoon met het feit dat ze een eenduidige syntax willen hebben om objecten te construeren (of dat nou op de heap of op de stack is). Vooral in generic types of functies is dit uiteraard nodig, omdat je anders nooit een object goed kunt initialiseren zonder je implementatie te binden aan óf classes óf structs.
Waarschijnlijk heb je gelijk (ja, dat kostte moeite :p). Ik zat er net wat mee te rommelen en int i = new int(); werkt ook in .NET 1.1, dus het zal wel een of andere vage syntax afspraak zijn. Het int type heeft geen constructor, dus new int(0) werkt niet en .NET 1.1 heeft geen generics, dus het lijkt een beetje nutteloos. De enige reden die ik ervoor kan bedenken zou inderdaad zijn om het voor alle value types consistent te houden, aangezien je voor structs wel gewoon 'constructors' kan definieren.
Ik zit trouwens nog steeds te wachten op een taal die gewoon alles by-value doet (semantisch gezien dan) en in de achtergrond netjes autoboxing en dergelijke voor je doet (zeg maar zoals PHP maar dan wel vooruit te branden).
Bedoel je implicit typing zoals in C# 3.0, of dat alles achter de schermen ook echt by-value wordt gepasst?

Verwijderd

.oisyn schreef op dinsdag 27 juni 2006 @ 23:18:
[...]

Toch jammer dat je niet voorbij die barrière kunt kijken. Je hoeft het niet eens te zijn met hun business model, maar dat is nog geen reden om een product niet te kunnen waarderen :) (het komt een beetje over als: het is van MS, dus is het slecht. En dat is, quite frankly, niet erg rationeel :))
Oh, ik heb an-sich weinig problemen met Microsoft spul. Ik vind UNIX alleen fijner werken. Simpeler, hackbaarder, makkelijker om als geavanceerde gebruiker of programmeur mee te werken (omdat je niet zo beperkt wordt door 'n voorbedachte GUI en binaire configuratiebestanden). En dat vrijheids-ideaal spreekt me ook erg aan.

Maar dat ik nu achter een Windows bak zit en met C#/.net werk lijkt me genoeg bewijs dat ik wel voorbij die barrière kan kijken. :)

Verwijderd schreef op dinsdag 27 juni 2006 @ 23:44:
Bedoel je implicit typing zoals in C# 3.0, of dat alles achter de schermen ook echt by-value wordt gepasst?
Gewoon alles semantisch by-value. Hoe dat in machinecode wordt uitgedrukt zal me 'n zorg wezen, als 't maar enigszins vlot is. Voor simpele objecten zou ik me allocatie op de stack kunnen voorstellen, en voor complexere objecten iets met reference counting.

[ Voor 22% gewijzigd door Verwijderd op 27-06-2006 23:48 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22:55
Verwijderd schreef op dinsdag 27 juni 2006 @ 23:14:
Ik zit trouwens nog steeds te wachten op een taal die gewoon alles by-value doet (semantisch gezien dan) en in de achtergrond netjes autoboxing en dergelijke voor je doet (zeg maar zoals PHP maar dan wel vooruit te branden).
Gebruik je nu PHP en netjes in één zin? :o (Verder heeft PHP wel references en - nog veel 'erger' - globale variabelen.)

Side-effects zijn een essentieel onderdeel van OOP (het idee is immers dat objecten zinnige entiteiten representeren en als die entiteiten veranderen, moet ook de toestand van een object veranderen) en daar horen references (in een of andere vorm) bij. Als je side-effect vrij wil programmeren kun je eens naar functionele talen kijken. Dan heb je echt uitsluitend 'waarden' (/objecten die niet gewijzigd kunnen worden) tot je beschikking.
Als UNIX-zeloot laat ik me zelden waarderend uit over Redmondiaanse waren, maar ik vind C# toch wel een stuk minder rommelig dan C++. Maargoed, da's een kwestie van smaak. :)
Mwah, dat is gewoon zo, maar C# had dan ook hele andere ontwerpdoelen dan C++. Logisch dat als je geen compatibiliteit met C nastreeft, je je beperkt tot een enkel paradigma (OOP) en platform (CLR), en je bereid bent om performance te laten liggen, je je taal een stuk simpeler kunt maken. Dat gold ook al voor Java trouwens. Het gevolg is dat talen als C# en Java inderdaad simpeler en uniformer zijn, maar niet zo breed toepasbaar als C++.

[ Voor 5% gewijzigd door Soultaker op 28-06-2006 00:04 ]


  • Vedett.
  • Registratie: November 2005
  • Laatst online: 23:05
Er is hier al aangehaald dat je met reflector niets bent omdat je naar de JIT-compilede code moet kunnen kijken. Voor zover ik weet kan je met Ngen.exe een native image maken van een dll.
http://msdn2.microsoft.com/en-us/library/6t9t5wcf.aspx
Ngen.exe creates native images, which are files containing compiled processor-specific machine code
Ik weet niet of er ook een reflector achtige tool bestaat voor deze images. Vrees eigenlijk van niet. Maar als je verder wilt kijken dan enkel IL code, is dit misschien wel iets.

  • misfire
  • Registratie: Maart 2001
  • Laatst online: 12-10-2024
Klinkt als een typisch geval van micro-benchmarking. In de situatie die je nu beschrijft is "pure" .NET sneller dan de managed/unmanaged mengelmoes van DirectX.NET, omdat je geen extra marshalling stappen hebt, pinnen van geheugen, enz. Het is geen vergelijking met native DirectX, maar meer de extra overheid die de interop veroorzaakt.

Dit wil echter niet zeggen dat ze bij DirectX.NET hier niet over nagedacht zouden hebben. Wellicht is het performance verschil zo minimaal (matrices berekenen is in de grand scheme niet echt de duurste actie) dat ze het niet herschreven in .NET, misschien zijn er gevallen die wel sneller zijn op de huidige manier, wellicht in combinatie met andere DirectX functie-calls.

Ik zou het nog eens proberen als je echt een volledige render-pass hebt geïmplementeerd om te kijken waar de bottlenecks zitten en hoe je die zelf kunt optimaliseren. Het is dan handig om eerst te meten (met bijv. CLR Profiler) waar de échte pijnpunten zitten. Bij een micro-benchmark heb je al snel dat je appels en peren aan het vergelijken bent, in het grote geheel kan er te veel anders zijn om hier echt iets mee te kunnen.

Verwijderd

misfire schreef op woensdag 28 juni 2006 @ 10:24:
Klinkt als een typisch geval van micro-benchmarking. In de situatie die je nu beschrijft is "pure" .NET sneller dan de managed/unmanaged mengelmoes van DirectX.NET, omdat je geen extra marshalling stappen hebt, pinnen van geheugen, enz. Het is geen vergelijking met native DirectX, maar meer de extra overheid die de interop veroorzaakt.

Dit wil echter niet zeggen dat ze bij DirectX.NET hier niet over nagedacht zouden hebben. Wellicht is het performance verschil zo minimaal (matrices berekenen is in de grand scheme niet echt de duurste actie) dat ze het niet herschreven in .NET, misschien zijn er gevallen die wel sneller zijn op de huidige manier, wellicht in combinatie met andere DirectX functie-calls.
Nou, de hypothese waar we mee begonnen was eigenlijk dat .net (relatief) traag is (gezien onze ervaringen met Java), en dat we daarom in alle gevallen waarin we enigszins krap in performance denken te zitten moeten uitwijken naar native code. Maar naar nu blijkt is de .net jit compiler eigenlijk bestwel goed; de gegenereerde machinecode voor deze test is praktisch equivalent aan DirectX.

Het resultaat hiervan betekend dus meer dan alleen "matrix-vermenigvuldiging kan in .net", het betekend ook "we hebben meer performance dan we dachten". We hadden 't echter niet verwacht, vandaar dit topic.
Ik zou het nog eens proberen als je echt een volledige render-pass hebt geïmplementeerd om te kijken waar de bottlenecks zitten en hoe je die zelf kunt optimaliseren. Het is dan handig om eerst te meten (met bijv. CLR Profiler) waar de échte pijnpunten zitten. Bij een micro-benchmark heb je al snel dat je appels en peren aan het vergelijken bent, in het grote geheel kan er te veel anders zijn om hier echt iets mee te kunnen.
Uiteraard. Maar aangezien we nog helemaal niks hebben om door de profiler heen te halen en willen beginnen met iets wat enigszins goed in elkaar zit ontkomen we niet aan microbenchmarks.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ok, het antwoord is dus dat de d3dx versie van de matrix muls helemaal niet voldoende geoptimaliseerd is :)

Overigens zit de grootste bottleneck in games meestal niet in het doen van berekeningen, maar in het touchen van heel veel memory, wat resulteert in een hoop cache-misses.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op donderdag 29 juni 2006 @ 10:59:
Ok, het antwoord is dus dat de d3dx versie van de matrix muls helemaal niet voldoende geoptimaliseerd is :)
Ik heb een keer gelezen dat general purpose native DLL's normaal niet worden gecompileerd met SSE optmimalisaties, omdat die niet beschikbaar zouden zijn op alle gangbare systemen. Is dat zo en zou het kunnen dat de .NET CLR deze optimalisaties wel toepast bij het JIT-en van de IL code?
Uiteraard. Maar aangezien we nog helemaal niks hebben om door de profiler heen te halen en willen beginnen met iets wat enigszins goed in elkaar zit ontkomen we niet aan microbenchmarks.
De CLR profiler kan alleen de code benchmarken die op de CPU wordt uitgevoerd, dus als je straks met renderen aan de slag gaat, heb je meer aan de PIX profiler of de NVidia perfkit. Deze kunnen je ook wat meer vertellen over de interactie van de CPU met je GPU. Een van de belangrijkste doelen in games programmeren is om je GPU bezig te houden zodat je je CPU vrij hebt (lees meer). Uit de optimalisatie daarvan haal je waarschijnlijk veel meer performance dan CPU matrix math :)

[ Voor 48% gewijzigd door Verwijderd op 29-06-2006 11:48 . Reden: Info over profiling toegevoegd ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hoe je je general purpose dlls compileert moet je zelf weten, ik kan best begrijpen dat MS dat niet doet (het moet natuurlijk ook werken op CPU's die geen SSE instructieset ondersteunen). Voor d3dx had ik wel een detectie van SSE en 3dnow! verwacht, maar blijkbaar is dat niet zo.

de jitter van .Net kan het uiteraard wel, het systeem is op dat moment al bekend. De vraag is alleen hoe goed hij is in het vectoriseren van generieke code. In VC++ gebruik je doorgaans het __m128 type (waarmee je aangeeft dat het in een SSE register past) en de SSE intrinsics (elke SSE instructie heeft z'n C counterpart die op die __m128 variabelen werken). Dat compileert direct naar de bijbehorende inline SSE code.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Verwijderd schreef op donderdag 29 juni 2006 @ 11:21:
De CLR profiler kan alleen de code benchmarken die op de CPU wordt uitgevoerd, dus als je straks met renderen aan de slag gaat, heb je meer aan de PIX profiler of de NVidia perfkit. Deze kunnen je ook wat meer vertellen over de interactie van de CPU met je GPU. Een van de belangrijkste doelen in games programmeren is om je GPU bezig te houden zodat je je CPU vrij hebt (lees meer). Uit de optimalisatie daarvan haal je waarschijnlijk veel meer performance dan CPU matrix math :)
Daarin heb je volkomen gelijk, maar dat is nog niet helemaal het stadium waarin we zitten. Of althans, dat was niet de reden waarom ik dit topic opende oorspronkelijk. De matrix benchmark was puur een inventarisatie van de te verwachten resultaten van native geoptimaliseerde (was toen nog de aanname, die helaas ook iets te optimistisch was) vs. geJITte .net code...

De tools van nVidia waarnaar je linkt gaan we in de toekomst zeker wel nodig hebben. Het hele project is voor mezelf mede begonnen als leertraject om eens echt te duiken in C# en DirectX (en alles wat daar bij komt kijken)... Mijn ervaring qua programmeren ligt vooral in de applicatiebouw, waar wel performance kritieke delen in zitten, maar de optimale interactie tussen systeem componenten (CPU/GPU) is daar veel minder van belang. Dat is voor mij grotendeels toch nieuwe kennis...

Verwijderd

maar dat is nog niet helemaal het stadium waarin we zitten. Of althans, dat was niet de reden waarom ik dit topic opende oorspronkelijk.
Had ik inderdaad al gelezen, maar het leek me handige info voor als jullie dit stadium bereiken en om misschien alvast rekening mee te houden in jullie design. En het was een mooie kans om schaamteloos onze Managed DirectX site te pluggen (zie m'n sig) ;)

Verwijderd

Even een domme opmerking. Je eigen .Net code doet een 4 bij 4 matrix. Leuk maar probeer eens een 100 bij 100 of 1000 bij 1000 matrix. Het is goed mogelijk dat de standaard implementatie bij kleine matrices slechter presteert maar veel beter schaalt.

Het gebruik van native methods kan sneller zijn, maar het is de vraag of je die wil gebruiken. In ieder geval is dat appels met peren vergelijken.

Verwijderd

Topicstarter
Verwijderd schreef op donderdag 29 juni 2006 @ 15:54:
Even een domme opmerking. Je eigen .Net code doet een 4 bij 4 matrix. Leuk maar probeer eens een 100 bij 100 of 1000 bij 1000 matrix. Het is goed mogelijk dat de standaard implementatie bij kleine matrices slechter presteert maar veel beter schaalt.
Maar... in mijn situatie, en dat is 3D computer graphics, zijn er alleen maar 4x4 matrices om mee te werken. Daarom staat die functie daar ook helemaal geunrolled uitgeschreven, in plaats van dat er een generieke matrix vermenigvuldigingsmethode staat. In de d3dx native bibliotheek zit ook geen generieke matrix vermenigvuldiger, maar 1 die alleen op 4x4 matrices werkt.
Pagina: 1