Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

11

28.04.2014, 09:17

Was du da tust ist loop unswitching mithilfe von templates. Würdest du den Inhalt der anderen Funktion direkt in den Code packen, könnte das der Compiler selbst.
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

12

28.04.2014, 09:28

@Bluecobold
Messen macht schon Sinn.
Ich mache ja irgendwelche Simulationssoftware. Da brummt die CPU.
Klar, nur sollte Dein Testfall dann auch repräsentativ sein, was er eben rein gar nicht ist. Eine Situation künstlich zu verschlechtern, damit eine andere besser da steht, kann wohl kaum Sinn der Messung sein.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

13

28.04.2014, 09:41

Eventuell sollte er mal seine Voraussetzungen definieren. Beispielsweise:

"Es soll eine beliebige Memberfunktion mit Parametern aufgerufen werden, die erst zur Laufzeit bekannt sind."

C-/C++-Quelltext

1
2
3
4
5
6
7
8
inline void CWorkerClass::Work (const bool Arg1, const bool Arg2, const int Iterations)
{
    if (Arg1)       
        for (int i = 0; i < Iterations; ++i) ...       

    if (Arg2)
        for (int i = 0; i < Iterations; ++i) ...
}


Und dazu noch die beliebige Memberfunktion noch optimieren, bevor man ewig an dem Drumherum optimiert.

C-/C++-Quelltext

1
2
3
4
5
inline void CWorkerClass::Work (const bool Arg1, const bool Arg2, const int Iterations)
{
    if (Arg1) Data = (Data2 += 1* Iterations) - 1;
    if (Arg2) Data = (Data2 += 2 * Iterations) - 2;
}
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

14

28.04.2014, 11:20

Zitat

Ist das wirklich sinnvoll? Das geht mir ja persönlich schon sehr in Richtung virtuelle Methoden sind langsam und muss man vermeiden. Macht das wirklich so viel aus?

Die Gruppen will ich vor allem weil ich SIMD nutze und dann immer vier Elemente zusammen berechne.
Die Berechnung zu verschlanken, ohne Overhead durch die ifs selber, das ist zumindest die Absicht mit den templates.


Zitat

Was du da tust ist loop unswitching mithilfe von templates.

Genau.

Zitat

Würdest du den Inhalt der anderen Funktion direkt in den Code packen, könnte das der Compiler selbst.

Weiß nicht welche für die die "andere" Funktion ist und was du mit "direkt in den Code" meinst.


Zitat

Es soll eine beliebige Memberfunktion mit Parametern aufgerufen werden, die erst zur Laufzeit bekannt sind.

Nein, es geht praktisch darum dass viele Elemente verarbeitet werden. Das passiert in vierer Gruppen mit SIMD.
Die vier Elemente die in die Gruppe kommen werden identisch verarbeitet.

In dem Test geht es um einen Nachweis, dass man die Branches mit Templates zur Compilezeit auflösen kann, bzw, dass der Compiler den Code tatsächlich so auflöst, und darum ob das irgendwelche Nachteile hat.

MFG
Bilder zu meinem Projekt: ParSim

15

28.04.2014, 12:10

Es geht und die Nachteile haben wir ja schon genannt, bzw. liegen auf der Hand ;)
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

16

28.04.2014, 12:56

Habe nochmal was getetset.
Eine Aufrufstrukttur über std::function.

C-/C++-Quelltext

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
26
27
28
29
30
31
32
33
    Branch BranchObj;
    std::function<void(int)> f_branch[4] =
    {
        [&](int i){ BranchObj.Work(false, false, i); },
        [&](int i){ BranchObj.Work(true, false, i); },
        [&](int i){ BranchObj.Work(false, true, i); },
        [&](int i){ BranchObj.Work(true, true, i); }
    };

    Template<false, false> TemplateObj0;
    Template<true, false> TemplateObj1;
    Template<false, true> TemplateObj2;
    Template<true, true> TemplateObj3;
    std::function<void(int)> f_template[4] =
    {
        [&](int i){ TemplateObj0.Work(i); },
        [&](int i){ TemplateObj1.Work(i); },
        [&](int i){ TemplateObj2.Work(i); },
        [&](int i){ TemplateObj3.Work(i); }
    };


/*...*/

        BranchObj.Work(Arg1, Arg2, Iterations);    //144ms

/*...*/

        f_template[TemplateNum](Iterations);    //76,s

/*...*/

        f_template[TemplateNum](Iterations);    //74.s


Auch so lassen sich auch die normalen Argumente zur Compilezeit auflösen.
das Template ist nur noch minimal besser als die Funktionsaufrufe mit Konstanten.

Das ist vielleicht handlicher...
Bilder zu meinem Projekt: ParSim

Werbeanzeige