steckdenis a écrit 327 commentaires

  • [^] # Re: Lock-free: Encore beaucoup à apprendre.

    Posté par  (site web personnel) . En réponse au journal S'essayer à la production scientifique. Évalué à 1.

    J'ai lu cet article (comme tout le reste du contenu de preshing.com, captivant), et je trouve juste dommage qu'il saute le chapitre « agrandissement de la table quand elle devient trop petite ». C'est justement ça qui m'aurait intéressé car cela pose plein de problèmes si on veut garder ça lock-free. D'ailleurs, une grande majorité de mon petit papier explique comment j'ai résolu le problème, et je pense que c'est d'ailleurs le seul point un peu nouveau que je présente.

    En tous cas, ce site est vraiment bien fait et vulgarise très très bien des concepts compliqués. Pour les amateurs, l'article sur comment trier je ne sais plus quelle quantité de données en n'utilisant qu'un seul méga-octet de RAM est très intéressant aussi.

  • # Étoffer le contenu de l'article

    Posté par  (site web personnel) . En réponse au journal S'essayer à la production scientifique. Évalué à 4.

    Bonjour,

    Merci à tous ceux qui ont commenté mon article. Ce sont des remarques pertinentes qui pointent toutes vers un travail de meilleur qualité. Voici quelques remarques et quelques réponses (je répond en un bloc car plusieurs personnes disent parfois la même chose).

    Tout d'abord, comme beaucoup l'ont fait remarquer, cet article n'a pas du tout la qualité d'une production scientifique professionnelle, rigoureuse et documentée. J'en suis conscient et c'est pour ça qu'au lieu d'essayer « d'imiter » un article professionnel, j'ai joué la carte de la vulgarisation. Les schémas peuvent donc sembler bêtes (bien sûr qu'un expert du domaine comprend le principe de ce que j'explique avant même d'avoir vu le schéma ou lu l'explication), et j'explique les algorithmes à un niveau qui s'adresse plutôt au lecteur du code qui aimerait comprendre ce qui se passe. Je m'adresse dans cet article aux personnes qui m'ont posé des questions sur mon précédent journal.

    Le point sur les sources et la recherche est très pertinent. Je me suis rendu compte lors de l'écriture de l'article que je n'avais que très peu de références (et aucune valable). Cela vient de la manière dont j'ai développé la base de donnée. J'avais des besoins très particuliers (explicités dans l'introduction), et j'avais besoin d'une base de donnée correspondant très exactement à ces points. J'ai cherché, assez longuement (tant du côté des bases SQL classiques que du très intéressant Kyoto Cabinet ou DBM), et je n'ai rien trouvé. J'ai peut-être mal cherché, et si quelqu'un trouve une pièce de logiciel qui fait exactement ce que mon papier décrit, mais en prouvé, je serais vraiment ravi de l'apprendre. En attendant, j'étais devant une page blanche avec seulement quelques articles sur la programmation lock-less et les tables de hachage pour m'aider dans mon développement. Ces articles sont cités.

    Pour la forme, j'ai lu des thèses très variées. Ma préférée est une très longue et captivante thèse richement illustrée du Dr Tarazona. Une autre thèse, très longue mais difficilement lisible parle d'un algorithme de différenciation de fichiers par Colin Percival (FreeBSD, bsdiff, et d'autres). Ces deux thèses sont de très haute qualité mais m'ont fait me dire que je préfère les papiers moins rigoureux mais plus facilement lisibles. Je n'avais pas envie de me perdre en pseudocode et en formules qui auraient de toute manière été fausses. Pour l'histoire, la thèse de Colin Percival a été « traduite » par Lothar May dans sa thèse de Master.

    Le fait que je m'adressais à un public de « curieux » pas spécialement spécialisés, ainsi que mes non-compétences en informatique formelle, m'ont fait m'orienter vers un article pas très détaillé et surtout le plus court possible. Pendant toute la rédaction, j'ai effacé des paragraphes qui me semblaient superflus, j'ai simplifié les idées, j'ai réorganisé l'article plusieurs fois pour ne développer de manière profonde que ce qui en vaut la peine, et surtout après avoir présenté brièvement les algorithmes.

    Pour le reste, je prends note de toutes les remarques. J'ai essayé de contacter des gens de mon université il y a quelques mois mais ils n'ont pas répondu, je réessayerai pour avoir plus d'avis et pour pouvoir m'améliorer.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    Pour rentrer un peu dans les détails, j'ai deux listes de blocs libres :

    • Quand on efface un bloc dans la base de donnée, il est placé dans la liste de blocs discarded. À ce point, rien ne dit qu'un lecteur n'est pas encore en train d'y accéder
    • Quand on doit allouer un bloc dans la base de donnée, il est pris depuis la liste des blocs available, disjointe des blocs discarded.
    • S'il n'y a plus de blocs dans la liste available, un nouveau bloc est alloué atomiquement dans le fichier (le fichier grandit de 512K en 512K, alors que les blocs sont bien plus petits)
    • Si le fichier est trop court, le flag _db_access_allowed dont j'ai parlé dans un de mes commentaires est mis à 0 pour tous les threads, puis on attend que tous les threads aient cessé d'accéder à la base de donnée (leur variable _db_accessed doit valoir 0).
    • Maintenant que plus aucun thread n'accède à la base de donnée, il y a deux cas possibles : soit la liste des blocs discarded contient des blocs, auquel cas on swappe simplement les pointeurs de tête de liste de available et discarded (on sait que plus aucun thread ne lit discarded, donc on peut la réutiliser), soit cette liste est vide, auquel cas 512K de zéros sont écrits dans le fichier, qui est ensuite remappé avec mremap.
    • On re-tente l'allocation, la liste available contient normalement des blocs. Normalement l'allocation réussira maintenant, mais on ne sait jamais, peut-être qu'on a été préempté pendant plusieurs minutes et que les 512K qu'on vient de rajouter au fichier ont déjà été consommés. Ce n'est pas grave, on va juste recommencer tout ce qui est swap des listes et agrandissement du fichier

    Le fichier de la base de donnée n'est jamais réduit. Un bloc ici est une unité d'espace utilisée par la base de donnée. Chaque objet (donc chaque premier entier d'un couple (i, j)) est lié à un bloc, et ce bloc contient une liste de couples (clé, valeur). Un bloc doit être supprimé quand il devient trop petit pour l'ensemble des (clé, valeur) qu'on veut y placer (il faut donc en allouer un nouveau, plus grand), ou quand on veut supprimer un objet.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    La base de donnée est un fichier mappé en mémoire, il n'y a pas de fsync explicite dans le code, l'OS écrit quand il le veut ou quand la mémoire et unmappée. Je conviens que ce n'est pas très sécurisé et que ça ne peut pas être utilisé dans certains environnements, mais l'avantage de la base de donnée lockless est qu'en cas de crash, comme les opérations sont atomiques à tous les niveaux, la base de donnée ne sera jamais corrompue (si quelques pages n'ont pas été écrites sur le disque, ça ne fait rien, la machine à état reprendra exactement là où elle en était au moment de la dernière écriture).

    Pour la terminologie, j'avoue ne pas avoir été clair. La base de donnée associe bien un entier à un couple d'entiers, de la forme (i, j) -> k. Ces nombres, pour ne pas simplement être appelés « nombres », portent les noms suivants :

    • i : l'objet
    • j : la clé
    • k : la valeur

    Cette nomenclature permet maintenant de représenter la base de donnée comme une suite de changements d'états quand des objets réagissent à des messages. Si j'envoie le message M à l'objet O, je vais aller regarder la valeur du tuple (O, M), notée O.M, dans la base de donnée. J'obtiens une valeur V.

    Maintenant, suivant ce que je voulais faire au départ, je vais encore accéder ma base de donnée. Par exemple, V peut être un objet auquel je veux forwarder le message, auquel cas je vais maintenant me positionner sur la valeur V.M . Cette valeur peut également avoir une signification spécifique, comme afficher le message dans la console, etc.

    Ce que je fais avec les valeurs des tuples dépend de l'objet : j'ai un tableau qui associe pour chaque valeur de l'objet une classe C++ que j'instancie à chaque fois que l'objet est rencontré. Cette classe contient des méthodes virtuelles permettant de continuer le traitement. C'est cette gestion des classes C++ qui devait normalement être lourd et masquer les délais introduits par la base de donnée.

    Le fait que chaque objet fasse 32 octets vient du fait qu'il y a des pointeurs dans l'histoire (pour ne pas devoir stocker une matrice objets*messages sur le disque) ainsi que quelques flags.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    C'est en effet très intéressant !

    J'ai fait sur ma machine le test décrit sur kerneltap. Un mail en haut du thread donne un petit programme appelé "task2", qui affiche en continu le temps qu'il faut pour exécuter une boucle vide de 100 millions d'itérations.

    Le programme "task1" est donné par le code suivant :

    #include <sched.h>
    
    int main()
    {
        while (1)
        {
            sched_yield();  // Version 1
            asm("pause");   // Version 2, instruction PAUSE conseillée par Intel pour les busyloops
            ;               // Version 3, On ne fait rien
        }
    }
    
    

    Seulement une des trois lignes est décommentée à la fois, pour avoir trois versions du programme. les deux programmes sont compilés en -O0, sinon GCC est trop intelligent et élimine les boucles vides. Les résultats sont les suivants (plus c'est petit, plus c'est rapide) :

    1. Quand task2 tourne seul sur un coeur, aucune autre tâche en parallèle : 505851 plus ou moins des poussières, je vais considérer le nombre 50
    2. Quand task2 tourne seul sur un coeur, avec sched_yield sur un autre : 52
    3. Quand task2 tourne seul sur un coeur, avec pause sur un autre : 51
    4. Quand task2 tourne seul sur un coeur, avec la boucle vide sur un autre : 51
    5. Quand task2 tourne sur le même coeur que sched_yield : 76 (alors qu'idéalement, on aurait voulu 50 ou 51, l'autre tâche yield le processeur)
    6. Quand task2 tourne sur le même coeur que pause : 150
    7. Quand task2 tourne sur le même coeur que la boucle vide : 88

    Le choix des coeur est fait avec taskset -c X commande, avec X égal à 0 ou 2, sachant que mon processeur dispose de l'hyper threading, et que les coeurs 0 et 1 sont en fait deux threads du même coeur physique. J'ai découvert ça en lançant task1 et task2 sur les coeurs 0 et 1, et les deux étaient ralenties. La fréquence de mon processeur a été fixée à 1200 Mhz pour tous les coeurs (fréquence basse car je suis sur batterie et j'aimerais éviter de consommer 35 W).

    Si j'essaie de tirer des conclusions, je dirais que sched_yield induit un léger ralentissement inter-coeurs (résultat 2), sans doutes parce que le scheduler doit agir, ou que les caches sont vidés. Par contre, sched_yield semble sur ma machine (Linux 3.8.8 d'openSUSE 12.3, x86_64) la solution la plus rapide pour quand deux threads partagent le même coeur. De manière surprenante, PAUSE introduit un énorme ralentissement quand les deux tâches sont sur le même coeur !

    J'ai en tous cas l'après-midi devant moi pour m'intéresser aux futex.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    Ce sont exactement 2 nombres de 32 bits qui pointent vers un seul de 32 bits.

    La taille de la base de ce test était très petite, quelques kilo-octets. La particularité de ma base de donnée est qu'elle ne contient pas réellement des « données » mais des directives. On peut la voir comme une grosse matrice N*M => K qui peut servir de machine à état. Avec peu de données, il est donc possible de faire beaucoup de choses s'il y a beaucoup de transitions d'état.

    Je ne pense pas qu'elle sera fortement limitée par le débit mémoire ou disque, car ce sont énormément de petites lectures qui y sont effectuées, comme un processeur qui lit ses instructions, qui peuvent très bien lui faire faire des boucles. Par contre, la latence du cache, de la mémoire, le readahead de l'OS, tout cela va entrer en jeu. En comptant large, 32 octets par triplet (objet, clé, valeur), je peux stocker 256 millions de ces couples sur 8 Gio. Le stockage est sparse, les triplets non-utilisés ne sont pas stockés.

    Le test dont je parle est un test qui consiste qui consiste à faire effectuer 100 000 transitions d'état simple à ma machine à état. Chaque transition est lue depuis la base de donnée (certains à répétition, sinon la base de donnée serait immense et surtout pas optimisée).

    En écrivant ce test, je pensais mettre en évidence toute la machinerie de gestion des états, qui est très complexe et assez lourde (il y a des méthodes virtuelles à appeler, des constructeurs et destructeurs à invoquer, de la mémoire à allouer et libérer (mais pas trop), etc). En lançant ce test dans valgrind et en analysant les résultats avec kcachegrind, j'ai constaté que la base de donnée représentait néanmoins 50% du temps processeur, alors que son code est comparativement très simple par rapport au reste.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    Bonjour,

    Je me suis en effet trompé dans le volatile, ce n'est pas var qui doit l'être (les instructions atomiques se chargent de tout), c'est i. Rendre la variable d'itération volatile est un petit hack dont j'ai besoin pour m'assurer que le compilateur ne déroulera ni n'optimisera la boucle. En effet, le benchmark teste la lecture depuis la base de donnée, et ce chemin de code ne contient aucune instruction atomique (seulement le sfence comme instruction bizarre). Sans le volatile, GCC déroule la boucle, inline les appels à la base de donnée, voit que c'est de la lecture seule et finalement supprime toute la boucle sauf sa dernière itération !

    En mode non-benchmark, il y a bien sûr des assertions (ou plutôt des fail_if() pour ceux qui connaissent Check) sur les valeurs renvoyées par la base de donnée, mais elles n'y sont pas en mode benchmark car le but est vraiment juste de mesurer le temps que Database::get prend pour s'exécuter, en conditions parfaites.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    C'est proche d'un spinlock mais le sched_yield() permet à tous les autres threads de la machine d'être ordonnancés avant que ce thread ne le soit à nouveau (si le scheduler utilisé est CFS, qui ordonnance il me semble les threads en round-robin, sauf ceux en temps-réel).

    Idéalement, j'aurais aimé utiliser une wait-condition, mais on ne peut pas s'en servir sans mutex. C'est pour cela que j'aimerais regarder du coté des futex : quand _db_access_allowed est à false, un appel à futex est fait pour que le noyaux ne donne plus de temps CPU au thread courant. Le noyau réveillera lui-même le thread quand _db_access_allowed vaudra à nouveau true.

    Néanmoins, j'ai lu à pas mal d'endroits que les futex sont très difficiles à utiliser correctement, donc pour le moment, je préfère me concentrer sur d'autres choses.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    En effet.

    Dans mon cas, ce qui m'a motivé à me passer du readers-writer lock a été quand je me suis rendu compte que dans un autre benchmark, la base de donnée comptait pour 50% du temps, alors que ce benchmark fait également plein d'autres choses.

    Cet autre benchmark, multithreadé, est passé de 280 ms à 126 ms entre la version rwlocks et lockless, ces deux chiffres comprenant également le temps de démarrage du benchmark, de parsing d'un fichier d'entrée et du lancement de threads (c'est une mesure donnée par time).

  • [^] # Re: Linux perf

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 1.

    J'avais déjà regardé du côté de cet outil, mais jamais de près. Et bien, c'est vraiment très pratique !

    Par contre, serais-ce possible d'invoquer perf depuis le code source du benchmark, ou seulement sur une partie du programme ? En effet, en utilisant "perf stat ./benchmark", les statistiques de tout le benchmark (y compris les entrées/sorties console, la création de la base de donnée, le mapping des fichiers) sont agrégées en un seul report, alors que j'aimerais n'avoir que la partie qui concerne la lecture de la base de donnée.

  • [^] # Re: y'a trop peu d'infos pour t'aider.

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 2.

    J'ai posté le journal au cas où quelqu'un aurait eu une réponse indépendante de l'implémentation exacte du code, par exemple « les instructions atomiques indiquent au processeur ce que tu veux faire, et donc il ne se trompe pas dans ses prédictions ». D'ailleurs, ce genre de truc serait bien possible, car Intel cite dans sa documentation sur PAUSE, une instruction qui ne fait rien :

    Improves the performance of spin-wait loops. When executing a “spin-wait loop,” processors will suffer a severe
    performance penalty when exiting the loop because it detects a possible memory order violation. The PAUSE
    instruction provides a hint to the processor that the code sequence is a spin-wait loop. The processor uses this hint
    to avoid the memory order violation in most situations, which greatly improves processor performance. For this
    reason, it is recommended that a PAUSE instruction be placed in all spin-wait loops.

    L'emphase est de moi. Certaines instructions qui semblent donc ralentir le code peuvent l'accélérer.

    Maintenant, je me rend bien compte que le problème peut être beaucoup plus proche de mon code que ce que je pensais (le but du journal était grosso-modo de dire « un machin qui prenait 3 ms en prend maintenant 1,6 alors que j'ai ajouté des instructions atomiques »). D'ailleurs, en corrigeant un bug, j'ai modifié une ligne de code qui n'est jamais exécutée par mon benchmark (ni dans la partie écriture, ni dans la lecture), et il a accéléré.

    Si ça se trouve, c'est donc simplement une histoire d'alignement de code, qui entre peut-être en conflit de ligne de cache avec mes données. Si mon benchmark passe son temps à accéder à un certain endroit de la base de donnée, en vidant la ligne de cache qui contenait justement les instructions pour effectuer cet accès, alors il est lent. Peut-être qu'ajouter ces instructions a simplement décalé une partie de code ou un accès au donnée, et le conflit n'a plus lieu.

    En tous cas, ce serait chouette que ce genre de phénomène soit documenté pour qu'un compilateur puisse choisir où il place ses fonctions pour qu'elles ne soient pas évincées du cache.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à -1.

    J'ai regardé le code assembleur et ma méthode Database::get est bien présente dans le fichier objet, et appelée le bon nombre de fois (callgrind confirme). Le benchmark ne portant que sur la lecture de la base de donnée, la seule chose qui peut arriver est que la base de donnée tienne dans le cache du processeur. Des parties peuvent être contenues dans ce cache (qui fait 3 Mio), mais pas tout, la base de donnée fait 12 Mio.

    Entre la version non thread-safe et la version thread-safe, le seul code qui change au niveau de la lecture de la base de donnée (testée dans le benchmark) est l'ajout de ceci :

    void PerThreadAccess::enterDatabase()
    {
        while (true)
        {
            _db_accessed = true;
            store_fence();
    
            if (_db_access_allowed)
            {
                break;
            }
            else
            {
                // Waiting for the db to be accessible is a very long operation
                // (the database file has to be remapped, pagefaults may occur, etc)
                // Don't spin, but yield the processor to an useful thread
                _db_accessed = false;
                store_fence();
    
                while (!_db_access_allowed)
                    sched_yield();
            }
        }
    }
    
    void PerThreadAccess::leaveDatabase()
    {
        _db_accessed = false;
    }
    
    

    Ces deux méthodes sont appelées juste avant et juste après la lecture. store_fence() est une méthode inline qui exécute l'instruction assembleur sfence, qui garanti qu'aucune lecture après cette instruction (donc de la base de donnée, et surtout de _db_access_allowed) n'aura lieu avant que l'écriture de _db_accessed soit visible par tous les autres coeurs de la machine. Le code assembleur contient bien toutes les instructions nécessaires, donc l'inlining, bien qu'agressif (c'est pour ça qu'on utilise un compilateur, surtout que j'ai tout compilé en LTO), n'a pas modifié le comportement du programme.

    Ce bout de code vient du fait que dans de très rares cas, tous les accès à la base de donnée doivent être suspendus (aussi bien en lecture qu'en écriture). En effet, quand la base de donnée devient trop petite pour ce qu'on veut y stocker, il faut agrandir le fichier, et le re-mapper. Re-mapper le fichier va très probablement invalider tous les pointeurs vers ce fichier mappé, et donc aucun accès ne peut être en cours.

    L'algorithme est donc :

    • Placer les _db_access_allowed de tous les threads à false, les threads évitent dès lors de commencer un accès
    • Boucler et faire un sched_yield tant que tous les threads n'ont pas placé leur _db_accessed à false, donc tant qu'ils accèdent à la base de donnée
    • Agrandir et re-mapper le fichier
    • Placer tous les _db_access_allowed à true, les threads peuvent reprendre leur activité

    L'utilisation de sched_yield n'est peut-être pas la plus élégante, et je n'ai pas encore suffisamment testé la base de donnée en condition réelle pour voir si ça accélère ou ralentit les choses par rapport à une busyloop. Sous Linux, il y a aussi les futex qui pourraient être utilisés pour endormir les threads tant que leur flag _db_access_allowed n'est pas à true, je regarderai de ce côté-là quand j'en aurai l'occasion (même si idéalement, déjà que pas mal de code est spécifique à x86, j'aimerais éviter de trop tomber dans le Linux-only).

    Pour info, l'écriture en base de donnée (première phase du benchmark) est plus normale : il fallait avant 16 ms pour écrire toutes les clés, il en faut maintenant 46. L'écriture a donc été fortement impactée, mais ce n'est pas grave car cette base de donnée passe son temps à être lue (ce serait grave d'avoir un programme qui génère 250 Mio de données par seconde, en tous cas pour ce que je fais).

  • [^] # Re: y'a trop peu d'infos pour t'aider.

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 2.

    Je suis tout à fait d'accord.

    Le problème est que je viens de rendre cette base de donnée thread-safe, donc utilisable. J'ai encore corrigé un bug juste avant de poster ce journal. Je n'ai donc pas encore vraiment eu le temps de réfléchir à la distribution de cette base de donnée.

    L'idéal serait d'en faire profiter tout le monde avec une licence BSD (la plupart de mes projets sont en GPL, mais pour les composants bas-niveaux, j'aime la BSD, mais c'est une autre affaire). Néanmoins, j'aimerais d'abord avoir quelques retour quant à l'intérêt qu'auraient quelques explications supplémentaires quant aux algorithmes et structures de données utilisées. Ça peut peut-être paraître bête, mais c'est quand-même deux ans de réflexion, donc soit je suis particulièrement lent, soit ça vaut la peine que j'explique bien comment tout fonctionne.

    Je comptais donc publier un « papier » au sujet de cette base de donnée. Par papier, j'entends un PDF disponible quelque-part et bien fait, ce serait je trouve un bon exercice sachant que je veux m'orienter vers une carrière de chercheur. Après, si quelqu'un veut réellement le publier au sens propre du terme, pas de problème, mais ce n'est pas le but.

    En attendant plus de retours sur cet éventuel papier, et pendant les prochains jours, je préfère être plutôt trop prudent que trop peu. C'est en effet un monde que je ne connais pas, et j'invite d'ailleurs toute personne renseignée sur le monde de la recherche, si elle le désire, à me ou nous faire part de ce qu'elle connaît du domaine et des bonnes pratiques qui s'y appliquent.

  • [^] # Re: Ai-je bien compris ?

    Posté par  (site web personnel) . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 3.

    Bonjour,

    En fait, le programme qui fait le benchmark n'utilise qu'un thread. La version pas thread-safe de la base de donnée, donc sans les instructions atomiques, s'exécute correctement car un seul thread accède à la base de donnée. La version thread-safe de la base de donnée est aussi utilisée par ce même unique thread.

    C'est comme si je comparais ces deux fonctions :

    void thread_safe(int *ptr)
    {
        __sync_fetch_and_add(ptr, 1);
    }
    
    void not_thread_safe(int *ptr)
    {
        *ptr += 1;
    }
    
    #define BENCHMARK_TYPE SAFE
    
    void benchmark()
    {
        volatile int var = 0;
    
        for (unsigned int i=0; i<BENCHMARK_ITERATIONS; ++i)
        {
    #if BENCHMARK_TYPE == SAGE
            thread_safe(&var);
    #else
            not_thread_safe(&var);
    #endif
        }
    
        assert(var == BENCHMARK_ITERATIONS);
    }
    
    

    Le benchmark ne teste donc pas la validité de l'implémentation (c'est testé par des tests unitaires dédiés), mais seulement sa rapidité, en mono-thread. Cela permet donc d'évaluer l'overhead des instructions atomiques, qui est ici négatif, ce qui est surprenant.

    Après, c'est vrai que la base de donnée non thread-safe est « buguée » si on veut l'utiliser en mode thread-safe, mais elle reste parfaitement utilisable par un programme qui aurait une base de donnée propre par thread, ou qui serait mono-thread, ou qui protégerait lui-même les accès par un mutex.

    Pour ce qui est des lignes de cache, toutes les opérations atomiques portent sur des adresses mémoires différentes (il n'y a pas de lock global, tout est de grain fin). Les objets stockés dans la base de donnée font 16 octets, il y en a donc 4 par ligne de cache de 64 octets. C'est en effet un problème quand on accède à des objets proches l'un de l'autre, je verrai avec le temps si cela pose problème et si je dois ajouter des zéros à la fin de mes objets pour qu'ils fassent 64 octets et soient alignés avec le cache.

  • [^] # Re: À propos d'un nouveau langage… (rien à voir avec ton projet)

    Posté par  (site web personnel) . En réponse au journal Nouveau langage de programmation : Parangon-Lang. Évalué à 6.

    Bonjour,

    J'ai eu l'occasion de travailler pendant plusieurs années avec Visual Studio .NET 2003 (ça remonte). Je ne suis pas du tout pro-Microsoft, mais j'ai toujours du reconnaitre à contre coeur que rien n'équivalait cet environnement. Complètement automatique au doigt et à l'oeil, et qui comprend les surcharges, avec documentation intégrée, système de projets assez efficace pour ce que j'en faisais, compilation rapide, coloration syntaxique suffisante (en fait, les mots-clé étaient colorés, mais ils sont très nombreux en Visual Basic).

    J'ai testé Eclipse, Netbeans, Anjuta, et je me suis résolu à utiliser Kate comme « environnement » sous Linux. Il m'a toujours convenu.

    Maintenant que tous les anti-Microsoft ont la souris sur « Inutile », je peux mettre en avant le « équivalait », au passé, de mon premier paragraphe. Un jour, j'ai testé KDevelop. Je me souviens encore d'un billet de blog que j'avais rédigé, et qui est maintenant effacé. C++, Qt, KDevelop, c'est le bonheur sublime qui m'a fait oublier la simplicité du Visual Basic, les fonctionnalités de .NET et l'intégration de Visual Studio. KDevelop est l'équivalent libre de tout ça, et est en plus bien meilleur.

    Outre le fait que ça gère les projets CMake, QMake, Makefile normal et complètement personnalisé, c'est multi-langages. Que ce soit pour le C++ (support first-class), le Python (support expérimental) et le PHP (support stable), il propose une coloration syntaxique poussée (mots-clé, mais aussi chaque variable, fonction, membre, attribut peut avoir sa couleur si on veut), une compréhension de code (erreurs à la compilation, sans devoir lancer GCC), refactoring (modifier le nom d'une variable propose de corriger toutes ses utilisations, même chose pour les attributs, classes, fonctions, méthodes, etc), c'est un bonheur à utiliser.

    Puis viennent les greffons Git, SVN et Mercurial (je pense), le support de GDB (un très bon support, avec pretty-print des types Qt, donc QString("machin") au lieu de QString object at 0x4f900000), les extraits de code, la documentation intégrée (HTML + Doxygen dans les en-tête qu'on utilise, avec support de la surcharge de fonctions), etc.

    À tester donc, par tous ceux qui font du C++. La création de projets est un tout petit peu longuette à mon gout, mais déjà très simple, et KDevelop aide vraiment dès que le projet est un peu gros, avec l'auto-complètement des attributs et méthodes possibles, mais aussi ses possibilités de refactoring. Son site web expose des fonctionnalités un peu plus avancées, comme créer une classe qui dérive d'une ou plusieurs autres, puis taper le nom d'une méthode virtuelle dans une des classes ascendantes, et hop, KDevelop complète le type de retour et tous les arguments. Puis, dans le .cpp, on tape à nouveau ce nom, et il ajoute automatiquement le « Type MaClasse::(paramètres){ … } ».

  • # Nautilus ou autre GUI

    Posté par  (site web personnel) . En réponse au journal Android 4 et MTP sous GNU/Linux. Évalué à 3.

    Bonjour,

    Je n'ai malheureusement pas la chance d'avoir un Android 4 sur mon Wildfire S (si quelqu'un sait où en trouver un, je prends), mais j'ai justement lu récemment quelque-part que d'autres personnes se posent la même question. Il paraît (non vérifié) que Nautilus intègre la libmtp, ce qui lui permet d'accéder à un périphérique MTP, sans doutes de la même manière que le push et pull de la méthode 2.

    Il devrait également être possible, sous KDE, d'utiliser simplement Dolphin. Je ne sais pas s'il intègre également ça, mais je pense me souvenir, lors d'une compilation de KDE, que libmtp est une dépendance optionnelle de KDE.

    À tester.

  • # Codes à récupérer

    Posté par  (site web personnel) . En réponse au journal C'est en forgeant qu'on devient forgeron. Évalué à 4.

    Bonjour,

    Pour ceux que ça intéresse, j'ai un jour développé une forge mono-projet pour mon projet Logram (j'avais des besoins assez spécifiques). Le code est public et disponible sous GNU Affero GPLv3 ici : http://gitorious.org/logram/website/ . Vous pouvez voir ce que ça donne en production sur http://www.logram-project.org .

    C'est une forge utilisable par n'importe qui, mais je n'ai pas encore connaissance d'un projet qui l'utilise (il faut dire qu'il faut adapter pas mal de trucs pour la rendre utilisable par autre-chose que Logram, dont le thème qui doit être refait).

    Côté fonctionnalités, c'est assez complet, la forge la plus complète à ma connaissance, ce qui explique pourquoi je l'ai faite au lieu de réutiliser l'existant :

    • Forum classés par catégories, avec vraie gestion du lu/non-lu, modération des commentaires, permissions, déplacement de sujets, sondages, etc. Quasiment au niveau de phpBB quand j'avais comparé.
    • Messagerie privée entre utilisateurs, avec possibilité d'avoir plusieurs utilisateurs par fil de discussion.
    • Annonces en page d'accueil, soit globales au projet, soit privées pour chaque utilisateur (l'équivalent des journaux de Linuxfr). Les membres peuvent les commenter.
    • Wiki utilisant la syntaxe Markdown (comme le forum, les MP, les commentaires d'annonces et les rapports de bugs), avec possibilité de protéger et de rendre privées des pages et d'avoir un historique de modifications
    • Un petit module "pastebin" histoire d'avoir un truc intégré au site et de ne pas devoir s'en remettre à un service externe.
    • Un système de demandes (bug reports) inspiré de Bugzilla : on sait tout faire. Chaque demande a un type (bug, idée, demande d'aide), peut avoir un nombre infini d'état (ouvert, résolu, en cours, abandonné, etc), des demandes filles, des demandes liées. Une demande peut être attribuée à un utilisateur, une adresse e-mail (pour que tous les développeurs n'aient pas à s'inscrire sur la forge) ou une URL externe (pour upstreamer des bugs). On peut manipuler les demandes comme on veut, les filtrer, les trier, les supprimer, etc.
    • Un espace de téléchargements, la partie à épurer. La page d'accueil de cet espace permet de télécharger des fichiers, mais Logram étant une distribution, il permet également de télécharger des paquets, de les rechercher, de les gérer, un peu comme packages.debian.org. On peut même voir les paquets en cours de construction par le serveur de construction, en temps réel, comme l'openSUSE Build Service (sauf que le projet Logram étant arrêté, il n'y a plus de paquets qui se construisent).

    Bref, une autre forge en Django, comme quoi on sait faire pas mal de choses avec Django. Son but est d'être la plus complète possible, et on a même quelque-part un plugin SVN pour explorer un dépôt SVN (le plugin se base également sur PySVN). J'espère que ce projet à l'arrêt (quoique je le reprendrai peut-être dans quelques temps) intéressera l'auteur de Django-Simple-Forge :) .

    Merci de m'avoir lu, et désolé pour le long post publicitaire.

  • # C'est fini !

    Posté par  (site web personnel) . En réponse à la dépêche La fin de l’aventure pour D‑Cubes. Évalué à 3.

    Bonjour,

    Merci beaucoup à tous ceux qui nous ont envoyé des mails pour acheter des produits, nous avons une dizaine de personnes intéressées par le Gamer et quelques unes par le Light. Les premiers l'emportent, les suivants doivent maintenant espérer qu'ils ne paieront pas dans les deux jours et que l'ordinateur remontera jusqu'à eux :) .

    Donc encore un grand merci. On a eu tellement de commandes qu'il aurait été possible d'en faire d'autres non-bradées, mais nous partons en voyage scolaire dans une semaine, et c'est également à cette période que le compte sera fermé. Désolé. Mais bons, gardons espoir que D-Cubes revienne dans quelques années, en grand (pas mini) :) .

  • [^] # Re: Rapport

    Posté par  (site web personnel) . En réponse à la dépêche La fin de l’aventure pour D‑Cubes. Évalué à 5.

    On doit effectivement faire un rapport, et je pense qu'on pourra le mettre en ligne. Je ferai une fois un journal avec le rapport, ainsi que les fichiers SVG des affiches et d'autres documents dont nous avons eu besoin (un Powerpoint et un truc génial fait avec Sozi, dont je remercie l'auteur pour avoir créé un outil aussi génial).

    Il faut juste voir avec l'ASBL si ce genre de documents peut sortir du cadre des actionnaires et de l'ASBL, on ne sait jamais.

  • [^] # Re: J'en ai un!

    Posté par  (site web personnel) . En réponse à la dépêche La fin de l’aventure pour D‑Cubes. Évalué à 6.

    Bonjour,

    Je suis très content que vous soyez satisfait de votre ordinateur !

    Le boîtier est difficilement trouvable, il provient d'un constructeur bruxellois, Samcheer, et sa référence est le IW-BM639.

    On appelle «commande spéciale» toute commande passée autrement que par le site web ou nos formulaires de commande. Par exemple, nous avons eu quelqu'un qui nous a demandé de monter son ordinateur entièrement sur mesure. Il nous a fourni la liste du matériel qu'il voulait, et on lui a monté son ordinateur en tant que prestataire de service. Je pense que c'est le seul exemple, on a failli avoir quelqu'un qui demandait un deuxième disque dur dans son Gamer, mais cette commande ne s'est jamais faite.

    Et pour finir, un client qui pose des questions n'est pas un mauvais client, c'est un client consciencieux :) .

  • [^] # Re: Grand bravo!

    Posté par  (site web personnel) . En réponse à la dépêche D-Cubes : ordinateurs sous Linux et promotion du logiciel libre. Évalué à 3.

    Si les lois belges autorisent de créer une entreprise qui ne paie personne, pas même son directeur (ou alors très très peu), alors là c'est possible. Mais sinon, on ne vend pas assez d'ordinateurs pour être viables (quoique des publications comme ici sur Linuxfr nous amènent quelques clients, donc on a du succès quand on parle de nous :) ).

    Côté temps, je saurais en trouver, mais c'est vraiment la viabilité de l'entreprise qui me fait douter. On n'existe plus que pour un mois, et ça me paraîtrait étonnant qu'on se fasse un nom assez important pour qu'on vende 4 ou 5 ordinateurs par jour de manière soutenue, tous les jours, avant le mois d'avril.

    A plus.

  • [^] # Re: Grand bravo!

    Posté par  (site web personnel) . En réponse à la dépêche D-Cubes : ordinateurs sous Linux et promotion du logiciel libre. Évalué à 7.

    Bonjour,

    La page de description du Light contient en bas un cadre avec les différentes options disponibles, dont le processeur Intel Atom D510 double coeur pour 18 € supplémentaires.

    Les informations geek sont données dans la dépêche pour le Gamer (1 port PCI-e 16x, 1 port PCI-e 1x, deux slots de RAM, etc). Celles pour le Light sont moins intéressantes car l'ordinateur est conçu pour être compact et efficace, pas vraiment personnalisable. La carte mère comprend un port PCI (le boîtier impose que ce soit une carte à profil bas, comme une carte tuner TV par exemple), deux slots de RAM DDR2 et 2 connecteurs SATA. La carte mère D510 possède un connecteur mini-PCI permettant de mettre des espèces de toutes petites cartes, mais je n'en sais pas plus. Le chipset de la carte mère est le Intel NM10 (carte graphique GMA 3150).

    Côté boîtier, le Light permet d'avoir un disque dur (baie 3,5" pleine hauteur) et un lecteur CD/DVD (baie 5" pleine hauteur). L'alimentation est de 160 W.

    Pour le virement, il suffit que la somme exacte arrive sur notre compte, avec votre numéro de commande en communication. Les chèques n'existent plus en Belgique depuis des années, je ne sais donc pas comment ça marche, mais vous faites comme vous voulez (virement, carte de banque, guichet, chèque, homebank, coup de téléphone à la secrétaire en lui disant de se débrouiller, etc).

    • Nous avons un mini-salaire pour la forme, de quelques euros par mois (on est payé à l'heure, ça dépend de ce qu'on fait).
    • La mini-entreprise est rentable : nous avons en moyenne vendu suffisamment d'ordinateurs depuis le début pour nous payer nos salaires. Il faut juste que ça continue jusqu'en avril, avec de préférence un petit bénéfice (pour la FSFE).
    • Je pense qu'on pourrait publier nos résultats en fin d'exercice. Nous devons remettre un rapport détaillé à l'ASBL Les Jeunes Entreprises, je pense qu'on peut également le mettre sur le site web.
    • Pour perdurer, je ne pense malheureusement pas. L'ASBL nous oblige à déposer le bilan, sauf si nous voulons transformer la mini-entreprise en une véritable entreprise. Le problème est qu'il faut gérer tout cela, et qu'on devra alors vendre beaucoup plus pour rester viables (les mini-salaires sont entre 20 et 30 fois plus faibles que les barèmes des véritables salaires).

    Merci pour les encouragements.

  • [^] # Re: Projet très intérressant.

    Posté par  (site web personnel) . En réponse à la dépêche Soutenir le Logiciel Libre avec une mini-entreprise. Évalué à 2.

    Bonjour,

    Quel plaisir de te retrouver ici, surtout avec un post aussi positif !

    Le gestionnaire de paquets d'openSUSE est mon deuxième préféré (après celui de Logram). C'est une de mes sources d'inspiration. Il est très rapide, et a une interface graphique vraiment très bien faite (quoique je déplore le fait qu'il n'existe pas une application michu-friendly comme gnome-app-install ou l'Ubuntu Software Center). De plus, le gestionnaire de paquets d'openSUSE gère sans problème les multiples dépôt, du fait qu'openSUSE propose avec son Build Service l'équivalent des PPA d'Ubuntu. Si plusieurs choix sont possibles, comme Setup, openSUSE les propose tous avec les conséquences que ça aura. On a donc un système de base très stable et les dernières applications :) .

    L'environnement graphique par défaut est KDE mais GNOME reste possible. Notre installation OEM contient également IceWM, comme bureau léger dans le cas où le KDE est mort.

    Notre version OEM est en fait le LiveCD d'openSUSE avec quelques applis préinstallées (kdenlive, digikam, koffice par exemple) et YaST2-firstboot d'activé (ce qui permet à l'utilisateur de configurer son ordinateur au premier démarrage). Il n'y a rien de particulier qui justifierait vraiment de mettre en ligne un Live-DVD de 3,8 Gio (notre installation OEM est ... fournie :) ).

    La version OEM contient plein d'applications graphiques et est destinée à l'utilisation bureautique et web. Mais on peut sans problème installer une Debian ou une ArchLinux (ou même un BSD), tout le matériel tourne avec des pilotes libres.

    Pour parler de Logram, D-Cubes pourrait un jour remplacer openSUSE par Logram, quand Logram sera prêt. J'avais à un moment parlé de Tébéas, entreprise soutenant Logram. Cette entreprise, c'est D-Cubes :) . Les deux projets ne sont pour le moment pas liés, mais peuvent le devenir quand ils s'apporteront mutuellement de bonnes choses.

    Pour le support, je ne sais pas. Les forums marchent bien, et le support par téléphone prend soit beaucoup de temps aux dirigeants, soit il faut payer des gens qui ne s'y connaissent pas forcément pour l'assurer. Dans tous les cas, la qualité est bien inférieure à ce que propose un forum comme Alionet, ubuntu-fr voire Linuxfr.

    Dans la grande surface, on parlait plus de «OpenOffice sait lire les fichiers MS Office» que «le système de fichier s'utilise comme ceci». Les gens avaient des questions bien précises, et s'ils n'en avaient pas, on leur faisait faire un petit tour du propriétaire. Pas besoin de trop rentrer dans les détails, ça les fait fuir. On veut montrer que Linux est facile à utiliser, montrons-leur ce qui les intéresse et laissons-les simplement découvrir qu'il y a plein de dossiers à la racine. Grâce aux magnifiques permissions UNIX, l'utilisateur peut tester ce qu'il veut dans les dossiers qu'il ne connaît pas sans faire de mal au système (il peut même ouvrir /proc/cpuinfo dans Kate s'il le veut, le fichier sera simplement ouvert en lecture seule).

    Voilà.
  • # Documentation

    Posté par  (site web personnel) . En réponse à la dépêche Soutenir le Logiciel Libre avec une mini-entreprise. Évalué à 2.

    Bonjour,

    Cet après-midi, j'ai rédigé un beau morceau de la documentation sur le site, accessible à l'adresse http://d-cubes.be/doc-index.html . Je vous invite, vous, linuxiens experts, à vérifier que je n'ai pas fait de trop grosses erreurs (j'avoue que j'ai pris certains raccourcis pour Madame Michu, comme le fait de ne pas ajouter GNU/ devant Linux, parce que c'est imprononçable).

    J'en profite également pour dire que notre version OEM d'openSUSE est enfin prête et qu'elle marche impeccablement. Les disques durs sont en ce moment en train d'être répliqués pour les ordinateurs que nous avons déjà vendus (au passage, si quelqu'un sait pourquoi le boîtier USB vers SATA «Magic Bridge II» tourne à 800 kio/s et seulement de temps en temps à 22 Mio/s, je suis preneur).

    Merci en tous cas à tous ceux qui ont manifesté leur intérêt et ont donné leurs conseils, c'est un grand plaisir pour nous de voir que ce qu'on fait plaît.
  • [^] # Re: Rentable ?

    Posté par  (site web personnel) . En réponse à la dépêche Soutenir le Logiciel Libre avec une mini-entreprise. Évalué à 3.

    On ne créera une vraie entreprise que si on sent qu'elle est viable, mais, si on communique bien, on pourrait y arriver.

    Un de nos actionnaires avait déjà posé cette question, et je lui avais répondu qu'en déposant le nom de l'entreprise, les salaires deviendraient bien plus importants, mais on ne fera ça que si les ordinateurs se vendent bien (plus de rentrées d'argent et prix intéressants de la part des fournisseurs car achat en gros).

    Pour le moment, nous ne devons vendre qu'une trentaine d'ordinateurs sur l'année pour parvenir à l'équilibre, donc ça devrait aller, en tous cas j'espère.