Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Mär 29, 2024 10:13

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 83 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3, 4, 5, 6  Nächste
Autor Nachricht
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Mi Apr 16, 2014 19:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
Ich würde mich freuen, wenn du da mal Beispiele bringen kannst, denn solche Erfahrung konnte ich bisher nicht machen.

Wir haben auf Arbeit ein Game, welches Weltweit lokalisiert wird, auch Chinesiche Zeichen, Vertikale ausrichtung, verschiedene Pluralformen und so weiter und ausser setlocal/getlocal, vsprintf und für windows noch utf8 zu utf16(was windows bereits zur verfügung stellt oder halt C++11) fällt mir nur die Lokalisierungstabelle ein(welche eine stink normale sqlite tabelle für jede Sprache ist) welche nicht aus dem Standard kommt.
Wenn man mit dem System redet ist es bei windows utf16 und alle unix basierten nutzen utf8, da die meisten System bezogenen Strings mit ANSI abbildbar sind und utf16 und 32 dort viel zu viel performance verbrennen.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Mi Apr 16, 2014 22:22 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Visual Studio unterstützt nicht die Unicode-Features von C++11. Siehe zb. diese Übersicht zum aktuellen CTP: http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-65-69/0638.Updated-Conformance-Map.png

Konsequent zb. UTF8 einzusetzen wird dadurch erheblich erschwert.
Auch in C++11 fehlen viele elementare Funktionen. Zb. die Länge in dargestellten Zeichen oder Codepoints eines UTF8 Strings bestimmen. In C gibt es da ein paar wenige Sachen in die Richtung. Die Funktionen zur Verarbeiten von Zeichen also zb. "std::towlower" und Konsorten sind auf "wchar_t" ausgelegt. Auf Windows ist also nur eine Unterstützung der UTF16 Zeichen durch die Funktion möglich. Unter Windows hat man generell immer Scherereien mit UTF16. Während UTF16 vor langer Zeit sinnvoll war, als alle Zeichen noch mit 16 Bit darstellbar waren, vereint es heute auf elegante Weise die Nachteile von UTF8 und UTF32. Häufig wird fälschlicherweise angenommen, dass "wchar_t" alle Codepoints darstellen könnte (Siehe zb. "std::towlower" und Andere). Unicode Ausgabe auf die Konsole, Unicode in Dateipfaden wird dadurch sehr aufwendig. Die C++ Streams sind eh sehr unpraktisch.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 09:33 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
VC++ ist auch ein ziemlich schlechter und veralteter Compiler, das haben die Hauseigenen Programmierer fest gestellt.
Aktuell wird ja an VS2014 gearbeitet und man hat die art der Entwicklung geändert, man packt prinzipiell alle Standards in den Preprocessor, Tokenizer und Compiler aber ignorieren diese prinzipiell. So ist der geschriebene Code erstmal kompatibel und man fügt dann über patches den Inhalt rein.

Für den Support dort muss man leider auf die Windows Spezifischen Funktionen zugreifen, die den C++ Standard repräsentieren.
VC++ macht nix anderes als nahezu alles in der C Runtime library auf System Funktionen zu mappen.
strlen, malloc, printf und so weiter sind auf Windows funktionen gemapped und da gibt es z.B. auch die Konvertierung von utf8 nach utf16, toupper und so weiter. Diese sind auch in Unicode und ANSI Code verfügbar. memcpy, memmove, strcmp und ähnliche funktionen sind von intel und kommen als asm code.

Ansi/Utf8 zu UTF16
umkehr operation

Ich stimme zu, dass UTF16 blöd ist und UTF8 und 32 wesentlich mehr vorteile haben.
UTF8 ist ASCII und ANSI kompatibel aber super langsam weil 8 und 16 bit operationen ~13x langsamer sind als 32-512Bit operationen.
Daher ist utf32 für performance generell praktisch und utf8 kann mit optimierung wesentlich schneller sein, wenn man im ASCII, ANSI bereich bleibt(sse4.2 bietet da sehr geile funktionen).
Eine QT Partner hatte unter linux mal ihre String klasse analysiert und für alle mit QT basierten Linux apps statistiken aufzeichnen lassen.
Raus kam, dass die Strings durchschnittlich ~11 Zeichen lang sind und über 90% in ASCII abbildbar sind. Daher hat man sich entschlossen UTF8 mit SSE zu optimieren statt weitere UNICODE Varianten zu supporten.
Man sollte dazu wissen, dass wenn man 16 UTF8 Zeichen naive verarbeitet man pro operation 13cycles braucht, weil die modernen CPU's 13 cycles für alle 8 und 16bit operationen(ausser division die noch teurer ist) braucht und für MMX, SSE1-4, AVX256-512 nur 1cycle brauchen aber zwischen 16-64 UTF8 Chars verarbeiten können.

edit:
Wegen ToUpper und ToLower, hab ich auf der gcc mailingliste eine Diskussion gesehen, dass es ein wirklich kompliziertes Problem ist und ich stimme dir zu, dass dies wirklich ein Problem in C++ ist aber wie schon erwähnt benutzen wir es nicht, weil wir es nicht brauchen ^^
Würden wir es brauchen, dann hätten wir wirklich ein Problem.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 13:17 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
VC++ ist auch ein ziemlich schlechter und veralteter Compiler

Ich stimme dir da weitgehend zu. Allerdings ist die damit verbundene IDE meiner Meinung nach mit Abstand das Praktischte auf Windows was es gibt. Ich wollte mich schon lange mal an Eclipse oder andere IDEs gewöhnen, aber irgendwie fällt mir das bislang noch recht schwer. Wenn man Performancevergleiche anschaut, ist der MSVC meistens nach dem Intel Compiler, der die Spitzenposition einnimmt. Es wird auch regelmäßig Unterstützung für verschiedene Dinge hinzugefügt. Bei jeden Updaten werden ein paar C++11/14 Features eingestreut und es wird zb. AVX2 inzwischen unterstützt und aktiv weiterentwickelt. "Veraltet" trifft es deshalb meiner Meinung nach nicht ganz.
Wie das intern genau geregelt wird, ist mir persönlich eigentlich relativ egal. C++ hat ja schon ein paar Features die man intern vorgelagert gesondert behandeln und umwandeln kann. Ich hoffe, die wissen was sie mit ihrer eigenen Software machen. Im Prinzip ist mir das halt relativ egal. Ich will nur mehr Standardfeatures. Gegen den UTF16 Wahn auf Windows, wird das natürlich alles kaum helfen.

Das mit dem Systemfunktionen ist meiner Meinung nach auch das Sinnvollste und bei manchen Dingen(zb. IO) das einzig Mögliche. Du schreibst es irgendwie so, als ob es etwas schlechtes wäre. "std::strlen" ist übrigens auch nativ unter anderem als Asm implementiert. "std::tolower" auch. Es würde keinen Sinn machen, solche Minifunktionen in Systemaufrufe umzuwandeln. Bei "towlower" wäre ich mir auch nicht so sicher. Also mindestens teilweise ist es in der MSVCRT, aber zu 100% konnte ich das in den Sources gerade nicht nachverfolgen.

Die von dir genannten Funktionen verwende ich zufälligerweise bereits. :lol:
Aber das platformunabhänig hinzubekommen, das erfordert eben selbst Hand anzulegen. Das ist das, was ich meinte. Die "codecvt"-Funktionen würden von einer neuen Version von VS inzwischen sogar schon unterstützt, nur leider in einer Älteren nicht, mit der ich im Moment noch kompatibel sein will. Die STL ist eigentlich ganz gut auf dem Stand. Bei C++11 krankt es hauptsächlich am Compiler.
Problematisch ist eigentlich am aller meisten, dass alle "System"funktionen auf UTF16 ausgelegt sind. Entsprechende Probleme gibt es mit externen Bibliotheken, die nicht primär auf Windows ausgelegt sind, und in "char"s UTF8 Zeichen speichern und auch an das System übergeben. Man muss die sich also alles selbst auf der Windowsplatform zurecht richten, damit sie mit UTF8/32 arbeiten. Ich habe leider in der Vergangenheit auch den Fehler gemacht, "wchar_t" für alles zu verwenden was Unicode sein soll. Jetzt wäre es an der Zeit mal alles konsequent umzustellen. Ich will jedenfalls unbedingt mal eine performante und einfache Unicodeklassen schreiben, damit ich das Problem in Zukunft nicht mehr habe. Für "std::towlower" und andere, habe ich schon überlegt dann zb. ICU einzusetzen.

Zitat:
UTF8 ist ASCII und ANSI kompatibel aber super langsam weil 8 und 16 bit operationen ~13x langsamer sind als 32-512Bit operationen.

Ich glaube nicht, das das im optimierten Fall gilt. Das mit Abstand kritischte Element ist Speicher. Wie du selbst schon schreibst, sind 90% aller Zeichen ASCII. In meiner Software würde ich sogar noch mehr schätzen. 4 mal soviel Speicher pro Zeichen geht auf den Cache und wird wohl kaum außer im isolierten Fall schneller sein, als UTF8. Außerdem glaube ich, werden moderne Compiler keine 8 und 16 Bit Befehle mehr in Maschinencode emittieren, sondern das entsprechend umformen. Ist es nicht so, dass der x64 Long Mode gar keine 8/16-Bit Befehle mehr kennt?

Wenn es um Performance geht, kann man Unicode in die Tonne treten. Ich habe es nie gemessen, aber zb. ein korrekter Stringvergleich nach allen Regeln der Kunst, muss wohl hunderte bis tausende oder mehr Takte pro Zeichen brauchen. Am performantesten ist wahrscheinlich, entweder normalerweise naiv byteweise zu vergleichen, was zwar nicht korrekt ist, für meine Anwendungsfälle aber so gut wie immer gut genug, oder Unicode extra zu behandeln, nur wenn es notwendig ist und andere Strings wieder direkt zu vergleichen. Unperformant ist auch, das insbesondere C-Strings keine Längenangabe haben, sondern nur Nullterminiert sind. Das ist viel teurer umzusetzen, aber verblasst vor dem Anblick des Overheads, den Unicode bringt.


Zuletzt geändert von OpenglerF am Do Apr 17, 2014 17:25, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 16:46 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Das waren noch Zeiten, wo man nur den Standard -ASCII-Zeichensatz kannte, da musste man sich um nichts kümmern. ASCII-Tabelle

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 17:34 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
nu, mir ist schon klar wie und warum C++ Templates behandelt wie es ist. Die Frage ist aber eher wie man diese Template/Generic Problematik angeht. C++ betrachtet hier diese Geschichte nicht als ein Template, sondern als fertig aufgelöste Funktionen. Dann ist natürlich der C++-Weg in jeden Fall richtig. Betrachtet man das Ganze aber mit der OOP-Brille, dann ist ja das einfache "T" eindeutig abstrakter. Sprich, der Template Mechanismus an sich bildet hier einen größeren Widerspruch zur restlichen Sprache als ein Generic. Ob man das Ganze nun zur Compile-Zeit oder zur Laufzeit macht wäre ja erst einmal egal.

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 17:44 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Ehrlich gesagt verstehe ich im Moment nicht ganz was du mit dem Text aussagen willst. Ich sehe da in C++ keinen Widerspruch. Generics unter dem Namen gibt es da nicht. (Wobei mit Templates exakt das selbe und noch viel mehr erreichen kann.)
Eine dogmatische "OOP-Brille" ist auch nicht immer der beste Weg.

Zitat:
Ob man das Ganze nun zur Compile-Zeit oder zur Laufzeit macht wäre ja erst einmal egal.

Eigentlich gibt es da einen sehr großen Unterschied.
Es gibt viele Ausdrücke, bei denen die Werte zur Compile-Zeit ausgewertet werden müsssen. Zb. in anderen Templates ,in statischen Arrays(Ab C++14 gibt es hier zwar eine kleine Änderung...), oder in Verbindung "constexpr"-Funktionen.

In C++ könnte man also zb. machen...
Code:
  1. using SuitableIterableType = std::conditional<isIterable<OtherT>(), OtherT, std::list>;

... um für den Fall, dass "OtherT" nicht iterierbar ist, einen alternativen Typ zu verwenden. (In dem Fall "std::list")
Wenn "isIterable" nicht zur Compile-Zeit aufgelöst werden könnte, wäre das unmöglich.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 17:56 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Ich nenn es nur Generic und Template damit man die Wirkung der beiden "Auflösung"-Methoden besser Unterscheiden kann. Es würde ja schließlich nichts dagegensprechen (außer vielleicht längere Compile Zeiten und Kompatibilität) das Ganze genauso wie ein Generic aufzulösen.

Und der Widerspruch besteht halt darin, das ich bei normalen Funktionen, Klassen, usw. halt auch das abstrakteste zuletzt nehme. Warum also dieses Prinzip nicht auch auf Templates ausweiten?

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 18:46 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
OpenglerF hat geschrieben:
Zitat:
VC++ ist auch ein ziemlich schlechter und veralteter Compiler

Ich stimme dir da weitgehend zu. Allerdings ist die damit verbundene IDE meiner Meinung nach mit Abstand das Praktischte auf Windows was es gibt. Ich wollte mich schon lange mal an Eclipse oder andere IDEs gewöhnen, aber irgendwie fällt mir das bislang noch recht schwer. Wenn man Performancevergleiche anschaut, ist der MSVC meistens nach dem Intel Compiler, der die Spitzenposition einnimmt. Es wird auch regelmäßig Unterstützung für verschiedene Dinge hinzugefügt. Bei jeden Updaten werden ein paar C++11/14 Features eingestreut und es wird zb. AVX2 inzwischen unterstützt und aktiv weiterentwickelt. "Veraltet" trifft es deshalb meiner Meinung nach nicht ganz.

Ich hab es schon indirekt erwähnt aber diese Teile kommen nicht von MS sondern Intel, MS verwendet diverse Bibliotheken von Intel, die in allen Bereichen Optimierte Varianten und auch den größten Teil der intrinsics liefert. Deswegen mag ich auch den Compiler nicht so sehr, weil kritische Funktionen wie strlen, strcmp auf Intel CPU's mit SSE optimiert sind aber auch nur SSE2.

OpenglerF hat geschrieben:
Das mit dem Systemfunktionen ist meiner Meinung nach auch das Sinnvollste und bei manchen Dingen(zb. IO) das einzig Mögliche. Du schreibst es irgendwie so, als ob es etwas schlechtes wäre. "std::strlen" ist übrigens auch nativ unter anderem als Asm implementiert. "std::tolower" auch. Es würde keinen Sinn machen, solche Minifunktionen in Systemaufrufe umzuwandeln. Bei "towlower" wäre ich mir auch nicht so sicher. Also mindestens teilweise ist es in der MSVCRT, aber zu 100% konnte ich das in den Sources gerade nicht nachverfolgen.

strlen kommt zu 100% von Intel und kommt als intrinsic bei der tolower würde ich nicht mehr meine Hand ins Feuer legen, da müsste ich erst mit nem symbol browser rein gucken.
Mit den Systemfunktionen bin ich eigentlich schon glücklich, MS bietet in MSDN auch eine Tabelle, wo steht, welche System Funktionen 1zu1 auf C/C++ Standard funktionen ersetzt werden können und wo partiell.
Aber wie du schon sagtest, man muss leider wrapper schreiben :\

OpenglerF hat geschrieben:
Für "std::towlower" und andere, habe ich schon überlegt dann zb. ICU einzusetzen.

Ich hatte schon mit ICU zu tun und mag es überhaupt nicht, das ding ist so riesig, da wirkt Boost und QT wie ein kleines projekt gegen.
EA nutzte es lange Zeit und ist deswegen auch mit im veröffentlichten Framework Code aber die sind auf Frostbite umgestiegen und was dort verwendet wird ist mir nicht bekannt.

OpenglerF hat geschrieben:
Zitat:
UTF8 ist ASCII und ANSI kompatibel aber super langsam weil 8 und 16 bit operationen ~13x langsamer sind als 32-512Bit operationen.

Ich glaube nicht, das das im optimierten Fall gilt. Das mit Abstand kritischte Element ist Speicher. Wie du selbst schon schreibst, sind 90% aller Zeichen ASCII. In meiner Software würde ich sogar noch mehr schätzen. 4 mal soviel Speicher pro Zeichen geht auf den Cache und wird wohl kaum außer im isolierten Fall schneller sein, als UTF32. Außerdem glaube ich, werden moderne Compiler keine 8 und 16 Bit Befehle mehr in Maschinencode emittieren, sondern das entsprechend umformen. Ist es nicht so, dass der x64 Long Mode gar keine 8/16-Bit Befehle mehr kennt?

Ich glaube so ziemlich jeder Programmierer hat diesen Irrglauben, dass intern optimiert wird um die lahmen Operationen zu umgehen aber das ist leider nicht ganz der Fall.
Es wird nun etwas länger und ziemlich tiefgreifen, einfach aufhören zu lesen, wer nicht gerade Interesse an Cycles, register, caches, opcode und wieso die Welt so schlecht ist ;)

Der Compiler darf Datenstrukturen nicht sortiern oder ersetzen und daher bleibt ein char auch ein char und es werden entsprechende Operationen dafür verwendet.
Was der Compiler optimieren kann sind wiederverwendung von register, code reordering, schleifen, vergleiche und noch einige ziemlich kranke dinge, wovon ich keine Ahnung hab aber die Optimierungen findet recht fix ihre Grenzen.
Früher waren alle Operationen recht ähnlich teuer(Intel P2 lässt grüßen) aber als SIMD kam waren diese meist nur 1 cycle teuer, später waren alle SIMD operationen 1 Cycle teuer, dann zogen 32 und 64Bit bezogenen Operationen größten teils nach(division z.B. ist immer noch sehr teuer, das war Intel P4 Zeit) und 8/16Bit wurden teurer. Mit moderneren CPU's 64Bit fähige waren nun die häufig genutzten 32Bit und aufwärts funktionen 1 cycle teuer und einige hatten noch kleine Latenzen aber die kleineren sind teuer geblieben, so zwischen so 12x und mehr langsamer als die equivalente.
Mit Sandy Bridge aufkommende Intel i3/5/7 Reihe und AMD X2/4/6 FX hat man angefanen die SIMD Operationen nochmal zu Optimieren, quasi SIMD SIMD xD
Man kann eine vec4 Multiplikation 3x machen und sie kostet nur 1 cycle(wenn alle Werte noch in den Registern liegen) und der 4. kostet dann den 2. cycle aber eine Multiplikation kostet auch 1 Cycle. Die CPU tut vorraus schauend diese Funktionalität verwenden und damit noch mehr BAM aus den einzelnen Kernen holen.
Es gibt auch indirect call und pointer access prediction, welche vorrausschauend schon speicherblöcke in den cache lädt, bevor die eigentliche anfrage erst kommt und führt den true case im dynamic branching aus, bevor überhaupt die Bedingung die Antwort zurück gibt, ob die CPU richtig liegt und eventuell zurück rudern muss(das sind die Magischen ~12Cycle Latenz, daher sollte man immer den häufigsten eintretenden Fall als wahre Kondition nehmen und den seltenen im Else Zweig packen).
Man sollte prinzipiell int dem char, short vorziehen, auch wenn es mehr Speicher braucht, ist es in der Regel inkl. Cache misses schneller.

strlen kann man naive wie folgt bauen(das echte strlen ist nicht sicher und kann auch bufferoverflow produzieren, wenn im speicherblock keine 0 drin ist).
Code:
  1. const char* p; for(p=str; *p != 0; ++p){} return p-str;

Da kann der compiler nicht viel machen, der macht für jedes *P == 0 ein byteweise vergleich und das Vergleichen kostet A cycle + B cyles latenz und das kopieren von *p in ein register noch C cycles. Also A+C+(0 bis B) cycles, das sollten ~20-30 cycles pro durchlauf sein(bei ner modernen cpu).
Die Funktion ist eh schon unsicher also kann man gleich so richtig dreckig werden und parallelisieren.
Dazu kann man die Schleife auflockern und z.B. mehrere Bytes vergleichen, bevor man in die nächste runde geht oder SIMD verwenden und mit leben dass man mal eben 15 Byte über den Speicherblock hinaus arbeiten kann.
Unaligned SIMD operationen sind extrem teuer und bei strings machen diese erst Sinn, wenn man entweder ein aligned String hat, was VC++, gcc und clang explizit schreiben, dass byte alignment keinen Einfluss auf strings im PE/ELF header hat(gambling for the win) oder mindestens 17 bytes(SIMD braucht 16Byte alignment und 1 byte mehr für ein unaligned string) lang sind.
Deswegen ist der assembly von so ziemlich allen low level intrinsics und c/c++ routinen ziemlich groß, weil erst bytealignment erreicht wird, dann mit korrekten byte alignment SIMD laufen lässt und dann die trailing byte noch eventuell ohne SIMD verarbeitet.
Üblich ist [code=http://de.wikipedia.org/wiki/Duff%E2%80%99s_Device]Duff's Device[/code] über labels in assembler zu verwenden um nicht aligned bytes zu verarbeiten, bis man byte alignment erreicht hat.
Gcc, VC++ und clang benutzen 8byte alignment, also selbst mit new ist man noch aufgeschmissen, wenn man ein byteoffset von 8 hat, man aber 16 byte offsets braucht.
Also muss man erstmal den Memory Allocator überschreiben, damit man selber noch sicher gehen kann, dass man 16Byte alignment erreicht(dazu einfach Speicher+15Byte alloziieren und entsprechend den pointer um N bytes verschieben).
Benutzt man ein festen String in einer Klasse/Struktur, dann sollte man sicher gehen, dass diese 16 byte alignment erzwingt(dazu hat gcc,clang und vc++ pragmas).
Nun kann man tatsächlich sicher gehen, dass SIMD operationen laufen und nicht die lahme byte by byte Verarbeitung.
Nun kommt das Problem, dass man bei 32Bit nur über extra parameter den Compiler dazu zwingen kann SIMD zu verwenden und wenn er dann auf ein System trifft was es nicht kann, dann crasht das ganze.
Bei 64Bit fähigen CPU's ist SSE2 immer verfügbar und deswegen bauen die dann auch SSE2 fähigen Code.
Leider sind viele Operationen für Strings in SSE3 und 4.2 verteilt, wieder pech ^^
Intel Compiler, QT und mein Radon Framework verwenden z.B. Funktion dispatcher um das Problem zu bewältigen.
Dabei wird die Funktion mit einem dispatcher code gestartet, der läuft durch, ersetzt sich und ruft die Funktion noch auf, damit der erste Aufruf korrekt arbeitet.
Alle folge Aufrufe laufen nun nicht auf die dispatcher Funktion sondern eine der Optimierten Varianten z.B. StrLenNaive, StrLenSSE2 oder StrLenSSE42.
Kein Crash, immer der beste Optimierte Code, keine abstrische bei der Optimierung nötig und auch kein overhead seitens Aufrufe.
In SSE4.2 gibt es eine Operation _mm_cmpestri, welche das 0 byte in einem 16 Byte vector sucht und die stelle zurück gibt, wenn es keine gibt, dann bekommt man 16 und macht den aufruf nochmal, bis man < 16 bekommt und die Summe ergibt den terminator, kostet pro aufruf 1cycle und zum vergleich 1 einziges byte zu vergleichen kostet ~30cycles und 16 entsprechend 480cycles.
Das ist natürlich erstmal nur interessant wenn man ein perfektes caching hat, das ist das nächste Problem, das gibt es leider nicht.
Ein Cache miss kostet so grob 120-160cycles, ist also der String am Ende der ersten Cache Page und geht bis zur Mitte der 2., dann hat man ein Cache Miss und man hat von den ultra tollen SSE nicht viel.
Deswegen sollte man auch seine Strings und Klassen mit festen Strings sehr genau angucken und Idealerweise so reservieren, dass er bei Pagebeginn los geht, also 64Byte Alignment für die meisten Systeme xD
Spätestens hier merkt man, wieso so ziemlich nix bzgl. Strings optimiert ist, weil man erstmal nen eigenen Memory Allocator braucht, der so ziemlich jede Kombination von String alloziierung und einbettung erkennt, CPUID/System API zum abfragen der CachePageSize und Caching verfahren(4Way, 8Way, ...) function dispatcher, Implementierungen für die einzelnen SIMD extensions und CPU Hersteller.

Nach den kleinen Tauchgang in die Hardware soll mal noch wer sagen, wieso man für Performante Binaries C++ verwendet und nicht Java, C# oder ähnliches ;) Weil man von Haus schon schneller ist(dank CPU Hersteller optimierter Code in den Compiler libs) und noch bis ins extrema viel viel schneller werden kann. Es ist halt ne Frage, wie viele Jahre man Zeit hat die STL, CRT neu zu schreiben oder eigenen Code auf Intel, AMD, ... assembly libs um zu schreiben und mit Performance Analysen ins Bett zu gehen xD.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 19:24 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
da fällt mir doch glatt was ein... http://gcc.godbolt.org/ :P

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Do Apr 17, 2014 21:14 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
Ich hab es schon indirekt erwähnt aber diese Teile kommen nicht von MS sondern Intel, MS verwendet diverse Bibliotheken von Intel, die in allen Bereichen Optimierte Varianten und auch den größten Teil der intrinsics liefert. Deswegen mag ich auch den Compiler nicht so sehr, weil kritische Funktionen wie strlen, strcmp auf Intel CPU's mit SSE optimiert sind aber auch nur SSE2.

Hast du erwähnt. Ich habe bloß nicht verstanden, was du daran schlecht findest. Niemand anderes als Intel selbst, sollte diese Funktionen wohl effizenter umsetzen können. Auch wenn es wohl nicht die absolut optimale Spitzenperformance auf AMD erreichen, aber auch wenigstens Gute. Ich finde absolut legitim, das Intel machen zu lassen. Die werden wohl auch am Besten wissen, ob mehr als SSE2 helfen würde. Immerhin braucht man dafür auch eine weitere Verzweigung die zb. bei kurzen Strings teuer kommen könnte. Wenn es nicht ums Rechnen geht, hilft AVX wahrscheinlich auch kaum, weil einfach der Speicher ausschlaggebend ist und nicht die Instruktionen selbst. In der Doku zur "Subroutine" Asmlib hier schneidet die Implementierung von Microsoft nicht unbedingt schlecht im Vergleich ab, auch wenn leider nicht die aktuellsten Versionen zum Vergleich herangezogen wurden.
Hier beschreibt zb. ein Microsoft Compilerentwickler gegen Ende wie AVX2 in bestehender Software zu starken Performanceeinbrüchen führen kann.
Hier würde ich mich auf jeden Fall nicht über die Implementierungen bei Microsoft beschweren. Die sind absolut konkurenzfähig.

Zitat:
strlen kommt zu 100% von Intel und kommt

Genau, du hast vorher aber geschrieben... "strlen, malloc, printf und so weiter sind auf Windows funktionen gemapped" Deshalb mein Kommentar.

Zitat:
tolower würde ich nicht mehr meine Hand ins Feuer legen

Ich hatte nachgeschaut und es ist eine Minifunktion aus der MSVCRT die in C implementiert ist.

Zitat:
Ich hatte schon mit ICU zu tun und mag es überhaupt nicht, das ding ist so riesig, da wirkt Boost und QT wie ein kleines projekt gegen.

Habe ich auch gehört, deshalb bin ich verunsichert. Weißt du da zufällig eine empfehlenswerte Alternative? Unicode am Besten auf UTF8/32 Basis, möglichst leichtgewichtig?

Zitat:
Man kann eine vec4 Multiplikation 3x machen und sie kostet nur 1 cycle

Der Intel Intrinsics Guide deutet Latenzen von bis 4-5 Zyklen an.

Zitat:
Man sollte prinzipiell int dem char, short vorziehen, auch wenn es mehr Speicher braucht, ist es in der Regel inkl. Cache misses schneller.

Wenn man ein ganzes Array davon hat wie bei einem String, glaube ich da eher nicht dran. Die CPU ist sehr schnell. 1 Byte aus 4 Byte ausschneiden wird kaum mehr kosten als ein Cachemiss. Je nachdem welcher Cache fehlschlägt, sind die Verzögerungen GEWALTIG. Insbesondere bei so stupiden Aufgaben wie bestimme die Länge von 10 000 Zeichen. Was genau gerechnet wird, ist da völlig irrelevant. Das einzige Problem ist es, schnell genug die Daten durch die Caches nachzuschaufeln. Konkret kann ich zum Beispieö von Horus mit seiner Partikelengine berichten, die inzwischen Datenorientiert verarbeitet werden um noch mehr rauszuholen. Die Indices testweise durch 16 Bit Integer zu ersetzen, soll "gewaltige"(für uns) Performanceschübe um bis zu ~30% gebracht haben, nur durch diese Umstellung im Kontext mit viel anderen Code außenrum, der ebenfalls Leistung frist.

Zitat:
Da kann der compiler nicht viel machen [...]

Du hattest doch geschrieben, dass "int8" wesentlich langsamer zu verarbeiten wäre als "int32". Ich meinte, der Compiler würde diese 8 Bit Operationen in 32 Bit Operationen umformen("emulieren"), wenn sie so langsam wären, schon alleine deswegen, weil es auf dem x64 keine 8 Bit Rechenbefehle mehr gibt.

Zitat:
const char* p; for(p=str; *p != 0; ++p){} return p-str;

Da gibt es ein Problemchen mit Const-Correctness bei "p". ;-)

Zitat:
Unaligned SIMD operationen sind extrem teuer

Soweit ich weiß soll das bei neueren CPUs also beispielweise Haswell wie meiner, weitgehend aufgehoben sein. Ist zwar nicht ganz so gut für den Cache, aber der Effekt ist bei richtigen Rechnungen bei neueren CPUs nicht mehr alles bestimmend beim SIMD.

Zitat:
z.B. Funktion dispatcher um das Problem zu bewältigen.

Wie hast du das konkret implementiert?
Kann das auf dem MSVC funktionieren?
Normalerweise sind die Pages des eigenen Maschinencode doch Schreibgeschützt eingebunden? Wie kann sich da etwas ersetzen?
Ich habe auf der Optimierungsseite von Agner(oben bei der Asmlib verlinkt) schonmal etwas davon gelesen, klang aber sehr kompliziert, platformabhänig und nicht wirklich überzeugend für mich. Inlining funktioniert dann auch nicht mehr?
Kann eine moderne Sprungvorhersage etwa eine solch statische Entscheidung nicht selbstständig vernümpftig auflösen?

Deine Lib finde ich übrigens sehr interessant, ich habe ja privat etwas leicht Ähnliches. Vlt. sollte ich mich mal bei dir inspirieren lassen, wie du solche Dinge gelöst hast.

Zitat:
Ein Cache miss kostet so grob 120-160cycles.

Man sollte, glaube ich, eher dafür sorgen, dass es gar nicht soweit kommt. Also die MB weise niederwertigen Cache die es zum Glück gibt, gut ausnutzen. Zb. durch kleine Datentypen, enge Packung und Datenorientierung. Die expliziten Prefetch und Streamanweisungen von SSE können auch einen netten Schub bringen.

Zitat:
Spätestens hier merkt man, wieso so ziemlich nix bzgl. Strings optimiert ist.

Na, das ist eigentlich auch nicht das, was ich mit "optimierter Stringklasse" für mich meinte. ^^
Überwiegend sind beim "std::string" nämlich die vielen kleinen Heap-Allokationen und die damit verbundene Fragmentierung. Nebenbei noch die schlechte Unterstützung von Unicode. DAS war eher das was ich meinte. Und wenn Unicode tatsächlich benötigt wird, helfen die ganzen LowLevel-Tricks leider eh nur noch wenig, da kommt ganz andere Komplexität ins Spiel.

Zitat:
wieso man für Performante Binaries C++ verwendet und nicht Java, C# oder ähnliches

Also eine gänige Aussage von MS ist ja, man würde besser optimieren können, weil die Zielplatform genau bekannt ist.
Allerdings in der Praxis totaler Schwachsinn, nachdem sie noch nichteinmal SSE1 SIMD unterstützen. Auch wenn es nach über 10 Jahren einen Ansatz gibt. Selbst Autovektorisierung darf man natürlich wieder vergessen, weil ja alles nebenher zur Laufzeit funktionieren muss und da fehlt es an Rechenzeit, wie auch in den Kommentaren steht.

Zitat:
dass er bei Pagebeginn los geht, also 64Byte Alignment für die meisten Systeme xD

Was hast du den für ein System? x86/x64 hat 4KB große Pages. Meinest du möglicherweise Cachelines? Ich habe meine Zweifel, das das in der Praxis bei durchschnittlich 11 Zeichen langen Strings nach deiner Angabe sinnvoll wäre. Dadurch würde viel Speicher verschwendet, am Ende jeder Cachline. Folglich würden viele ungenutze Daten mit den Cache geladen und das würde wiederum bedeuten, dass der Cache schlechter genutzt wird und damit niedrigere Performance durch mehr Cache-Misses. Ich könnte mir jedoch auch vorstellen, das man alleine durch geschickteres Memorylayout zb. von Strings man noch merklich etwas herausholen könnte.

EDIT:
Weil ich gerade mal spontan einen Blick in deine Lib geworfen habe...
Ich bin mir zum Beispiel ziemlich sicher, das diese Funktion...
Code:
  1. RFTYPE::UInt32 Math<T>::GetFastSinArrayElement(const T Angle)
  2. {
  3.     if(WasInitialized)
  4.     {
  5.         RFTYPE::UInt32 index=(FastSinArrayLen/(T)360)*(Angle%360);
  6.         return FastSinArray[index];
  7.     }
  8.     else
  9.     {
  10.         Init();
  11.         RFTYPE::UInt32 index=(FastSinArrayLen/(T)360)*(Angle%360);
  12.         return FastSinArray[index];
  13.     }
  14. }

... weder "Fast" noch genau ist. Gleitkommadivision durch 360 sollte ziemlich langsam sein. Erstmal eine vermeidbare Verzweigung die man hätte statisch auflösen können. Bei "Angle" sehe ich spontan ein Typsicherheitsproblem und der Compiler für Modulo keinen LowLevel-Trick findet, auch relativ langsam. Beim Zugriff in die Lookup-Daten eine hohe wahrscheinlichkeit eines Cachmisses. Sehr langsam. Die Genauigkeit ohne interpolation scheint mir auch nicht überzeugend. Da gibt es wesentlich bessere Approximationen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Fr Apr 18, 2014 01:45 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
OpenglerF hat geschrieben:
Zitat:
Ich hab es schon indirekt erwähnt aber diese Teile kommen nicht von MS sondern Intel, MS verwendet diverse Bibliotheken von Intel, die in allen Bereichen Optimierte Varianten und auch den größten Teil der intrinsics liefert. Deswegen mag ich auch den Compiler nicht so sehr, weil kritische Funktionen wie strlen, strcmp auf Intel CPU's mit SSE optimiert sind aber auch nur SSE2.

Hast du erwähnt. Ich habe bloß nicht verstanden, was du daran schlecht findest. Niemand anderes als Intel selbst, sollte diese Funktionen wohl effizenter umsetzen können. Auch wenn es wohl nicht die absolut optimale Spitzenperformance auf AMD erreichen, aber auch wenigstens Gute. Ich finde absolut legitim, das Intel machen zu lassen. Die werden wohl auch am Besten wissen, ob mehr als SSE2 helfen würde. Immerhin braucht man dafür auch eine weitere Verzweigung die zb. bei kurzen Strings teuer kommen könnte. Wenn es nicht ums Rechnen geht, hilft AVX wahrscheinlich auch kaum, weil einfach der Speicher ausschlaggebend ist und nicht die Instruktionen selbst. In der Doku zur "Subroutine" Asmlib hier schneidet die Implementierung von Microsoft nicht unbedingt schlecht im Vergleich ab, auch wenn leider nicht die aktuellsten Versionen zum Vergleich herangezogen wurden.
Hier beschreibt zb. ein Microsoft Compilerentwickler gegen Ende wie AVX2 in bestehender Software zu starken Performanceeinbrüchen führen kann.
Hier würde ich mich auf jeden Fall nicht über die Implementierungen bei Microsoft beschweren. Die sind absolut konkurenzfähig.

Ja das hab ich auch gelesen und wenn man dann in die Cycle Tabellen von Intel guckt dann frag ich mich was die Probleme verursacht, weil die Operationen sollten es nicht sein. Ich hab mit den AVX, AVX 2 und 512 nicht viel auseinander gesetzt, weil AMD gerade mal in der neuen K10 Reihe AVX supported und ich versuche meine Zeit möglichst Sinnvoll ein zu teilen und die Extensions sind einfach noch nicht weit genug verbreitet als das ich die Zeit gewillt bin zu investieren.

OpenglerF hat geschrieben:
Zitat:
strlen kommt zu 100% von Intel und kommt

Genau, du hast vorher aber geschrieben... "strlen, malloc, printf und so weiter sind auf Windows funktionen gemapped" Deshalb mein Kommentar.

Der Fehlerteufel! Ich hatte beim nachträglichen korrigieren der Listen das übersehen in die danach folgende Aufzählung zu übertragen.

OpenglerF hat geschrieben:
Zitat:
Ich hatte schon mit ICU zu tun und mag es überhaupt nicht, das ding ist so riesig, da wirkt Boost und QT wie ein kleines projekt gegen.

Habe ich auch gehört, deshalb bin ich verunsichert. Weißt du da zufällig eine empfehlenswerte Alternative? Unicode am Besten auf UTF8/32 Basis, möglichst leichtgewichtig?
Leider nein, das ist auch super kompliziert, weil alleine die lokalisierung von Zeiten ne katastrophe ist.
tzdata nennt sich die Datenbank für Zeit, die mindestens jedes Jahr 1mal geupdated wird, weil sich Sommer/Winterzeiten und andere Werte ändern.
Wähtungen und punktierung ändern sich zum glück eher selten aber dann gibt es ja noch die Code page Änderungen.
Je länger ich über Unicode nach denke, des so mehr bekomme ich Kopfweh.

OpenglerF hat geschrieben:
Zitat:
Man kann eine vec4 Multiplikation 3x machen und sie kostet nur 1 cycle

Der Intel Intrinsics Guide deutet Latenzen von bis 4-5 Zyklen an.

Kann gut sein, ich hab die Zahl von Agner.

OpenglerF hat geschrieben:
Zitat:
Man sollte prinzipiell int dem char, short vorziehen, auch wenn es mehr Speicher braucht, ist es in der Regel inkl. Cache misses schneller.

Wenn man ein ganzes Array davon hat wie bei einem String, glaube ich da eher nicht dran. Die CPU ist sehr schnell. 1 Byte aus 4 Byte ausschneiden wird kaum mehr kosten als ein Cachemiss. Je nachdem welcher Cache fehlschlägt, sind die Verzögerungen GEWALTIG. Insbesondere bei so stupiden Aufgaben wie bestimme die Länge von 10 000 Zeichen. Was genau gerechnet wird, ist da völlig irrelevant. Das einzige Problem ist es, schnell genug die Daten durch die Caches nachzuschaufeln. Konkret kann ich zum Beispieö von Horus mit seiner Partikelengine berichten, die inzwischen Datenorientiert verarbeitet werden um noch mehr rauszuholen. Die Indices testweise durch 16 Bit Integer zu ersetzen, soll "gewaltige"(für uns) Performanceschübe um bis zu ~30% gebracht haben, nur durch diese Umstellung im Kontext mit viel anderen Code außenrum, der ebenfalls Leistung frist.

Wir reden von 2 verschiedenen dingen, du redest von arrays und ich von struct/class variablen.
Bei arrays lohnt es sich das kleinste register zu nehmen, weil man sehr viele elemente verarbeitet und cache misses wesentlich teurer sind als die operationen, die auf dem array laufen und es durch simd noch viel deutlicher wird.
Klassen tendieren dazu einen cache miss zu verursachen, hier ist nur noch interessant wie schnell die zugriffe auf die member variablen sind und der compiler verhält sich da für signed 8 und 16 bit wie folgt. Konvertierung nach int, int operationen ausführen, konvertierung zurück.
Bei 32 und 64bit werden nur die operationen aus geführt.
Das findet man in der C++ Optimierungs PDF von Agner.
Ich hab nur 25% gefunden aber sehr interessant, das das prefetching und assume(kannte ich nicht mal) so viel bringen.

OpenglerF hat geschrieben:
Zitat:
Da kann der compiler nicht viel machen [...]

Du hattest doch geschrieben, dass "int8" wesentlich langsamer zu verarbeiten wäre als "int32". Ich meinte, der Compiler würde diese 8 Bit Operationen in 32 Bit Operationen umformen("emulieren"), wenn sie so langsam wären, schon alleine deswegen, weil es auf dem x64 keine 8 Bit Rechenbefehle mehr gibt.

Genau das Konvertieren macht int8 langsamer als int32 oder int64 aber ich hab nochmal geguckt wieviel das genau ist und keine exakten angaben gefunden da der compiler da je nach fall anders optimiert und man nicht genau sagen kann was nun zur konvertierung gehört. Ich würde da Agner seiner Konvention folgen, ausser wenn ich gezielt kleine structs/class baue, wo mehrere in eine page passen könnten, wenn ich z.B. enums packe(ist ein c++11 feature).

OpenglerF hat geschrieben:
Zitat:
Unaligned SIMD operationen sind extrem teuer

Soweit ich weiß soll das bei neueren CPUs also beispielweise Haswell wie meiner, weitgehend aufgehoben sein. Ist zwar nicht ganz so gut für den Cache, aber der Effekt ist bei richtigen Rechnungen bei neueren CPUs nicht mehr alles bestimmend beim SIMD.

Ja ist besser geworden aber selbst Agner hat in seiner lib noch nen duff's device vor und nach den aligned simd operationen in verwendung, von daher bau ich lieber auf sein wesentlich tiefergehendes Wissen und erfahrung ^^

OpenglerF hat geschrieben:
Zitat:
z.B. Funktion dispatcher um das Problem zu bewältigen.

Wie hast du das konkret implementiert?
Kann das auf dem MSVC funktionieren?
Normalerweise sind die Pages des eigenen Maschinencode doch Schreibgeschützt eingebunden? Wie kann sich da etwas ersetzen?
Ich habe auf der Optimierungsseite von Agner(oben bei der Asmlib verlinkt) schonmal etwas davon gelesen, klang aber sehr kompliziert, platformabhänig und nicht wirklich überzeugend für mich. Inlining funktioniert dann auch nicht mehr?
Kann eine moderne Sprungvorhersage etwa eine solch statische Entscheidung nicht selbstständig vernümpftig auflösen?

Deine Lib finde ich übrigens sehr interessant, ich habe ja privat etwas leicht Ähnliches. Vlt. sollte ich mich mal bei dir inspirieren lassen, wie du solche Dinge gelöst hast.

Da du schon in mein Code geguckt hast, funktions dispatcher verwende ich z.B. hier.
Ich verwende funktionspointer, vc++ und gcc verhalten sich bei diesen Konstrukt wie bei einem normalen funktionsaufruf auf eine globale funktion.
Es ist noch nicht das Ende, da ich überlege das Dispatchern aller anderen Funktionen aus dem Namespace wieder aus den einzelnen Dispatcher raus zu nehmen.
Was die komplexeren assembly dispatcher als Vorteil haben, ist das man nur einen hat und nicht für jeden Funktionstyp(was natürlich die binary größer macht aber nur ne handvoll bytes).

OpenglerF hat geschrieben:
Zitat:
wieso man für Performante Binaries C++ verwendet und nicht Java, C# oder ähnliches

Also eine gänige Aussage von MS ist ja, man würde besser optimieren können, weil die Zielplatform genau bekannt ist.
Allerdings in der Praxis totaler Schwachsinn, nachdem sie noch nichteinmal SSE1 SIMD unterstützen. Auch wenn es nach über 10 Jahren einen Ansatz gibt. Selbst Autovektorisierung darf man natürlich wieder vergessen, weil ja alles nebenher zur Laufzeit funktionieren muss und da fehlt es an Rechenzeit, wie auch in den Kommentaren steht.

LuaJit kann SSE ^^
Naja Jit hat ja auch Vorteile, hab ich gehört aber müssen die immer gleich ein Garbage Collector mit dran bamseln.
Das mag toll sein, wenn man nicht gerade 16ms Zeitfenster hat und der ich dann mehr Zeit investiere .net Komponenten komplett neu zu schreiben, damit die kein Garbage mehr erzeugen oder so wenig, dass der GC sehr kurz zuckt. Besser wird es noch, wenn man so unausgereifte Compiler wie mono oder vc# hat, die auf diversen Platformen nicht mal erlauben ein erzwungenes aufräumen des GC zu triggern.
Gott wie ich Unity und C# hassen gelernt habe und hab auch schon gleiche Ergebnisse mit D und Java in post mortems gelesen.

OpenglerF hat geschrieben:
Zitat:
dass er bei Pagebeginn los geht, also 64Byte Alignment für die meisten Systeme xD

Was hast du den für ein System? x86/x64 hat 4KB große Pages. Meinest du möglicherweise Cachelines? Ich habe meine Zweifel, das das in der Praxis bei durchschnittlich 11 Zeichen langen Strings nach deiner Angabe sinnvoll wäre. Dadurch würde viel Speicher verschwendet, am Ende jeder Cachline. Folglich würden viele ungenutze Daten mit den Cache geladen und das würde wiederum bedeuten, dass der Cache schlechter genutzt wird und damit niedrigere Performance durch mehr Cache-Misses. Ich könnte mir jedoch auch vorstellen, das man alleine durch geschickteres Memorylayout zb. von Strings man noch merklich etwas herausholen könnte.

Das siehst du richtig aber hast mit falsch verstanden. Was wohl daran liegt das ich nicht alles geschrieben hab was ich gedacht hab.
Lange strings, die über eine Cacheline hinaus gehen sollte man in einem 64Byte aligned speicher legen. Damit kannst du alle Cachelines mit aligned SIMD voll verarbeiten und sicher sein, dass es kein überlauf gibt. Die letzte Cacheline wird vieleicht nicht voll genutzt, im schlimmsten Fall nur 1Byte also 63Byte verschwendet aber du kannst dafür stumpf mit aligned SIMD operationen über alle genutzten Cachelines drüber rutschen.
So hab ich mich zumindestens für mein neues String Design entschieden. Jeder hat da andere Preferenzen.
Für Strings, die inklusive 0 terminierung kleiner als 17 byte(nicht string länge ;) ) sind nutz ich ein lokalen buffer in der Stringklasse.

OpenglerF hat geschrieben:
EDIT:
Weil ich gerade mal spontan einen Blick in deine Lib geworfen habe...
Ich bin mir zum Beispiel ziemlich sicher, das diese Funktion...
Code:
  1. RFTYPE::UInt32 Math<T>::GetFastSinArrayElement(const T Angle)
  2. {
  3.     if(WasInitialized)
  4.     {
  5.         RFTYPE::UInt32 index=(FastSinArrayLen/(T)360)*(Angle%360);
  6.         return FastSinArray[index];
  7.     }
  8.     else
  9.     {
  10.         Init();
  11.         RFTYPE::UInt32 index=(FastSinArrayLen/(T)360)*(Angle%360);
  12.         return FastSinArray[index];
  13.     }
  14. }

... weder "Fast" noch genau ist. Gleitkommadivision durch 360 sollte ziemlich langsam sein. Erstmal eine vermeidbare Verzweigung die man hätte statisch auflösen können. Bei "Angle" sehe ich spontan ein Typsicherheitsproblem und der Compiler für Modulo keinen LowLevel-Trick findet, auch relativ langsam. Beim Zugriff in die Lookup-Daten eine hohe wahrscheinlichkeit eines Cachmisses. Sehr langsam. Die Genauigkeit ohne interpolation scheint mir auch nicht überzeugend. Da gibt es wesentlich bessere Approximationen.

Der Code ist so alt, der hat schon nen Bart aber mich beruhigt es, dass der algorithmus nicht von mir ist sondern von einer Demo Scene seite war ^^
Die / optimiert der Compiler raus, wegen "constant folding" und das % ist wirklich lahm aber immer noch 10x schneller als sin selber aus zu rufen.
FastAndLessPreciseSin wäre der passendere Name und hab ich in meiner Bachelor Arbeit für Procedurale Textur generierung verwendet.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Fr Apr 18, 2014 10:02 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 587
Programmiersprache: C++
OpenglerF hat geschrieben:
Zitat:
const char* p; for(p=str; *p != 0; ++p){} return p-str;

Da gibt es ein Problemchen mit Const-Correctness bei "p". ;-)
Nö. p darf modifiziert werden, nur *p darf nicht.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Fr Apr 18, 2014 13:06 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Zitat:
Nö. p darf modifiziert werden, nur *p darf nicht.

... und du hast recht. :evil:
Verflucht. Das hatte tatsächlich immer falsch verstanden. Ich war irgendwie der festen Überzeugung, bei der Deklaration wäre sowohl der Pointer als auch der "Char" konstant...
Peinlich. Ich kann gar nicht aufzählen, wie oft ich das bisher wahrscheinlich falsch gemacht habe.

Zitat:
Ich hab mit den AVX, AVX 2 und 512 nicht viel auseinander gesetzt, weil AMD gerade mal in der neuen K10 Reihe AVX supported

Ich denke, AVX wird langsam relevant. Ich schätze, das schon mindestens etwa die Hälfte der potentiellen Nutzer AVX zur Verfügung hätten.

Zitat:
wo mehrere in eine page passen könnten

Die Dinger heißen Cachelines... :P

Zitat:
, vc++ und gcc verhalten sich bei diesen Konstrukt wie bei einem normalen funktionsaufruf auf eine globale funktion.

Muss ich mal ausprobieren. Ich würde bloß vermuten, dass es einen indirekten Funktionsaufruf gibt, der bekanntlich sehr negative Auswirkungen auf die Performance hat, weil es einen Pipeline-Stall gibt und die Sprungvorhersage daran scheitert. Da wäre ich mir nicht sicher, ob normale Verzweigungen da nicht im Vorteil wären?

Zitat:
LuaJit kann SSE ^^

SSE sollte .Net auch können. Die Frage ist, kann es SIMD? Ohne SIMD bringen die meisten neuen CPU Features erstmal nicht wirklich sehr viel.

Zitat:
aber müssen die immer gleich ein Garbage Collector mit dran bamseln.

Meistens ist der halt, um es mit einem Wort zu beschreiben, einfach überflüssig.
D hat aber auch native Unterstützung für Speicherverwaltung ohne GC. Leider ist die StdLib leider nicht unbedingt darauf ausgelegt, deswegen muss man auch wieder selbst Hand anlegen, aber besser als nichts.
Nur so große Verzögerungen wie du immer angibst, kann ich aus persönlicher Erfahrung nicht wirklich bestätigen und manchmal bei komplexeren Beziehungen zwischen den Objekten, kann er optional auch recht praktisch sein.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Welche Sprache ist Zeitgemäss
BeitragVerfasst: Fr Apr 18, 2014 13:28 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
Steam listet leider noch nicht AVX, um genaue Infos zu bekommen aber unter 50% der Leute haben 4 oder mehr Kerne und da glaube ich sehr Stark dran, dass die Verbreitung noch weit von 50% entfernt ist.

Zitat:
Meistens ist der halt, um es mit einem Wort zu beschreiben, einfach überflüssig.
D hat aber auch native Unterstützung für Speicherverwaltung ohne GC. Leider ist die StdLib leider nicht unbedingt darauf ausgelegt, deswegen muss man auch wieder selbst Hand anlegen, aber besser als nichts.
Nur so große Verzögerungen wie du immer angibst, kann ich aus persönlicher Erfahrung nicht wirklich bestätigen.

Ich hab ja garkeine Werte angegeben :p
In dem Artikel, den ich diese Woche gelesen habe waren es aber 4ms, die nach der Optimierung noch pro Frame in GC verharrt wurde.
Mein Kollege baut ein Atroid Shooter für alle gängigen Mobile und Consolen, mit Unity und der verbringt auch sehr viel Zeit damit seine Code um zu bauen, weil der GC die 16ms Zeit für ein Frame überschritten hatte.
Mono sein StringBuilder macht ne menge Garbage, daher hatte er ein eigenen bauen müssen und dann war das auch wieder im Rahmen.
Die StringBuilder Klasse ist aber genau für das wenig Garbage erzeugen da, ein großer Buffer wird angelegt und auf dem werden die stringoperationen gemacht, statt viele kleine String objekte zu erzeugen.
Wenn ich noch dazu denke, auf was ich und Kollegen aus dem Hamburger Office schon auf Compiler Bugs gestossen sind, da rate ich lieber die Finger von modernen Compilern zu lassen und erst ein paar Versionen ins Land verstreichen zu lassen.
Zum experimentieren ist das kein Problem aber sobald man sein Geld damit verdient sollte man Abstand nehmen.

Genauso wie mit Emscripten, wir sollen ein Spiel damit shippen, damit wir nicht den Anschluss zu Unreal Engine 4 und Unity3d 5 verlieren, weil die ja auch damit webgl based Games bauen können. Doch ist die ganze Sache noch viel zu jung und unausgereift, als das man darauf als Vertriebsplatform setzen sollte.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 83 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3, 4, 5, 6  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 34 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.157s | 18 Queries | GZIP : On ]