option dhcp119 – Search Domains

 Sans catégorie  Commentaires fermés sur option dhcp119 – Search Domains
Fév 022019
 

Je voulais passer plusieurs domaines de recherche dans l’option dhcp 119. Après plusieurs essais, mon client dhcp me dit toujours « suspect value in domain_search option – discarded »

Je cherche un peu sur le net, et il s’avère qu’il y a une syntaxe
rigolotte décrite dans la RFC3397

ci dessous un encodeur fait à l’arrache pour générer la chaine en hexadécimal correspondant a une liste

#include <stdio.h>

int main(void) {

    const char * StrToEncode = "lan chez.moi.net ailleurs.com";

    const char * ptrA = StrToEncode;
    const char * ptrB = StrToEncode;

    printf("\nSTART\n");

    printf("Chaine initiale : '%s'\n", StrToEncode);
    printf("Chaine resultat : '0x");

    while (1) {
        int cpt=0;
        const char * ptrB=ptrA;

        while (1) {
            if ( *ptrA =='\0' ) break;
            if ( *ptrA =='.' ) break;
            if ( *ptrA ==' ' ) break;
            cpt++;
            ptrA++;
        }

        printf("%02x", cpt);

        while ( ptrB != ptrA ) {
            printf("%02x", *ptrB);
            ptrB++;
        }

        if ( *ptrA ==' ' ) printf("00");        //separateur
        if ( *ptrA =='\0' ) { printf("00'\n");  break; }   //Fin de chaine

        ptrA++;
    }

    printf("END\n");
    return 0;
}

Generateur de sparse-file

 Trucs et astuces techniques  Commentaires fermés sur Generateur de sparse-file
Mai 192011
 
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>


const char * strtera="To";
const char * strgiga="Go";
const char * strmega="Mo";
const char * strkilo="Ko";
const char * stroctets="octets";
const char * strunkwn="inconnu";

#define TERA 1099511627776
#define GIGA 1073741824
#define MEGA 1048576
#define KILO 1024

const long tera = TERA;
const long giga = GIGA;
const long mega = MEGA;
const long kilo = KILO;

long unit=0;

char buffer[4096];
unsigned long size=0;
const char * filename = NULL;
int justdoit = false;



const char* strofunit(const long u)
{   switch (u)
    {   case TERA : return strtera;
        case GIGA : return strgiga;
        case MEGA : return strgiga;
        case KILO : return strkilo;
        case 1 :    return stroctets;
        default : return strunkwn;
    }
}

void usage(void)
{
    fprintf(stderr, "\n");
    fprintf(stderr, "usage :  zerogen -f filename -s size \n");
    fprintf(stderr, "    size peut tre specit avec une unit comme '12G' or '125M' \n");
    fprintf(stderr, "    Si l'unit n'est pas spcifie avec size, elle peut l'etre avec -u (mais pas les deux)\n");
    fprintf(stderr, "    En l'absence de toute unit, la taille est considre tre en octets.\n");
    fprintf(stderr, "    La taille ne doit en aucun cas depasser 8To (comportement imprvisible dans ce cas).\n");
    fprintf(stderr, "    \n");
    fprintf(stderr, "    zerogen ne modifiera pas les fichiers qui existent dja\n");
    fprintf(stderr, "    \n");
    fprintf(stderr, "    exemple :  \n");
    fprintf(stderr, "                zerogen -f disk.img -s 20G\n");
    fprintf(stderr, "                zerogen -f disk2.img -s 20 -u G\n");
    fprintf(stderr, "    \n");

}    


int getarg(int argc, char* argv[] )
{   
    int c;
    int tmp;
    char tmp2;

    if (!argc) return false;

    while ( (c = getopt(argc, argv, "jS:s:u:f:")) != EOF )
    {   
        switch(c)
        {   case 'j' :  justdoit=true;
                        break;
    
            case 's' :
            case 'S' :  if (size)
                        {   printf("Erreur : la taille est specifie plusieurs fois\n");
                            return false;                        
                        }
                        tmp = sscanf(optarg,"%lu%c", &size, &tmp2);
                        if ( ! tmp ) return false;
                        if ( tmp == 2 )
                        switch ( toupper(tmp2) )
                        {   case 'T' : unit = tera; break;
                            case 'G' : unit = giga; break;
                            case 'M' : unit = mega; break;
                            case 'K' : unit = kilo; break;
                            case 'O' : unit = 1; break;
                        }                
                        break;

            case 'u' :  if (unit)
                        {   printf("Erreur : Conflit d'units\n");
                            return false;
                        }
                        switch ( toupper(optarg[0]) )
                        {   case 'T' : unit = tera; break;
                            case 'G' : unit = giga; break;
                            case 'M' : unit = mega; break;
                            case 'K' : unit = kilo; break;
                            case 'O' : unit = 1; break;
                        }
                        break;

            case 'f' :  filename = optarg;
                        break;

            case '?' :  perror("Option inconnue\n");
                        return false;
        }
    }

    

    if ( !filename )
    {   fprintf(stderr,"fichier non specifie : utilisez l'option -f \"fichier\"\n");
        return false;
    }

    if ( ! size )
    {   fprintf(stderr, "taille non spcifie : utiliser l'option -s taille \n");
        return false;
    }


    if ( !unit )
    {   fprintf(stderr,"unit non specifie : On considere que la taille specifiee est en octets\n");
        unit=1;
    }
    
    if ( !unit )
    {   fprintf(stderr,"unit non specifie : utilisez l'option -uO -uK -uM -uG -uT pour specifier octets, kilo, mega, giga\n");
        return false;
    }
    
    return true;
                        
}


int main (int argc, char* argv[])
{   FILE* f;
    int w;
    assert( sizeof(long) == 8 );
    assert( sizeof(size_t) == 8);

    memset(buffer, 0, 4096);

    if ( ! getarg(argc, argv) ) 
    {   usage();
        return 1;
    }

    f = fopen(filename, "r");
    if (f && !justdoit)
    {   fclose(f);
        fprintf(stderr,"Le fichier existe dj specifiez -j pour passer outre (-j comme just do it)\n");        
        return 1;
    }

    if (f && !justdoit) fclose(f);
    
    printf("Cration du fichier [%s] de taille %lu %s\n", filename, size, strofunit(unit));
    f = fopen(filename, "w");
    assert(f);
    
    fseek(f, (size*unit)-1 , SEEK_SET);
    w=fwrite(buffer, 1, 1, f);
    assert(w);
    fclose (f);
    return 0;
}



Mar 022010
 

pour modéliser la dispertion, on aura souvent besoin d’un generateur alléatoire gaussien qui concentre la majorité des valeurs sur la moyenne.

ci dessous une librairie de mon cru permettant d’obtennir ce resultat:

#include "pgl_random.hpp"

#include <stdlib.h>
#include <math.h>


static const int precision = 1000000000;  

double pgl_random(void)
{   return (double)(rand()%precision)/precision;
}

double pgl_random(const double max)
{   return max*pgl_random();
}

double pgl_random(const double min, const double max)
{   return min + pgl_random(max - min);
}

double pgl_random_gauss(void)
{   //cette fonction génère 2 nombres alléatoires
    //le second est stocké pour le prochain appel
        
    //les valeurs de retour sont centrées sur 0, equitablement réparties dessus dessous 
    //les valeurs sont essentiellement entre -3 et +3 

    double x1;
    double x2;
    double w;
    double y1;
    static double y2;
    static bool cache = false;

    if ( cache )
    {   cache=false;
        return y2;
    }

    do 
    {   x1 = pgl_random(-1, 1);
        x2 = pgl_random(-1, 1);
        w = x1 * x1 + x2 * x2;  //somme des carrés
    } while ( w >= 1.0 ); 

    w = sqrt( (-2.0 * log( w ) ) / w ); //attention log() est la fonction du log népérien ln. dans math.h le log classique est "log10"
    y1 = x1 * w;
    y2 = x2 * w;    //cette valeur est mise en cache pour le prochain appel
    cache = true;
    return y1;    
}



double pgl_random_gauss(const double centre, const double ecart)
{   return centre + ecart * pgl_random_gauss();
}

double pgl_random_gauss(const double ecart, const double min, const double max)
{   double centre = ( max - min ) /2 ;
    double r;
    do
    {
        r = centre + ecart * pgl_random_gauss();
    }   while ( r < min || r > max )
    return r;
}



Optimisation des sauts conditionnels

 Trucs et astuces techniques  Commentaires fermés sur Optimisation des sauts conditionnels
Mar 012010
 

Dans bien des cas, les opérations mathematiques sont plus rapides que les sauts conditionnels
exemple avec ces deux fonctions.

double foo(bool a, double b)
{   return a*b;
}

double bar(bool a, double b)
{   if ( a == true ) return b;
    else return 0;
}

la fonction foo est plus rapide que bar, ou en tout cas est plus facile à optimiser si on l’apelle un grand nombre de fois.

exemple pour 10 millions d’appels sur un processeur Intel(R) Core(TM)2 6300@1.86GHz

//sans optimisation
FOO temps  : 0.191716 sec
FOO temps  : 0.191693 sec
BAR temps  : 0.208786 sec
BAR temps  : 0.208999 sec
ecart : 8%

//optimisation O1
FOO temps  : 0.123257 sec
FOO temps  : 0.122524 sec
BAR temps  : 0.130222 sec
BAR temps  : 0.129852 sec
ecart : 5%

//optimisation O2
FOO temps  : 0.024811 sec
FOO temps  : 0.025352 sec
BAR temps  : 0.072986 sec
BAR temps  : 0.073545 sec
ecart : 66%


Remarque importante concernant l’optimisation :
Dans un programme digne de ce nom, il est inutile d’optimiser ce qui n’en a pas besoin, surtout si ça nuit à la lisibilité du code.
Généralement, les gains de vitesse proviendront de la complexité de l’algorythme utilisé plutôt que de la qualité du codage.
Généralement 90% des gains de vitesse possibles peuvent être obtennus en optimisant moins de 10% du code.
Aussi, ne réservez ce genre d’astuces qu’a de très petites portions de code et vérifiez que vos modifications ont un impact positif et suffisant pour justifier leur emploi.

Fast-Math

 Trucs et astuces techniques  Commentaires fermés sur Fast-Math
Fév 272010
 

Il existe des options de compilation pour gcc permettant d’accélérer les calculs.
Par contre, attention il est posible d’avoir des erreurs d’arrondi non négligeables et donc un comportement erratique.
NE JAMAIS faire de tests d’égalité entre des float ou des doubles si cette option de compilation est activée.

gcc -mmmx -msse -msse2 -msse3 --ffast-math

Calculs trigonometriques rapides

 Trucs et astuces techniques  Commentaires fermés sur Calculs trigonometriques rapides
Fév 262010
 

Apres avoir lu quelques tutos sur comment optimiser les calculs trigonométriques, j’ai voulu me faire une librairie trigo rapide basée sur une table et là : surprise !

sur un PC récent

matablesin[(int)(angle/deuxpi*tailletable)]

est presque 2 fois plus lent que

sin(angle);

L’explication est toute simple : Les processeurs modernes ont tout le hardware necessaire pour calculer sin et cos, et même les deux en même temps. (instructions assembleur spécialisées)

Remarque : La taille de la table a une influence car il est probable qu’elle soit accédée a peu près alléatoirement. Dans ces conditions les mécaniques de cache et de préchargement de pages ne peuvent pas fonctionner et la lecture en RAM prends finalement plus de temps que de demander le calcul au processeur.

Ce genre de technique reste cependant applicable au calcul de asin et acos qui ne sont pas (encore) accélérés materiellement.