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

91

19.02.2014, 18:53

Hi,

es gibt par Neuerungen.
Erste Waffensysteme sind fertig:

(Link)

Man kann nun also Rumfliegen und schießen.

Zudem gibts noch was abgefahrenes:
Ich habe es geschafft die Schwingung der Materialien, oder besser gesagt den "Druck" des Beobachter-Partikels (Auf den auch die Camera zentriert ist) zu sampeln.
Aus dem Druck wird dann über die Boxen des Speilers Schalldruck.
Das Prinzip ist sehr realitätsnah. Es rumpst nun ordentlich wenn man getroffen wird, Wenn man in den Strahl fremder Triebwerke gerät rumort es.
Die Töne sind basslastig und vielfältig.

Leider gibts noch einen Bug. Es kann unter bestimmten Bedingungen der Sound thread fehlerhaft werden.


Hier sieht man eine Schwingung, erzeugt wird sie durch den Rückstoß beim abfeuern der Waffe im Bild oben.

(Link)

Es ist ein gleichförmiges sanftes Rumpsen, nicht so rau wie ein Crash.


Die Engine könnte in ihrem Zustand hunderte von vielseitigen Materialien verarbeiten. Da aber ständig noch kleine Baustellen am Framework habe kommeich nicht so richtig dazu.


Aufruf an alle die Lust haben!
ich könnte Hilfe brauchen beim Erstellen von Materialien?

  • Grundlegende Kenntnisse von Programmierung und C++ notwendig
  • Kreativität wichtige, Spielraum für Kreativität ist gegeben!
  • Ein Material ist eine Klasse.
  • Schwierige Funktionen übernimmt die Basisklasse.
  • Es gibt ca. 30 Materialien an denen man sich orientieren kann.

Da es momentan ganz gut läuft überlege ich auch demnächst mal wieder eine EXE hier hochzuladen.

MFG
Bilder zu meinem Projekt: ParSim

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Horus« (19.02.2014, 20:37)


David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

92

21.02.2014, 10:38

Extrem cool, das mit der Sound-Synthese!
Ich würde furchtbar gerne mal ein Video sehen und hören. Wärst du so nett eins aufzunehmen?

93

21.02.2014, 22:13

Hi,

"Cool" ist die Methode auf jeden fall. Es ist ja gewissermaßen der "echte" Sound.

Ich hoffe du stellst dir da nicht mehr drunter vor als es ist. ^^

Für ein Echo möchte ich die CPU nicht belasten.
Die erfasste Materialschwingung wird nur minimal verarbeitet, mit der folgenden Klasse.

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
34
35
36
37
38
39
40
class SoundTransducer
{
public:
    SoundTransducer()
    {
        LastIn = 0;
        Avg = 0;
        LastSample = 0;
    };

    ~SoundTransducer()
    {
    };

    double Process(double In)
    {
        const double Amp = 4000000.f;
        In *= Amp;

        double Sample = (Avg - In);

        if (Sample < -32767)
            Sample = -32767;

        if (Sample > 32767)
            Sample = 32767;

        Avg = Avg * 0.5f + In * 0.5f;

        Sample = Sample * 0.5 + LastSample * 0.5;
        LastSample = Sample;

        return Sample;
    };

private:
    double LastSample;
    double LastIn;
    double Avg;
};


Man hört also fast "Roh" in den Partikel rein.



Der Beobachterpartikel (der auch mit der Kamera anvisiert ist) stellt den Punkt der Schwingungsmessung dar.
Es können somit nur Ereignisse gehört werde, deren Erschütterungen diesen Partikel erreichen.

Mit dem Soundbuffer habe ich noch (etwas hörbare?) Probleme. Ich müsste statt SFML wohl mal direkt OpenAL nehmen. :evil:
Momentan hat die Weiterentwicklung des Soundsystemes keine Priorität, ich habe einige andere Dinge, die wichtiger sind.

Ob in einem ersten Release der Sound überhaupt so wie er ist aktiviert sein sollte?

MFG
Bilder zu meinem Projekt: ParSim

94

15.03.2014, 00:50

Hi,

ich habe es nicht für möglich gehalten, jedoch liegt die Performance jetzt bei etwa 200%.

Es war bereits alles bis ins Detail optimiert.
Deshalb bin ich total erstaunt wie ineffiezent doch alles war.

Vielleicht interessiert es jemanden wie es möglich war?

1. Datenorientierung.
Ich arbeite mit riesigen C-Arrays.
Objektorientierung gibt es bezüglich der Simulationsdaten nicht mehr.
Alles ist mit uint32 Indizes statt Zeigern auffindbar.

2. Nutzung von SIMD (SSE und SSE2)
Wo es möglich ist werden mehrere Partikel gleichzeitig berechnet.
Das ist bei der Aktualisierung der Partikel gut machbar.
Bei den Kollisionen bringt es bisher keinen Vorteil. Das Cachen mehrerer Kollisionen in den Simulationsthreads (zwecks Berechnung mit SIMD) ist noch zu langsam, daran muss ich noch testen.

3. __assume
http://msdn.microsoft.com/en-us/library/…w(v=vs.90).aspx
Wirkt bei den "heißen" Schleifen wahre Wunder.
Also vor der "for" schon festlegen wie groß der Wert maximal wird. Der Compiler von Visual Studio optimiert dann die Schleife erheblich.


Fazit:
Cache-Effekte waren bei meinen Verbesserungen wichtiger als das Tempo der Berechnung. Stichwort "cache miss penalty".
Ich habe mich fälschlicherweise oftmals zu sehr auf Effizzienz der Berechnungen konzentriert.
Ich bin der Meinung auf die zentrale Bedeutung von Cache-Effekten wird allgemein zu selten hingewiesen.


Da ich soviel umgestellt habe ist die alte Funktionalität bisher nicht erreicht.
Es sind noch einige „low level“ Sachen, die eventuell besser simuliert werden könnten.

MFG
Bilder zu meinem Projekt: ParSim

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

95

16.03.2014, 11:59

3. __assume
http://msdn.microsoft.com/en-us/library/…w(v=vs.90).aspx
Wirkt bei den "heißen" Schleifen wahre Wunder.
Also vor der "for" schon festlegen wie groß der Wert maximal wird. Der Compiler von Visual Studio optimiert dann die Schleife erheblich.

Kannst du hierzu mal ein konkretes Beispiel posten?
Hast du den Effekt wirklich gemessen bzw. gesehen, dass sich dadurch der generierte Code geändert hat?
Oft wird man bei solchen Optimierungen ja stark von Wunschdenken beeinflusst ;)
Ich habe das __assume-Feature noch nie benutzt, sieht aber interessant aus.

96

16.03.2014, 21:02

Hi,

über Performanceoptimierungen kann ich ewig diskutieren, gerne auch sehr konkret.

den Unterschied in der Disassembly habe ich bzgl. des __assume nicht untersucht.
Da sich der Effekt von Optimierungen eh kaum vorhersagen lässt, setze ich wie fast immer auch hier auf Messungen der Performance. Diese ist schließlich entscheidend für mich.

Diese Messungen sind nicht ganz verlässlich, bei dem __assume ist der Effekt allerdings absolut klar sichtbar, weil er recht groß ist. Assume an mehreren "heißen" Schleifen brachte etwa + 15% Leistung.

Das hat wohl damit zu tun, dass die Kollisionserkennung viel iterieren muss, der Maximalwert klein ist und nicht vom Compiler vorhergesagt werden kann.

Beispiel: die folgende Schleife muss im Spielbetrieb pro Sekunde schätzungsweise 50 Millionen Mal durchlaufen werden.
Es werden Kollisionen von Partikeln in den Sektoren eines "uniform grid" gesucht.

C-/C++-Quelltext

1
2
3
4
5
6
__assume(Sector_ParticleCount[Sector] <= SECTOR_PARTICLE_MAXIMUM);
for (uint8_t i = 0; i < Sector_ParticleCount[Sector]; ++i)
{
    const StdIndex P2 = Sector_StoredParticle[Sector_GetParticleIndex(Sector, i)];
        Particle_InteractCollisionDetect(P1, P2, ThreadCollisionCount, ThreadCollisionIndex);
}

Die Konstante SECTOR_PARTICLE_MAXIMUM ist 3.
Die Variable Sector_ParticleCount[Sector] ist oftmals 0 oder 1, selten 2, fast nie 3.

Es gibt nur wenige Stellen in meinem Sourcecode, an denen das __assume ähnlich wirkungsvoll ist.

Einzig "Loop unrolling" ist in dem obigen Anwendungsfall eventuell noch schneller:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const StdIndex Count = Sector_ParticleCount[Sector];
if (Count > 0)
{
    const StdIndex P2_1 = Sector_StoredParticle[Sector_GetParticleIndex(Sector, 0)];
    Particle_InteractCollisionDetect(P1, P2_1, ThreadCollisionCount, ThreadCollisionIndex);
    if (Count > 1)
    {
        const StdIndex P2_2 = Sector_StoredParticle[Sector_GetParticleIndex(Sector, 1)];
        Particle_InteractCollisionDetect(P1, P2_2, ThreadCollisionCount, ThreadCollisionIndex);
        if (Count > 2)
        {
            const StdIndex P2_3 = Sector_StoredParticle[Sector_GetParticleIndex(Sector, 2)];
            Particle_InteractCollisionDetect(P1, P2_3, ThreadCollisionCount, ThreadCollisionIndex);
        }
    }
}


Ob nun eine For-Schleife mit __assume oder das Unrolling in dem obigen Anwendungsfall bessere Performance bringt, konnte ich nicht klar messen. Der Unterschied ist, wenn vorhanden, sehr gering.

Wichtiger bleibt Datenorientierung bzw. Cache-Effekte. Wie sich diese gezielt nutzen lassen erschließt sich mir erst peu à peu. :wacko:

MFG
Bilder zu meinem Projekt: ParSim

JustSid

Frischling

Beiträge: 54

Beruf: Lead Idiot

  • Private Nachricht senden

97

17.03.2014, 00:34

Naja, von hand unrollen ist etwas meh (und falls du es doch machen willst, dreh es mal um und mach es aggressiver um branches zu sparen!). Der Compiler sollte dazu eigentlich selber in der Lage sein wenn du ihm sagst wie groß das maximal ist, und der Compiler hat auch kein Problem damit deinen Code zu nehmen und ein paar mal leicht verändert rum zu copy and pasten. Und eventuell kann der da auch noch was mit jump tables rausholen.

Wo wir allerdings bei caching und SIMD sind, hast du mal mit cache-oblivious data-structures und AVX2 rumgespielt? Ich hatte mit ersterem einigen Erfolg bei oft genutzten Daten in sehr engen loops, wäre eventuell auch noch einmal etwas zum reinschauen.

Falls das übrigens etwas ist was dich interessiert, dann wird dir das hier extrem gut gefallen: http://agner.org/optimize/
Insbesondere The microarchitecture of Intel, AMD and VIA CPUs: An optimization guide for assembly programmers and compiler makers gibt doch extrem gute Einblicke in den Aufbau der pipeline und stations von allen möglichen CPU Generationen. Nicht unbedingt immer 100% Anwendbar wenn du dir nicht dein eigenes Assembly schreibst, aber trotzdem eine sehr wertvolle Ressource.
Jabberwock is killing user

98

17.03.2014, 23:07

Hi,

Zitat

Naja, von hand unrollen ist etwas meh (und falls du es doch machen willst, dreh es mal um und mach es aggressiver um branches zu sparen!).

Vermutlich meinst du eine "binäre Suche"?

Aufgrund der Häufigkeitenverteilung während der Laufzeit in obigen Beispiel, scheint mir eine binäre Suche dort nicht geeignet.
Allerdings ist das eine gute Idee, das werde ich in der Tat mal probieren, allerdings an einer anderen Stelle, bei den Verklebungen der Partikel.

Zitat

Der Compiler sollte dazu eigentlich selber in der Lage sein wenn du ihm sagst wie groß das maximal ist, und der Compiler hat auch kein Problem damit deinen Code zu nehmen und ein paar mal leicht verändert rum zu copy and pasten. Und eventuell kann der da auch noch was mit jump tables rausholen.

Natürlich, es passt auch dazu, dass sich die Performance mit __assume nicht mehr messbar von dem unrolled for unterscheidet.

Zitat

Wo wir allerdings bei caching und SIMD sind, hast du mal mit cache-oblivious data-structures und AVX2 rumgespielt?

Hahaha. Die veraltete CPU des Rechners an dem ich entwickel unterstützt maximal SSE2. :|
AVX nutzen zu können ist aber ein Argument für einen neuen Rechner. ^^

Mit AVX wird bei der Datenverarbeitung noch eine verdoppelung möglich sein. Nach meiner Einschätzung macht diese Datenverarbeitung jedoch bei weitem nicht die Hauptlast aus. Der Effekt wird also letztendlich überschaubar ausfallen.

Die Links sehen gut aus. Das ist viel "schweres" Material, welches ich mir die Tage im Detail ansehe.

MFG
Bilder zu meinem Projekt: ParSim

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Horus« (17.03.2014, 23:13)


David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

99

18.03.2014, 08:07

Benutzt du eigentlich einen Profiler?
Wenn nein, kann ich dir das nur empfehlen. Dann musst du nicht selber messen oder raten. ;)

100

18.03.2014, 09:17

Hi,

ja, ich nutze den Profiler von VS2013. Der ist in der Tat hifreich.

Jdenfalls bin ich erstaunt über den Effekt der _mm_prefetch Anweiseung, die ich gerade getestet habe.
In einem ersten Anwendungsfall springen bereits satte 25% Leistungsgewinn raus.
Noch fällt es mir schwer diesen immensen Effekt durch blosß zwei _mm_prefetch Anweiseungen mehr pro Kollision/Adhäsion zu verstehen.

Meine vorläufige Interpretation ist, dass die blanke berechnung bereits extrem optimiert ist, wodurch cach misses stark ins gewicht fallen.
Durch die Datenorientierung möchte man erwarten, dass die Partikel in der cachline liegen. Das ist jedoch nur teilweise der fall!
Bei den Interaktionen von Partikel, kann praktisch jeder mit jedem.

Illsutration:

Partikel 1 - Partikel 591 interagieren
Partikel 1 - Partikel 682 interagieren
Partikel 2 - Partikel 10271 interagieren
Partikel 3 - Partikel 598 interagieren
usw.

Der pechte Partikel bringt dabei eine üble cach miss penalty. Laut Profiler ist diese größer als die nachfolgende Berechnung.

Zum jetzugen Zeitpunk bin ich nicht sicher, ob mit der _mm_prefetch Anweisung sich an dieser Stelle noch mehr geht. Das muss ich genauer untersuchen.
Zudem erwarte ich, dass Prefetching an anderer Stellen ebenfalls wirkungsvoll sein könnte.

Auf moderen CPUs laufen vermutlich bald mehrere 10k Partikel mit 1000 updates per second.
Ich werde das Limit auf 65536 Partikel erhöhen können. Riesige Asteroiden, Raumstationen Massenhaft gegner, Explosionen und Trümmer. Extreme Performance extremer Spaß 8) .


...Jedenfalls Prefetching sollte jeder mal probieren, der Performance benötigt und die Daten nicht in die Cachline legen kann.
Aber Achtung, man muss es richtig anwenden, sonst wirds nutzlos oder sogar langsamer sein, wie ich feststellen musste.

MFG
Bilder zu meinem Projekt: ParSim

Werbeanzeige