• # Aie mes yeux...

    Posté par . En réponse au lien Nim plus rapide que C++ sur du ray tracing. Évalué à 10.

    J'ai voulu lire le code C++... Ça pique. C'est illisible, et pas a cause d'optimisations.
    Ce qui, en revanche, n'est pas le cas du code nim, étrangement...

    Pour info, le fichier .cpp à 103 lignes, le fichier .nim 335, alors que C++ est réputé verbeux.

    Là ou le code Nim est bien lisible: une instruction par ligne, des lignes vides pour aider l'oeil a distinguer les blocs, des commentaires qui sont sur leur propre ligne, du code aligné... le C++ à l'air obfusqué et codé dans du pré-C++11.
    D'ailleurs, aucune bibliothèque de C++ n'est utilisée ici. Pourquoi? Ça aurait réduit considérablement la quantité de code à écrire... et aurait pu inclure du code optimisé, justement.
    Perso, quand je dois faire de la 3D, je n'implémente pas mes algo de détection, j'utilise ce qui existe. Que l'on compare son implémentation de nim avec du code C++ qui utilise ça, et on en reparle.

    Le code me semble clairement écrit en faveur de nim, et le C++ semble malgré tout proche de nim question performances. Ma conclusion c'est que Nim est plus lent que C++, et le code est fait salement en C++ pour empêcher de facilement voir pourquoi c'est lent.
    Non, ce n'est pas du C++ naïf, sinon l'auteur n'utiliserais inline, qui n'est pas ce que l'on trouve en 1er dans les tutoriels et docs.

    Extraits choisis de code C++:

     if (det<0) return 0; else det=sqrt(det);
     return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0);

    Pourquoi laisser le else? Si tu retournes dans le if, le else sert évidemment à rien.
    2 branchements avec l'opérateur ternaire sur un return? J'appelle ça du code de merde, sans parler des affectations au milieu: l'auteur ne veut pas que l'on puisse comprendre ce qui se fait.

     inline bool intersect(const Ray &r, double &t, int &id){
     double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20;
     for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&d<t){t=d;id=i;}
     return t<inf;
    }

    Errrr.... spheres était un table de taille de fixe, on peut constater ici plusieurs erreurs, possiblement optimisée par le compilo, mais peut-être pas:

    • a chaque appel de la fonction intersect, on refait une division inutile: n devrais être une constante, calculé une seule fois. Et pas un double.
    • cast double vers int inutile pour n.
    • for(int...) vraiment? Même en C ou C++03 on faisait mieux, avec les pointeurs. Du C++11 moderne, donc de moins de 10 ans, utiliserais juste un range for. Bon, ici, il semble réutiliser l'entier pour le retourner dans le cas ou il trouve une intersection, mais vu que le code est imbuvable, difficile de dire si on ne peut pas s'en passer.

    Aussi:

    Nim 1.2.0 (GCC 10.1), flag -d:danger

    Donc, version récente: "1.2.0 2020年04月03日".

    Pourtant, il n'utilise pas C++20, pourquoi? Ça aurait permis d'éviter certaines implémentations, genre clamp vs std::clamp.