• [^] # Re: Bof

    Posté par . En réponse au journal Microsoft réécrit Hurd ?. Évalué à 8.

    Oui enfin, le C n'est pas portable hein. Tu as du C portable façon POSIX, du C portable façon ISO seulement, et surtout, surtout, quand il s'agit de coder un OS, même si tu essaies très fort, tu auras forcément des bouts de code totalement non-portables. Par exemple, les types en C ISO ne sont que des relations d'ordre, du type sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long), etc. D'où le besoin d'une norme POSIX qui propose des types fixes (uint32_t, etc) [1].

    Dès qu'on parle de programmation bas-niveau (telle que celle d'un OS), il ne faut pas voir le C comme autre chose qu'un « assembleur de haut niveau ».

    Concernant les bouts de code à « spécialiser » en fonction des architectures, je suis assez d'accord. Cela dit, ça fait quand même un grand nombre d'optimisations spécifiques. Alors si par exemple sur x86, on peut utiliser les intrinsics, le problème est que sur une autre plate-forme, le nom et la sémantique des instructions diffèrent, ce qui force à tout réécrire, et qui est tout de même assez pénible.

    Par exemple, sur PowerPC 32 bits, il existe 32 registres adressables, alors que sur archi amd64/intel64, on n'a que 16 registres (sans parler des x86 32 bits et de leurs 8 registres). Bref, dans le cas du ppc, on a plein de registres à disposition (RISC oblige), avec des instructions qui peuvent en tirer parti -- par exemple, il existe une instruction qui affecte les valeurs situées à partir d'une certaine adresse dans tous les registres, e.g. :
    r1 <- @tab[0]
    r2 <- @tab[1]
    ...
    r32 <- @tab[30]

    ... alors que sur x86, à cause de l'héritage CISC, on doit faire un peu différemment (en « vrai », il y a évidemment plein de registres sur un processeur x86, mais ils sont cachés, et on est obligé de faire confiance au matériel pour renommer les registres en interne de façon intelligente).

    Ce genre d'instruction n'existe pas pour le SSE d'Intel/AMD. En revanche, on y trouve des pxor (parallel XOR, qui permet d'effectuer des XOR sur 128 bits d'un coup), et autres choses plutôt sympa pour la crypto, par exemple.

    Sauf que voilà, du coup, l'algo sous-jacent à une certaine fonction (filtre pour traiter des images, ...) risque de différer pas mal d'une archi à l'autre. On se retrouve donc finalement avec une fonction qui a la même interface, indépendante de l'architecture (MIPS, PowerPC, x86, x86_64, ia64, etc), mais un fonctionnement interne très différent, avec des perfs elles aussi très différentes. Et surtout, il faut trouver des gens pour maintenir ce genre de code (un par archi, voire un par génération d'une même archi ...).

    Maintenir (et mettre à jour !) correctement ce genre de code est très délicat, car le moindre bug risque non-seulement de faire planter l'appli (cas « idéal »), mais surtout de donner un résultat erroné (et là, c'est déjà plus coton).

    Enfin, même si j'aime bien l'assembleur, je suis pour son éradication sauf cas exceptionnel. On a vraiment très rarement besoin d'accéder aux instructions assembleur. Déjà, en insérant de l'assembleur en-ligne dans un code C, on coupe toute velléité d'optimisation au compilateur (qui se « houla, il tripatouille autre chose que du c/c++/java/pascal/whatever, qu'il se débrouille puisqu'il est si malin »). Donc déjà, ça signifie faire une fonction à part, compilée dans un fichier objet. Ensuite, il faudrait déjà qu'il n'existe pas déjà une interface « C » (intrinsics pour SSE, instructions vectorielles pour profiter d'AltiVec sur ppc, etc) pour utiliser ces instructions SIMD. Généralement de toute manière, le nom des instructions est très proche de l'instruction assembleur correspondante. Par contre, au programmeur de vérifier l'alignement des données [2], sinon ça va planter grave, à lui de vérifier que l'opération qu'il veut effectuer est légale dans le cadre d'instructions vectorielles, etc.

    Il existe cependant quelques rares cas où il n'existe pas d'équivalent « C » à ce qu'on peut faire en assembleur. Par exemple, un de mes collègues, expert en cryptographie, râlait il n'y a pas si longtemps sur le fait qu'on ne pouvait pas récupérer des infos concernant les retenues ou les overflows (qu'on a dans le registre d'état, mais qui est totalement masqué dans les langages de 3è génération et plus).

    [1] Enfin si je ne me trompe pas, avec C99, ce genre de type rentre dans la norme du langage.
    [2] Tiens, encore un truc qui fait que le C n'est pas trop portable dans ce cas.