Nous continuons d'examiner le nouvel ordinateur national. Après une brève connaissance des fonctionnalités de l'architecture Elbrus, nous considérerons les outils de développement logiciel qui nous sont proposés.
Rappelons la structure de l'article:- examen du matériel :
- processus d'acquisition;
- matériel
- revue du logiciel :
- lancement du système d'exploitation;
- logiciel ordinaire;
- aperçu des outils de développement:
- analyse comparative des performances :
- Description des ordinateurs concurrents
- résultats de référence;
- résumant.
Bonne lecture!Caractéristiques de l'architecture
L'essence de l'architecture E2K en une phrase peut être formulée comme suit: registres 64 bits, parallélisme explicite de l'exécution des instructions et accès mémoire strictement contrôlé.Par exemple, les processeurs d'architecture x86 ou SPARC qui sont capables d'exécuter plus d'une instruction par cycle (superscalaire), et parfois aussi hors service, sont implicitesparallélisme: le processeur analyse directement en temps réel les dépendances entre instructions sur une petite section de code et, s'il le juge possible, charge en même temps certains actionneurs. Parfois, il agit trop optimiste, - de manière spéculative, en rejetant le résultat ou en annulant la transaction en cas de prédiction infructueuse. Parfois, au contraire, c'est trop pessimiste - en supposant des dépendances entre les valeurs des registres ou des parties des registres, qui ne sont en fait pas du point de vue du programme exécutable.Si expliciteparallélisme (explicitement instruction parallèle calcul, EPIC) la même analyse a lieu au stade de la compilation, et toutes les instructions machine définies pour une exécution parallèle sont écrites dans un très grand mot d'instruction (VLIW), et Elbrus a la longueur de cette Les «mots» ne sont pas fixes et peuvent aller de 1 à 8 mots doubles (dans ce contexte, un seul mot a une capacité de 32 bits).Sans aucun doute, le compilateur a des capacités beaucoup plus importantes en termes de quantité de code couvert, de temps et de mémoire dépensés, et lors de l'écriture manuelle du code machine, le programmeur peut effectuer une optimisation encore plus intelligente. Mais c'est en théorie, et dans la pratique, il est peu probable que vous utilisiez l'assembleur, et donc tout dépend de la qualité du compilateur d'optimisation, et en écrire un n'est pas une tâche facile, c'est le moins qu'on puisse dire. De plus, si, avec un parallélisme implicite, des instructions «lentes» peuvent continuer à fonctionner sans bloquer la réception des instructions suivantes sur d'autres actionneurs, alors avec un parallélisme explicite, la commande Wide entière attendra l'achèvement complet. Enfin, un compilateur d'optimisation aidera peu à interpréter les langages dynamiques.Tout cela est bien compris au MCST, bien sûr, et par conséquent, Elbrus implémente également des technologies d'exécution spéculative, du code et des données préchargés et des opérations de calcul combinées. Par conséquent, au lieu de théoriser et de se demander infiniment combien de gigaflops hypothétiques telle ou telle plate-forme peut donner dans un ensemble de circonstances réussies, dans la quatrième partie de l'article, nous prenons et évaluons simplement les performances réelles de programmes réels - appliqués et synthétiques.VLIW: une percée ou une impasse?, VLIW : , ‑ Transmeta Crusoe — «». , Efficeon ( ) . , x86- , . , Pentium M , Pentium 4 , . VIA C3, x86.
En raison de son caractère exotique, la technologie d'exécution protégée de programmes en langages C / C ++, où l'utilisation de pointeurs offre une large gamme de possibilités de se tirer une balle dans le pied, n'est pas moins intéressante. Le concept de protection contextuelle, implémenté conjointement par le compilateur au stade de l'assemblage et le processeur au moment de l'exécution, ainsi que le système d'exploitation en termes de gestion de la mémoire, ne permettront pas de violer la portée des variables - qu'il s'agisse d'accéder à une variable de classe privée, aux données privées d'un autre module, aux variables locales de la fonction appelante . Toute manipulation avec modification du niveau d'accès n'est autorisée que dans le sens d'une réduction des droits. L'enregistrement des liens vers des objets à vie courte dans des structures à vie longue est bloqué. Les tentatives sont également empêchées d'utiliser des liens morts: si l'objet auquel le lien a été reçu une fois a déjà été supprimé,même l'emplacement d'une autre nouvelle installation à la même adresse ne sera pas considéré comme une excuse pour accéder à son contenu. Encouragé à utiliser les données comme code et à contrôler les transferts n'importe où.En effet, dès que l'on passe des idiomes de haut niveau à des pointeurs de bas niveau, tous ces domaines de visibilité se révèlent n'être rien de plus que du sel syntaxique. Certains cas (les plus simples) de mauvaise utilisation des pointeurs peuvent parfois aider à détecter les analyseurs de code source statiques. Mais lorsque le programme est déjà traduit en instructions machine x86 ou SPARC, rien ne l'empêchera de lire ou d'écrire la valeur à partir de la mauvaise cellule de mémoire ou de la mauvaise taille, ce qui entraînera un plantage dans un endroit complètement différent - et vous êtes ici, en regardant la pile endommagée et vous ne savez pas par où commencer le débogage, car sur l'autre machine, le même code fonctionne correctement. Et le débordement de pile et les vulnérabilités qui en résultent ne sont que le fléau des plates-formes populaires. Il est gratifiant que nos développeurs abordent systématiquement ces problèmes,et ne se limite pas à disposer de plus en plus de béquilles, dont l'effet ressemble plutôt à un râteau. Après tout, personne ne se soucie de la vitesse à laquelle votre programme fonctionne s'il ne fonctionne pas correctement. En outre, un contrôle plus strict par le compilateur vous oblige à réécrire le code "odeur nauséabonde" et intolérable, ce qui signifie qu'il améliore indirectement la culture de programmation.L'ordre des octets lors du stockage des nombres dans la mémoire d'Elbrus, contrairement à SPARC, est peu endian (l'octet inférieur vient en premier), c'est-à-dire, comme sur x86. De même, étant donné que la plate-forme vise à prendre en charge le code x86, il n'y a aucune restriction sur l'alignement des données en mémoire.Ordre, alignement et portabilité , Intel, , (, 32‑ 0x04000005) — , , , . - , , , — , ( , UTF‑16), , , , ‑. , , — , SPARC, — .
Vous pouvez en savoir plus sur la conception des ordinateurs MCST sur les architectures SPARC et E2K dans le livre «Microprocessors and Computing Complexes of the Elbrus Family», qui a été publié par la Peter Publishing House dans un tirage minimal et a longtemps été vendu, mais est disponible gratuitement en format PDF ( 6 Mo ) et pour une somme modique sur Google Play . Dans le contexte de l'absence d'autres informations détaillées dans le domaine public, cette publication n'est qu'un réservoir de connaissances. Mais le texte se concentre principalement sur le matériel, les algorithmes de fonctionnement des tampons et des pipelines, les caches et les dispositifs arithmétiques et logiques - le sujet de l'écriture de programmes [efficaces] n'est complètement pas abordé, et même la simple mention d'instructions machine peut être comptée sur les doigts.Langage machine
En plus de compiler les langages de haut niveau C, C ++, Fortran, la documentation à chaque occasion n'oublie pas de mentionner la possibilité d'écrire des programmes directement dans Assembler, mais nulle part il n'est spécifié comment exactement vous pouvez vous impliquer dans cet art en filigrane, où au moins vous pouvez obtenir une référence aux instructions de la machine. Heureusement, le système dispose d'un débogueur GDB qui peut désassembler le code des programmes précédemment compilés. Afin de ne pas aller au-delà de la portée de l'article, nous écrivons une fonction arithmétique simple qui a un bon retard de parallélisation.uint64_t CalcParallel(
uint64_t a,
uint64_t b,
uint64_t c,
uint32_t d,
uint32_t e,
uint16_t f,
uint16_t g,
uint8_t h
) {
return (a * b) + (c * d) - (e * f) + (g / h);
}
Voici à quoi cela se traduit lors de la compilation en mode -O3 :0x0000000000010490 <+0>:
muld,1 %dr0, %dr1, %dg20
sxt,2 6, %r3, %dg19
getfs,3 %r6, _f32,_lts2 0x2400, %g17
getfs,4 %r5, _lit32_ref, _lts2 0x00002400, %g18
getfs,5 %r7, _f32,_lts3 0x200, %g16
return %ctpr3
setwd wsz = 0x5, nfx = 0x1
setbp psz = 0x0
0x00000000000104c8 <+56>:
nop 5
muld,0 %dr2, %dg19, %dg18
muls,3 %r4, %g18, %g17
sdivs,5 %g17, %g16, %g16
0x00000000000104e0 <+80>:
sxt,0 6, %g17, %dg17
addd,1 %dg20, %dg18, %dg18
0x00000000000104f0 <+96>:
nop 5
subd,0 %dg18, %dg17, %dg17
0x00000000000104f8 <+104>:
sxt,0 2, %g16, %dg16
0x0000000000010500 <+112>:
ct %ctpr3
ipd 3
addd,0 %dg17, %dg16, %dr0
La première chose qui attire votre attention est que chaque commande est décodée immédiatement en plusieurs instructions exécutées en parallèle. La désignation mnémonique des instructions est généralement intuitive, bien que certains noms semblent inhabituels après Intel: par exemple, une instruction d'extension non signée s'appelle ici sxt , pas movzx . Le paramètre de nombreuses commandes de calcul, en plus des opérandes eux-mêmes, est le numéro du dispositif exécutif - ce n'est pas sans raison que ELBRUS signifie une planification explicite d'utilisation des ressources de base, c'est-à-dire une «planification explicite pour l'utilisation des ressources de base».Pour accéder à la valeur de registre 64 bits complète, le préfixe « d"; en théorie, il est également possible d'accéder aux 16 et 8 bits inférieurs de la valeur. La désignation des registres mondiaux à usage général, dont 32 pièces sont préfixées par « g » devant le numéro , et les registres de procédures locales par le préfixe « r ». La taille de la fenêtre des registres locaux demandés par l'instruction setwd peut atteindre 224, et la pompe est poussée automatiquement sur la pile selon les besoins.La façon dont vous appliquez certaines instructions est déroutante: par exemple, retourner, comme vous pouvez le deviner, sert à retourner le contrôle de la procédure d'appel, cependant, dans tous les exemples de code étudiés, cette instruction se produit bien avant la dernière commande (où une sorte de manipulation de contexte est également présente), parfois même dans le tout premier mot de commande, comme ici. Bien que le livre susmentionné consacre un paragraphe entier à ce problème, il n'est pas encore devenu clair pour nous. Mise à jour au 9 février 2016: les commentaires suggèrent que l' instruction return ne prépare que la voie pour le retour du sous-programme et permet au processeur de commencer à charger les commandes suivantes de la procédure d'appel, et le contrôle lui-même revient lorsque l'exécution atteint l'instruction ct .Cependant, «code facile à lire» et «code efficace» sont loin d'être les mêmes en matière d'instructions machine. Si vous compilez sans optimisation, le code est plus cohérent et similaire au calcul du front, mais au prix d'un allongement: au lieu de 6 mots de commande saturés, 8 mots clairsemés sont générés.Séance révélatrice sur le marc de café pour la simulation, finissons avant de fantasmer sur des hypothèses complètement ridicules. Espérons qu'un jour la référence de la commande et le guide de programmation et d'optimisation seront rendus publics.Outils de développement
Le compilateur de langage C / C ++ standard dans le système d'exploitation Elbrus est LCC, un développement propriétaire de la société MCST, compatible avec GCC. Des informations détaillées sur la structure et les principes de ce compilateur ne sont pas publiées, mais selon un entretien avec un ancien développeur de l' une des nombreuses sous-espèces développées du compilateur, Edison Design Group utilise une interface pour une analyse de haut niveau des codes source et la traduction de bas niveau en instructions machine peut être effectuée de différentes manières - sans optimisation ou avec optimisation. C'est le compilateur d'optimisation qui est fourni aux utilisateurs finaux, non seulement sur la plate-forme E2K, pour laquelle il n'y a tout simplement pas de générateurs de code machine alternatifs, mais également sur la famille de plates-formes SPARC, où le GCC habituel faisant partie du système d'exploitation MSVS est également disponible.Compte tenu des caractéristiques architecturales répertoriées ci-dessus - concurrence évidente, exécution sécurisée des programmes - le compilateur LCC implémente évidemment de nombreuses solutions uniques dignes des études et tests les plus rigoureux dans la pratique. Malheureusement, au moment de la rédaction de ces lignes, l'auteur n'a ni qualifications suffisantes ni temps pour de telles études; J'espère que tôt ou tard cette question sera abordée par un cercle beaucoup plus large de représentants de la communauté informatique, y compris des plus compétents.D'après ce que vous avez réussi à remarquer à l'œil nu lors de la création de programmes pour tester les performances, LCC sur E2K donne plus souvent que d'autres des avertissements sur les erreurs possibles, les constructions illettrées ou simplement les endroits suspects dans le code. Certes, l'auteur n'est pas si familier avec GCC pour garantir la distinction entre les messages LCC uniques en russe et les messages simplement traduits (de plus, la traduction est sélective), et je ne suis pas sûr qu'un flux d'avertissements plus intense ne soit pas le résultat d'une configuration d'assemblage automatiquement terminée. De plus, ne connaissant pas la sémantique d'une section particulière de code, il est parfois difficile de comprendre à quel point le compilateur est intelligent pour trouver des bogues cachés ou déclencher une fausse alarme. Par exemple, dans le code Postgresql, la même construction se retrouve quatre fois dans le même fichier avec de légères variations:for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) {
if ((*ptr)[strspn(*ptr, " \t")] == '\0')
fputs(" ", fout);
else
html_escaped_print(*ptr, fout);
}
Le compilateur prédit une sortie possible du tableau unidimensionnel dans la chaîne avec l'appel de la fonction strspn . Dans quelles circonstances cela peut arriver, l'auteur ne comprend pas (et il n'y a pas eu un tel avertissement sur d'autres plateformes, bien que le mode de vérification soit lié à Warrayest standard pour GCC), cependant, il convient de noter que plusieurs réplications du même design non trivial (car il était nécessaire d'expliquer son objectif dans le commentaire), au lieu de le mettre dans une fonction distincte avec un nom éloquent qui ne nécessite pas d'explication. Même si l'alarme s'est révélée fausse, la détection d'un code malodorant est un effet utile; les auteurs de l'analyseur statique PVS - Studio seront laissés sans travail. Mais sérieusement, il serait amusant et utile de comparer les erreurs supplémentaires dans le code que le LCC est vraiment capable de détecter en raison des caractéristiques uniques de l'architecture E2K - en même temps, le monde du logiciel libre pourrait obtenir un autre lot de rapports de bogues.Un autre résultat d'une connaissance curieuse avec LCC loquaces était l'auteur de l' éducation, et ses collègues plus expérimentés, sur ce trigraphs ( trigraphes ) dans les langues de C / C, et pourquoi ils ne sont pas pris en charge par défaut, heureusement. Vous vivez comme ça et ne vous doutez pas que la combinaison apparemment inoffensive de signes de ponctuation dans les littéraux de texte ou les commentaires peut se révéler être une bombe à retardement - ou un excellent matériel pour un signet de programme, selon le côté de la barricade sur laquelle vous vous trouvez.Une conséquence désagréable de l'autosuffisance de LCC est que son format de message est différent de celui de GCC, et lorsqu'ils sont compilés à partir d'un environnement de développement (par exemple, Qt Creator), ces messages tombent uniquement dans le journal général du travail, mais pas dans la liste des problèmes reconnus. Peut-être que cela peut être personnalisé d'une manière ou d'une autre, soit du côté du compilateur, soit dans l'environnement de développement, mais au moins prêt à l'emploi, il ne se comprend pas.Traditionnellement aiguë pour les plates-formes nationales, compte tenu de leurs performances relativement faibles, il y a le problème de la compilation croisée, c'est-à-dire l'assemblage de programmes pour l'architecture cible et un ensemble spécifique de bibliothèques système, en utilisant les ressources d'ordinateurs plus puissants, avec une architecture différente et d'autres logiciels. À en juger par les lignes d'identification dans le cœur du système Elbrus et dans le compilateur LCC lui-même, ils sont assemblés sur Linux i386, mais cette boîte à outils pour x86, bien sûr, n'est pas incluse dans le package de distribution du système lui-même. C’est intéressant, mais est-il possible de faire le contraire: sur Elbrus pour collecter des programmes pour d’autres plateformes? (L'auteur n'a pas réussi plus loin que la première phase de l'assemblage GCC pour i386.)Versions des packages les plus importants pour le développeur:- compilateurs: lcc 1.19.18 (compatible gcc 4.4.0);
- : erlang 15.b.1, gawk 4.0.2, lua 5.1.4, openjdk 1.6.0_27 (jvm 20.0‑b12), perl 5.16.3, php 5.4.11, python 2.7.3, slang 2.2.4, tcl 8.6.1;
- : autoconf 2.69, automake 1.13.1, cmake 2.8.10.2, distcc 3.1, m4 1.4.16, make 3.81, makedepend 1.0.4, pkgtools 13.1, pmake 1.45;
- : binutils 2.23.1, elfutils 0.153, patchelf 0.6;
- : boost 1.53.0, qt 4.8.4, qt 5.2.1;
- : expat 2.1.0, ffi 3.0.10, gettext 0.18.2, glib 2.36.3, glibc 2.16.0, gmp 4.3.1, gtk+ 2.24.17, mesa 10.0.4, ncurses 5.9, opencv 2.4.8, pcap 1.3.0, popt 1.7, protobuf 2.4.1, sdl 1.2.13, sqlite 3.6.13, tk 8.6.0, usb 1.0.9, wxgtk 2.8.12, xml‑parser 2.41, zlib 1.2.7;
- : cppunit 1.12.1, dprof 1.3, gdb 7.2, perf 3.5.7;
- : anjuta 2.32.1.1, glade 2.12.0, glade 3.5.1, qt‑creator 2.7.1;
- : bzr 2.2.4, cvs 1.11.22, git 1.8.0, patch 2.7, subversion 1.7.7.
Encore une fois, si vous vous attendiez à GCC 5, PHP 7 et Java 9, ce sont vos problèmes, comme le dit un footballeur célèbre. Dans ce cas, je dois également dire merci du moins pas GCC 3.4.6 (LCC 1.16.12), comme dans les versions précédentes du système Elbrus, ou GCC 3.3.6 dans la composition du MSVS 3.0; Par ailleurs, le compilateur principal dans MSVS 3.0 est toujours GCC 2.95.4 (et pourquoi être surpris quand il y a un noyau à partir d'une branche 2.4?). Par rapport à la situation précédente, lorsqu'il était possible de tomber sur un bogue GCC corrigé en amont il y a dix ans, le nouveau système a des conditions presque paradisiaques - vous pouvez même le faire glisser en C ++ 11 si vous ne souhaitez pas conserver la compatibilité descendante.L'émergence d'OpenJDK, au moins sous une certaine forme, peut déjà être qualifiée de grande percée, car l'aversion pour Java et Monodans de tels systèmes est connue depuis longtemps; et cette aversion peut être comprise lorsque même les programmes natifs bougent à peine. Puisqu'il y a beaucoup de Javistes parmi les collègues de l'auteur, en raison des circonstances ci-dessus, obligés de restreindre les merveilleuses impulsions de l'âme, il a été décidé de consacrer une série distincte de tests de performance pour consacrer Java. Pour l'avenir, nous notons que les résultats ont été décourageants même en termes relatifs: avec le même succès, vous pouvez probablement écrire des scripts interprétés en PHP ou en Python.La prise en charge de C et C ++ seul n'est pas limitée à la compatibilité avec la collection de compilateurs GNU: le système a toujours un traducteur Fortran. Comme l'auteur ne connaît que le professeur Fortran, toute personne intéressée peut recommander le sujet de décembre sur «Made with Us», où les commentaires portent sur l'utilisation de cette langue comme référence.Pour le dessert, nous avons stocké les plus délicieux: la dernière partie de l'article est consacrée à l'étude des performances d'Elbrus en comparaison avec une variété de plateformes matérielles et logicielles, y compris domestiques.