Exotische Architekturen, die den Normungsgremien am Herzen liegen

154

Ich weiß, dass die C- und C ++ - Standards viele Aspekte der Sprachimplementierung definiert lassen, nur weil es bei einer Architektur mit anderen Merkmalen sehr schwierig oder unmöglich wäre, einen standardkonformen Compiler dafür zu schreiben.

Ich weiß, dass vor 40 Jahren jeder Computer seine eigene Spezifikation hatte. Ich kenne jedoch keine Architekturen, die heute verwendet werden, wo:

  • CHAR_BIT != 8
  • signed ist nicht die Ergänzung von zwei (ich habe gehört, Java hatte Probleme mit diesem).
  • Gleitkomma ist nicht IEEE 754-kompatibel (Bearbeiten: Ich meinte "nicht in IEEE 754-Binärcodierung").

Der Grund, den ich frage, ist, dass ich den Leuten oft erkläre, dass es gut ist, dass C ++ keine anderen Aspekte auf niedriger Ebene wie Typen mit fester Größe vorschreibt . Es ist gut, weil es Ihren Code im Gegensatz zu "anderen Sprachen" bei korrekter Verwendung portabel macht (Bearbeiten: weil er auf mehr Architekturen portiert werden kann, ohne dass Emulationen von Aspekten der Maschine auf niedriger Ebene erforderlich sind, wie z. B. die Zweierkomplementarithmetik auf der Architektur mit Vorzeichen + Größe). . Aber ich fühle mich schlecht, dass ich selbst nicht auf eine bestimmte Architektur verweisen kann.

Die Frage ist also: Welche Architekturen weisen die oben genannten Eigenschaften auf?

uint*_ts sind optional.

Yakov Galka
quelle
9
Ich denke du hast es rückwärts. Wenn das C ++ beispielsweise zwei Komplemente für vorzeichenbehaftete Ganzzahlen vorschreiben würde, würde dies den C ++ - Code portabler machen und nicht weniger. Die Frage, warum das C ++ - Standardkomitee dies nicht vorschreibt, ist eine andere Frage. Zumal es trotz Ihrer Aussagen nicht unmöglich ist , einen Compiler für eine nicht standardmäßige Architektur zu schreiben, können Sie immer 8-Bit-Zeichen oder Zweierkomplement-Arithmetik simulieren, auch wenn Ihre Plattform dies nicht direkt unterstützt.
John
8
@ John: Dann wäre es unpraktisch, wenn ein nicht standardkonformer Compiler schnelleren Code generieren würde als ein konformer. Und ich sehe immer noch nicht, wie es Ihren Code portabler macht.
Yakov Galka
4
Ich bin sicher, der wahre Grund dafür ist nicht, dass es sich um eine ideale Lösung handelt. Stattdessen gab es zu dem Zeitpunkt, als der Standard geschrieben wurde, bereits viele C- und C ++ - Compiler, und das Standardkomitee wollte vorhandene Compiler nicht ablehnen.
John
4
@john: Ich bezweifle, dass "es für Compiler-Autoren einfacher zu machen" eine Priorität bei der Erstellung des C ++ - Standards ist (sie würden einen schrecklichen Job machen, wenn es so wäre, da C ++ eine der am schwierigsten zu analysierenden Sprachen und andere Aspekte von ist Die Sprache macht es auch Compiler-Autoren nicht gerade einfach. Leistung, breite Plattformunterstützung und Abwärtskompatibilität sind jedoch sehr wichtig. Und all diese drei würden leiden, wenn die von Ihnen erwähnten Einschränkungen zum Standard hinzugefügt würden.
Sander De Dycker
5
Es geht nicht um den Compiler, sondern um die Hardware. C ++ lässt einige Dinge nicht spezifiziert, um die direkte Verwendung der Hardwarefunktionen zu ermöglichen. Ihre Telefon-Apps werden ohnehin nicht auf einem Mainframe ausgeführt, daher gibt es keine Portabilität, egal wie konform der Code ist.
Bo Persson

Antworten:

114

Schauen Sie sich diesen an

Unisys ClearPath Dorado Server

bietet Abwärtskompatibilität für Personen, die noch nicht ihre gesamte Univac-Software migriert haben.

Wichtige Punkte:

  • 36-Bit-Wörter
  • CHAR_BIT == 9
  • eine Ergänzung
  • 72-Bit-Gleitkomma ohne IEEE
  • separater Adressraum für Code und Daten
  • wortadressiert
  • Kein dedizierter Stapelzeiger

Ich weiß nicht, ob sie einen C ++ - Compiler anbieten, aber sie könnten .


Und jetzt ist ein Link zu einer aktuellen Ausgabe ihres C-Handbuchs aufgetaucht:

Unisys C Compiler Programmierreferenzhandbuch

Abschnitt 4.5 enthält eine Tabelle mit Datentypen mit 9, 18, 36 und 72 Bit.

Größe und Bereich der Datentypen im USC C-Compiler

Bo Persson
quelle
13
Ich denke, void * muss höllisch sein, um es in dieser Architektur zu verwenden.
luiscubal
13
@ybungalobill - Ich glaube char*und void*muss die gleiche Größe und groß genug sein, um jeden anderen Zeiger zu halten. Der Rest liegt bei der Umsetzung.
Bo Persson
22
@ybungalobill: Auf alten Win16-Compilern waren reguläre Zeiger in der Nähe von Zeigern und enthielten nur einen 16-Bit-Offset sizeof(int*) == 2, aber Fernzeiger hatten auch einen 16-Bit-Selektor sizeof(void*) == 4.
Adam Rosenfield
10
Es gibt oder gab früher ein Online-Handbuch für den C ++ - Compiler. Es ist auch erwähnenswert, dass dies nur eine der Unisys-Mainframe-Architekturen ist: Die andere ist eine 48-Bit-Architektur mit vorzeichenbehafteter Magnitude (für die ich nur ein C-Handbuch gefunden habe, kein C ++). Was den Rest betrifft: Ich denke das sizeof(int*) != sizeof(char*)hier nicht: beide sind 36 Bit. Der Byteselektor in the char*befindet sich jedoch auf den höherwertigen Bits und wird in ignoriert int*. (Ich habe jedoch andere Maschinen verwendet, bei denen `sizeof (char *)> sizeof (int *).)
James Kanze
16
@Adam Rosenfield Auf den MS / DOS 16-Bit-Compilern gab es verschiedene "Modi", und Datenzeiger hatten nicht unbedingt die gleiche Größe wie Funktionszeiger. Aber zumindest bei denen, die ich verwendet habe, hatten alle Datenzeiger (einschließlich void*) immer die gleiche Größe. (Natürlich konnten Sie einen Funktionszeiger nicht in konvertieren void*, da dieser void*möglicherweise kleiner ist. Aber gemäß dem Standard können Sie dies auch heute nicht tun.)
James Kanze
51

Keine Ihrer Annahmen gilt für Mainframes. Für den Anfang kenne ich keinen Mainframe, der IEEE 754 verwendet: IBM verwendet Gleitkomma auf Basis 16, und beide Unisys-Mainframes verwenden Basis 8. Die Unisys-Maschinen sind in vielerlei Hinsicht etwas Besonderes: Bo hat den 2200 erwähnt Architektur, aber die MPS-Architektur ist noch seltsamer: 48-Bit-Wörter. (Ob das Wort ein Zeiger ist oder nicht, hängt von einem Bit im Wort ab.) Und die numerischen Darstellungen sind so gestaltet, dass es keinen wirklichen Unterschied zwischen Gleitkomma- und Integralarithmetik gibt: Der Gleitkomma ist Basis 8; Es erfordert keine Normalisierung und setzt im Gegensatz zu jedem anderen Gleitkomma, das ich gesehen habe, die Dezimalstelle rechts von der Mantisse und nicht links von der Mantisse und verwendet die vorzeichenbehaftete Größe für den Exponenten (zusätzlich zur Mantisse). Mit den Ergebnissen, dass ein integraler Gleitkommawert genau dieselbe Bitdarstellung hat (oder haben kann) wie eine Ganzzahl mit vorzeichenbehafteter Größe. Und es gibt keine Gleitkomma-Arithmetikbefehle: Wenn die Exponenten der beiden Werte beide 0 sind, führt der Befehl eine Integralarithmetik aus, andernfalls eine Gleitkomma-Arithmetik. (Eine Fortsetzung der Tagging-Philosophie in der Architektur.) Was bedeutet, dass währendint kann 48 Bits belegen, 8 davon müssen 0 sein, oder der Wert wird nicht als Ganzzahl behandelt.

James Kanze
quelle
4
IBM Mainframes (z / Architecture) unterstützen IEE754-Gleitkommazahlen.
Nikita Nemkin
1
fyi siehe diesen Twitter-Kommentar
Shafik Yaghmour
6
@ Nikita - Sie tun es jetzt . Anfangs war es ein (teures) Add-On zur Unterstützung von Java.
Bo Persson
42

Eine vollständige IEEE 754-Konformität ist bei Gleitkommaimplementierungen selten. Eine diesbezügliche Schwächung der Spezifikation ermöglicht viele Optimierungen.

Beispielsweise unterscheidet sich die Subnorm-Unterstützung zwischen x87 und SSE.

Optimierungen wie das Zusammenführen einer Multiplikation und Addition, die im Quellcode getrennt waren, ändern ebenfalls geringfügig die Ergebnisse, sind jedoch bei einigen Architekturen eine gute Optimierung.

Unter x86 erfordert die strikte IEEE-Konformität möglicherweise das Setzen bestimmter Flags oder zusätzliche Übertragungen zwischen Gleitkommaregistern und normalem Speicher, um die Verwendung des angegebenen Gleitkommatyps anstelle der internen 80-Bit-Gleitkommazahlen zu erzwingen.

Und einige Plattformen haben überhaupt keine Hardware-Floats und müssen sie daher in Software emulieren. Einige der Anforderungen von IEEE 754 sind möglicherweise teuer in der Implementierung in Software. Insbesondere die Rundungsregeln könnten ein Problem sein.

Mein Fazit ist, dass Sie keine exotischen Architekturen benötigen, um in Situationen zu geraten, in denen Sie nicht immer die strikte IEEE-Konformität garantieren möchten. Aus diesem Grund garantieren nur wenige Programmiersprachen eine strikte IEEE-Konformität.

CodesInChaos
quelle
7
Ein weiterer "exotischer" Satz von Hardware sind IBM-Mainframes, bei denen das Gleitkommaformat vor dem IEEE-Standard liegt. Im Gegensatz zu Java kann C ++ weiterhin die vorhandene Hardware verwenden.
Bo Persson
5
IEEE 754 wird von GPUs nicht vollständig unterstützt.
Zerem
3
Die mangelnde strikte Einhaltung von IEEE 754 ist für einige ein Problem, aber ich denke nicht, dass dies im Rahmen der Probleme liegt, die das OP wirklich interessiert.
Omnifarious
3
@Matthieu Da dies auch mit "C" gekennzeichnet ist, sollte ich einen C-Analysator erwähnen, der Ihnen alle Werte mitteilen kann, die Ihr Gleitkommaprogramm mit 80-Bit-Gleitkommaregistern annehmen kann, die nach Lust und Laune des C-Compilers in den Speicher verschüttet werden. blog.frama-c.com/index.php?post/2011/03/03/cosine-for-real
Pascal Cuoq
2
@MatthieuM.: Es ist schade, dass ISO / ANSI nicht zuließ, dass verschiedene Parameter minimale / maximale Größen für Gleitkomma- und Ganzzahlargumente angeben. Wenn dies der Fall gewesen wäre, hätte das 80-Bit long doubleein nützlicher und langlebiger Typ sein können, da das einzige wirkliche Problem darin bestand, dass es schlecht funktioniert printf. Die Tatsache, dass das erweiterte Doppel die führende 1 speichert, beschleunigt die Berechnungen auf Nicht-FPU-Systemen explizit und würde auch die Notwendigkeit einer speziellen Behandlung von Denormalen in einem anderen Kontext als der Konvertierung zu / von anderen Typen beseitigen. Schade, dass C printfalles durcheinander gebracht hat.
Supercat
40

Ich habe diesen Link gefunden, in dem einige Systeme aufgelistet sind, bei denen CHAR_BIT != 8. Sie beinhalten

Einige TI-DSPs haben CHAR_BIT == 16

BlueCore-5-Chip (ein Bluetooth-Chip von Cambridge Silicon Radio), der hat CHAR_BIT == 16.

Und natürlich gibt es eine Frage zum Stapelüberlauf: Welche Plattformen haben etwas anderes als 8-Bit-Zeichen?

Was Nicht-Zwei-Komplement-Systeme betrifft, gibt es eine interessante Lektüre auf comp.lang.c ++. Moderiert . Zusammenfassend: Es gibt Plattformen mit einer Komplement- oder Vorzeichen- und Größenrepräsentation.

dcn
quelle
5
Analoge Geräte 32-Bit-SHARC-DSP hat CHAR_BIT=32und Texas Instruments DSP von TMS32F28xx hat CHAR_BIT=16. GCC 3.2 für PDP-10 hat CHAR_BIT=9. Ich denke, S / 360 hat möglicherweise auch ein Nicht-8-Bit-Zeichen.
Osgx
1
Ich hätte immer noch gerne ein Beispiel für "Nicht-Zwei-Komplement" -Architekturen. Zumal es passiert ist, dass das CHAR_BITSein Teilduplikat ist.
Yakov Galka
TI-DSPs haben nur 16-Bit-Zeichen, weil die Implementierer sie ausgewählt haben (es wäre ein bisschen mehr Arbeit, um sie richtig zum Laufen zu bringen, aber kein absurd hartes IIRC - wahrscheinlich nur einige "Löcher" im Codegen-Gerüst im zugrunde liegenden Compiler). . Es ist also kein tiefer architektonischer Grund. C-Code funktioniert auf einer abstrakten Maschine. Wenn Sie nur 16-Bit-INTs haben, speichern Sie jeweils zwei Zeichen und fügen Sie dem Gucklochoptimierer (zumindest) Lese-, Änderungs- und Schreibzusammenführung hinzu. Sicher, es ist mehr Arbeit, aber schauen Sie sich nur an, wie viel mehr Arbeit jeder für sich hat, um mit solchen seltsamen Typen an Orten umzugehen, an denen sie nie auftauchen werden. Yuck.
Setzen Sie Monica
24

Ich bin mir ziemlich sicher, dass VAX-Systeme noch verwendet werden. Sie unterstützen kein IEEE-Gleitkomma. Sie verwenden ihre eigenen Formate. Alpha unterstützt sowohl VAX- als auch IEEE-Gleitkommaformate.

Cray-Vektor-Maschinen wie die T90 haben ebenfalls ein eigenes Gleitkomma-Format, obwohl neuere Cray-Systeme IEEE verwenden. (Der von mir verwendete T90 wurde vor einigen Jahren außer Betrieb genommen. Ich weiß nicht, ob noch einige aktiv sind.)

Der T90 hatte / hat auch einige interessante Darstellungen für Zeiger und ganze Zahlen. Eine native Adresse kann nur auf ein 64-Bit-Wort verweisen. Die C- und C ++ - Compiler hatten CHAR_BIT == 8 (erforderlich, da Unicos, eine Unix-Variante, ausgeführt wurde und mit anderen Systemen zusammenarbeiten musste), aber eine native Adresse konnte nur auf ein 64-Bit-Wort verweisen. Alle Byte-Ebene Operationen wurden durch den Compiler synthetisiert, und ein void*oder char*ein Byte in den höherwertigen 3 Bits des Wortes Offset gespeichert. Und ich denke, einige ganzzahlige Typen hatten Füllbits.

IBM Mainframes sind ein weiteres Beispiel.

Andererseits müssen diese speziellen Systeme Änderungen des Sprachstandards nicht unbedingt ausschließen. Cray zeigte kein besonderes Interesse daran, seinen C-Compiler auf C99 zu aktualisieren. vermutlich dasselbe gilt für den C ++ - Compiler. Es könnte angemessen sein , die Anforderungen für gehostete Implementierungen, wie erforderlich CHAR_BIT == 8, IEEE - Format Gleitkommazahlen , wenn nicht die vollständige Semantik und 2's-Ergänzung ohne Füllbits für signierte ganze Zahlen zu straffen. Alte Systeme könnten weiterhin frühere Sprachstandards unterstützen (C90 starb nicht, als C99 herauskam), und die Anforderungen für freistehende Implementierungen (eingebettete Systeme) wie DSPs könnten geringer sein.

Andererseits könnte es gute Gründe für zukünftige Systeme geben, Dinge zu tun, die heute als exotisch gelten würden.

Keith Thompson
quelle
6
Ein guter Punkt am Ende, wie zu strenge Standards Innovationen verhindern. Wenn wir Quantencomputer (oder organische Computer) mit trinären Zuständen erhalten, sind die Anforderungen an die Modulo-Arithmetik für unsignedintegrale Typen ein großer Schmerz, während die signierte Arithmetik in Ordnung ist.
Ben Voigt
@ BenVoigt Warum ist diese vorzeichenlose Arithmetik ein Schmerz? Ist Modulo 3 ^ n Addierer in diesen Computern nicht nicht möglich?
Phuclv
2
@ LưuVĩnhPhúc: Genau das ist der Punkt, wenn Hardwareoperationen modulo 3 ** n ausgeführt werden und es schwierig sein wird, vorzeichenlose C ++ - Typen bereitzustellen, deren Operationen modulo 2 ** n definiert sind.
Ben Voigt
2
Ich kenne einen VAX 11/780, der noch als Host für einen Cross-Compiler verwendet wird, der auf ein spezialisiertes eingebettetes System mit einer proprietären Architektur abzielt. Um diesen speziellen VAX aufrechtzuerhalten, haben sich die Depotbanken an Museen gewandt, um Ersatzteile zu erhalten.
Peter
2
@Keith - technisch gesehen besteht das einzige Hindernis darin, einen Prozess zu durchlaufen, um Beweise zu liefern, die den gesetzlichen Anforderungen entsprechen, da das eingebettete Zielsystem eine hohe Kritikalität aufweist. Es gibt jedoch eine Reihe nichttechnischer Hindernisse (Organisationspolitik usw.), die bisher unüberwindbar waren. Derzeit ist es einfacher, einen Fall für die Razzia in Museen bereitzustellen, als den Host zu aktualisieren.
Peter
16

CHAR_BITS

Laut gcc Quellcode:

CHAR_BITist 16Bits für 1750a , dsp16xx- Architekturen.
CHAR_BITist 24Bits für die dsp56k- Architektur.
CHAR_BITist 32Bits für die c4x- Architektur.

Sie können leicht mehr finden, indem Sie Folgendes tun:

find $GCC_SOURCE_TREE -type f | xargs grep "#define CHAR_TYPE_SIZE"

oder

find $GCC_SOURCE_TREE -type f | xargs grep "#define BITS_PER_UNIT"

wenn CHAR_TYPE_SIZEentsprechend definiert ist.

IEEE 754-Konformität

Wenn die Zielarchitektur keine Gleitkommaanweisungen unterstützt, generiert gcc möglicherweise einen Software-Fallback, der standardmäßig nicht dem Standard entspricht. Darüber hinaus können spezielle Optionen (z. B. die -funsafe-math-optimizationsDeaktivierung der Vorzeichenerhaltung für Nullen) verwendet werden.

ivaigult
quelle
3
positiv bewertet, weil das OP einfach angewiesen wurde, sich die Quelle eines beliebten Compilers anzusehen; Dies ist in diesem Fall die Definition von RFTM, daher sollte dies der erste Ort sein, an dem Menschen suchen.
underscore_d
9

Die binäre Darstellung nach IEEE 754 war auf GPUs bis vor kurzem ungewöhnlich, siehe GPU-Gleitkomma-Paranoia .

BEARBEITEN: In den Kommentaren wurde die Frage aufgeworfen, ob der GPU-Gleitkomma für die übliche Computerprogrammierung relevant ist, unabhängig von der Grafik. Auf jedenfall! Die meisten Hochleistungssachen, die heute industriell berechnet werden, werden auf GPUs ausgeführt. Die Liste umfasst KI, Data Mining, neuronale Netze, physikalische Simulationen, Wettervorhersage und vieles mehr. Einer der Links in den Kommentaren zeigt, warum: ein Gleitkomma-Vorteil von GPUs in der Größenordnung .

Eine andere Sache, die ich hinzufügen möchte, die für die OP-Frage relevanter ist: Was haben die Leute vor 10-15 Jahren getan, als GPU-Gleitkomma nicht IEEE war und als es keine API wie die heutige OpenCL oder CUDA gab, um GPUs zu programmieren? Ob Sie es glauben oder nicht, frühe Pioniere des GPU-Computing haben es geschafft, GPUs ohne API zu programmieren ! Ich habe einen von ihnen in meiner Firma getroffen. Folgendes hat er getan: Er codierte die Daten, die er zum Berechnen benötigte, als Bild mit Pixeln, die die Werte darstellen, an denen er arbeitete, und verwendete dann OpenGL, um die erforderlichen Operationen auszuführen (z. B. "Gaußsche Unschärfe", um eine Faltung mit normaler Verteilung darzustellen usw.) und dekodierte das resultierende Bild wieder in ein Array von Ergebnissen. Und das war immer noch schneller als mit CPU!

Solche Dinge veranlassten NVidia, ihre internen Datenbinärdateien endlich mit IEEE kompatibel zu machen und eine API einzuführen, die sich eher an Berechnungen als an Bildmanipulationen orientiert.

Michael
quelle
Wie sind GPUs relevant? (a) Diese Seite scheint sehr veraltet zu sein. (b) Bis heute können Sie GPUs nicht in C programmieren: weil C solche Dinge wie rekursive Funktionen unterstützt, die GPUs meines Wissens nicht tun. Sie können also nicht einmal einen Compiler schreiben, wenn Sie möchten.
Yakov Galka
1
@ybungalobill, das Auslagern sich wiederholender Arbeiten auf die GPU ist derzeit die bevorzugte Methode für Berechnungen in großem Maßstab . Tatsächlich entwickle ich derzeit eine in C ++. Glücklicherweise arbeiten wir nur mit NVidia CUDA- GPUs, die eine IEEE 754-kompatible binäre Darstellung von Floats haben.
Michael
Ich sage nicht, dass GPUs nicht für GP-Berechnungen verwendet werden. Ich sagte, dass Sie die Kernel in C trotz der Ähnlichkeit der Syntax nicht wirklich programmieren. Können Sie int f(int n) { return n <= 1 ? 1 : n * f(n-1); }in CUDA ausführen ? Wenn nein, sind GPUs für diese Frage nicht relevant (die nach C- und C ++ - Komitees fragt).
Yakov Galka
6
@ybungalobill: mehrere Antworten darauf. Erstens unterstützt CUDA C, C ++ und Fortran . Unter dem gleichen Link finden Sie den enormen Leistungsvorteil von 2048-Thread-GPUs gegenüber Ihrer typischen 8-Thread-CPU. Zweitens werden nur Teilmengen (obwohl große) dieser Sprachen unterstützt, einschließlich mangelnder Unterstützung für eine für CUDA-Programmiermodelle geeignete Rekursion (als "dynamische Parallelität" bezeichnet) bis CUDA 5.0. Drittens können Rekursionen normalerweise durch Schleifen ersetzt werden, was für die Multithread-Leistung ohnehin erforderlich ist.
Michael