Autor Beitrag
hjl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22
Erhaltene Danke: 2

Windows 10 Enterprise (64 Bit)
Delphi 7, Delphi XE2, Delphi Berlin (10.1), Delphi Tokyo (10.2)
BeitragVerfasst: Fr 07.10.16 09:22 
Hallo,
neulich habe ich hier erfahren, dass der Datentyp Extended auf 64-Bit-Anwendungen nicht wie auf 32-Bit-Anwendungen 10 Bytes,
sondern nur noch 8 Bytes groß ist, also so groß wie Double.

Nun hat es mir den Anschein, dass ich jetzt auch erfahren habe, warum das so ist.
Auf der Webseite von Embarcadero

docwiki.embarcadero...._auf_Double_(Delphi)

fand ich folgende Hinweise:

Zitat:
Gleitkommaoperationen mit einer "extended"-Genauigkeit werden von Delphi-Compilern für 32-Bit-Plattformen, aber nicht von Delphi-Compilern für 64-Bit-Plattformen unterstützt.

In Delphi-Compilern für 64-Bit-Plattformen wurde die Genauigkeit von Gleitkommaberechnungen von extended (10-Byte-Werte) auf double (8-Byte-Werte) reduziert. Die Verwendung von Gleitkommawerten mit der Genauigkeit "extended" wird nicht empfohlen. Die Intel x86-Architektur unterstützt reelle 10-Byte-Datentypen, aber der Trend bei neuen Prozessorarchitekturen geht zum parallelen Ausführen von Gleitkommaberechnungen mit einer Genauigkeit von höchstens "double" (siehe Intel® Streaming SIMD Extensions).


Daraus schließe ich, dass in 32-Bit-Anwendungen Extended-Berechnungen in mehreren gleichzeitig laufenden Threads in den heutigen Mehrprozessorkern-Systemen nicht mehr durchgeführt werden können.


Wie ich darauf komme?
Nach dem ich zuerst eine 64-Bit-Anwendung mit Multithreading-Betrieb mit Delphi Berlin (10.1) erstellte, die aber möglicherweise wegen der Extended-Beschränkung nicht die erwarteten Ergebnisse brachte, stellte ich auf 32 Bit um, damit Extended wieder 10 Bytes groß ist.
Doch während die 64-Bit-Anwendung ohne Laufzeitprobleme läuft, gibt es in der 32-Bit-Anwendung gleich am Programmanfang stets Thread-Abstürze.

Das Multithreading habe ich mit der Delphi Class TThread realisiert, was ja auch bereits in Delphi 7 schon machbar war.
Jeder Thread führt Berechnungen mit Extended-Variablen aus und läuft von alleine zu Ende, teilweise zeitgleich mit anderen Threads.
Mein Rechner ist ein 4-Prozessorkern-Rechner mit einem 64-Bit-Betriebssystem Windows 7.
Im Debugging kam stets die Meldung "floating point invalid operation at ..." auf einer Addition-Anweisung mit sehr kleinen Extended-Zahlen im Bereich von E-20.
Da Fehlermeldungen bekanntlich nicht immer den Kern des Problems treffen, habe ich das Programm auf Zugriffskonflikte untersucht, jedoch ohne dabei fündig zu werden.


Meine Frage ist: Habe ich die Sätze von der Embarcadero-Webseite mit meiner darunter stehenden Schlussfolgerung richtig verstanden?

Auch Anmerkungen dazu sind mir willkommen.
LG hjl
t.roller
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 118
Erhaltene Danke: 34



BeitragVerfasst: Fr 07.10.16 12:36 
TExtended80Rec ermöglicht unter Win64 die Durchführung von speicherbezogenen Operationen mit 10-Bit-Gleitkommavariablen, aber keine arithmetischen Operationen mit der Genauigkeit "extended".

docwiki.embarcadero....ystem.TExtended80Rec

Im Anhang beide Programme als EXE, wer es nicht compilieren kann.

64-Bit:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
program ProjectConsole64;  //20161007
  {$APPTYPE CONSOLE}
 
  {$R *.res}

  uses
    System.SysUtils;

  begin
    try
      writeln('NativeInt: ', SizeOf(NativeInt)); // 4 or 8
      writeln('Extended: ', SizeOf(Extended)); // 10 or 8
      writeln('Extended80: ', SizeOf(Extended80)); // 10
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message)
    end;
    readln
  end.


32-Bit:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
program ProjectConsole32;  //20161007
  {$APPTYPE CONSOLE}
 
  {$R *.res}

  uses
    System.SysUtils;

  begin
    try
      writeln('NativeInt: ', SizeOf(NativeInt)); // 4 or 8
      writeln('Extended: ', SizeOf(Extended)); // 10 or 8
      writeln('Extended80: ', SizeOf(Extended80)); // 10
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message)
    end;
    readln
  end.
Einloggen, um Attachments anzusehen!

Für diesen Beitrag haben gedankt: hjl
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Fr 07.10.16 13:30 
Du hast das schon richtig verstanden was die da schreiben - es ist aber (sorry) Bullshit. Also da stimmt eigentlich nix.

Richtig ist, dass die "alten" (bis Intel P6?) FPUs nur seriell gearbeitet haben und denen die Datengröße deswegen im Prinzip egal war. Man hat dann 80bit als nativen Typ genommen weil das mit der 63/64bit Mantisse und 16bit Exponent wieder schön adressierbare (in Register ladbare) Größen ergibt. Erweiterungen wie 3DNow! oder die ersten MMX waren dementsprechend wirklich irgendwo Erweiterungen die da dran vorbei mussten, um mehrere Single- oder Double Operationen in einem Rutsch durchzuführen. Sieht man auch schön daran dass man damals die CPU zwischen Float- und MMX-Modus umschalten musste.

Moderne FPUs sind prinzipiell schon im Silizium mehr darauf ausgelegt, 128bit-Operationen am Stück zu machen (mit AMD AVX bis zu 512bit, bin mir aber nicht sicher ob das vielleicht nur Microcode ist). Man hat deswegen im amd64-ABI drauf verzichtet, nochmal extra einen Fließkommatyp herauszuführen für eine Größe, die die Hardware gar nicht mehr her gibt (jede Operation müsste auf 128bit aufgeblasen werden, geht aber nicht mehr so schön auf).
Wie man sich einfach ausrechnen kann passen da rein:
Streaming SIMD Extensions hat folgendes geschrieben:
two 64-bit double-precision floating point numbers or
two 64-bit integers or
four 32-bit integers or
eight 16-bit short integers or
sixteen 8-bit bytes or characters.

Es ist wirklich so, dass die CPU im Rahmen der Out-of-Order-Execution gegebenenfalls komplett unabhängige Berechnungen in einem SSE-Register zusammenfasst, wenn zum Beispiel von zwei Kernen gleichzeitig ein "FADD" kommt. Das ist aber schwarze Magie und muss uns eigentlich außerhalb des HPC-Bereichs nicht interessieren.


Und jetzt kommt der große Nachteil von Delphi: man hat es m.W. bis heute nicht auf die Latte bekommen, dem Compiler long double/quad/float128-Support beizubringen. Den würde man eigentlich fast schon "umsonst" bekommen.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."

Für diesen Beitrag haben gedankt: hjl
hjl Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22
Erhaltene Danke: 2

Windows 10 Enterprise (64 Bit)
Delphi 7, Delphi XE2, Delphi Berlin (10.1), Delphi Tokyo (10.2)
BeitragVerfasst: Mo 06.11.17 09:38 
Inzwischen bin ich zur Erkenntnis gekommen, dass 32Bit-Programme durchaus auch mit Extended-Variablen im Multithreading-Betrieb laufen können.
Das besagte Programm ist inzwischen weiter entwickelt, dabei mehrfach geändert worden.
Weil Zahlen mit höherer Genauigkeit verlangt wurden, war es dennoch wieder mal ausprobiert worden und es funktionierte.
Leider kann ich nicht sagen, was einst wirklich die Ursache für das Problem war, sorry.

An einer anderen Stelle berichte ich über ein weiteres Problem mit Extended-Variablen,
wobei ich dann wieder mal auf der Embarcadero-Webseite eine Warnung vor der Verwendung von Extended-Variablen in 32 Bit fand.
Doch darüber, wie gesagt, in einem neuen Thread in diesem Forum.
mael
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 198
Erhaltene Danke: 39


Delphi XE3 Prof.
BeitragVerfasst: Mi 22.05.19 20:59 
Möglicherweise lag es daran dass eine DLL oder Routine in einem anderen Thread die FPU-Steuerung geändert hat.
Deswegen gibt es auch SafeLoadLibrary.

Um die FPU-Steuerung explizit zu beeinflussen (auch vom gleichen Thread) gibt es die Befehle Set8087CW und SetExceptionMask. Set8087CW ist anscheinend nicht thread-safe.

Siehe auch hier:

stackoverflow.com/qu...xcsr-and-twebbrowser

All dies könnten Ursachen gewesen sein.