Forum Programmation.c Copie rapide de tableau

Posté par (page perso) .
Tags : aucun
0
3
fév.
2005
Bonjour, j'ai un gros tableau de char, je me dis, "tiens ce serait plus rapide de mettre mes valeurs dedans en les castant en tant qu'unsigned long, ça ira beaucoup plus vite (on a des proc 32 bits, c'est stupide de ne pas en profiter) "

Donc, j'aimerai comprendre pourquoi quand j'écris


#include stdio.h;

char tab[4096000];

int main(void)
{
int i;
char c;
for(i=0;i<;4096000;i++) tab[i]='c';
for(i=0;i<;4096000;i++) printf("%d",tab[i]);
c = getchar();

for(i=0;i<1024000;i++) (unsigned long)tab[i<<2]=(unsigned long)(45);
c = getchar();
for(i=0;i<4096000;i++) printf("%d",tab[i]);
return 0;
}


il ne me cast pas correctement en asm comme je le voudrai :

pour la 1ère boucle j'ai


.LM1:

movl $tab,%esi
movl $4095999,%ebx
movl $tab+4095999,%eax
.p2align 4,,7
.L21:
movb $99,(%eax)
decl %eax
decl %ebx
jns .L21


Normal, rien à dire

Par contre pour la seconde :

.LM5:

movl $1023999,%ebx
movl $tab+4095996,%eax
.p2align 4,,7
.L32:
movb $45,(%eax)
addl $-4,%eax
decl %ebx
jns .L32


Je comprend pas qu'il me mette un movb ! Je lui ai demandé un movl !!

Comment solutionner ce problème sans passer par une fonction standard (genre memcpy) : je me demande comment solutionner ce problème sans librairie, avec une simple boucle... ?

C'est une limitation de Gcc ?
  • # ya pas une bourde dans le code C?

    Posté par . Évalué à 3.

    dans la version dite "optimisée"
    tu glisses ca:

    for(i=0;i<1024000;i++) (unsigned long)tab[i<<2]=(unsigned long)(45);

    ce qui pour moi signifie que tu stockes la valeur 45 dans un byte sur 4
    Le compilo trouve peut etre + optimal de faire un movb plutot qu'un movl dans ce cas là vu que tu ne forces qu'un byte.


    si tu veux forcer 4 bytes en meme temps il faut peut etre mieux utiliser ca:
    for(i=0;i<1024000;i++) (unsigned long)tab[i<<2]=(unsigned long)(0x63636363);

    Que dit le compilo?
    • [^] # Re: ya pas une bourde dans le code C?

      Posté par (page perso) . Évalué à 0.

      J'ai pas essayé (bonne idée), mais ce qui est sûr (j'ai testé avec le printf), c'est qu'il ne me charge qu'une valeur sur quatre

      le premier printf m'affiche 99999999999999999999999999999999999999

      le second 459999994599999945999999....

      « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

    • [^] # Re: ya pas une bourde dans le code C?

      Posté par (page perso) . Évalué à 2.

      effectivement ça marche...

      for(i=0;i<1024000;i++) (unsigned long)tab[i<<2]=(unsigned long)(0x63636363);

      il m'affiche bien 99999999999999999999999 le deuxième coup....

      « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

      • [^] # Re: ya pas une bourde dans le code C?

        Posté par . Évalué à 1.

        Et le code assembleur généré? movl ou movb?
        • [^] # Re: ya pas une bourde dans le code C?

          Posté par (page perso) . Évalué à 2.

          movb :(
          et le pire c'est qu'il me dit que la cast est déprécié...

          « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

        • [^] # Re: ya pas une bourde dans le code C?

          Posté par (page perso) . Évalué à 2.

          c encore pire que ce que je pensais : malgré le cast, il ne prend que le char de (0x6968afb3) soit -77...

          « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

          • [^] # Re: ya pas une bourde dans le code C?

            Posté par . Évalué à 2.

            Allez encore plus goret:
            (cette fois ca marche, j'ai testouillé avant)

            unsigned long* ptr = (unsigned long*) tab;

            ...

            for(i=0; i<1024;i++)
            ptr[i]=0x64646464;

            apres compile ca ressemble à ca:
            ...
            L12:
            cmpl $1023, -4(%ebp)
            jle L15
            jmp L13
            L15:
            movl -4(%ebp), %eax
            leal 0(,%eax,4), %edx
            movl -12(%ebp), %eax
            movl $1684300900, (%eax,%edx)
            leal -4(%ebp), %eax
            incl (%eax)
            jmp L12
            L13:
            ....
            • [^] # Re: ya pas une bourde dans le code C?

              Posté par (page perso) . Évalué à 2.

              Cool, génial ! Je plussois, plusoyons !

              Par contre l'asm produit à l'air beaucoup plus tordu...

              En O3, par contre c'est très propre et on voit bien le gain !

              la première boucle, en char
              <code>
              movb $99,(%eax)
              decl %eax // canal U
              decl %ebx // Canal V : parallelisable
              jns .L21
              </code>
              la seconde, en longint

              <code>
              movl ptr,%eax
              movl $101,(%eax,%ebx,4)
              incl %ebx
              cmpl $1023999,%ebx
              jle .L32
              </code>

              Par contre, j'ai testé les temps, c'est similaire.... Longueur des instructions ?

              « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

              • [^] # Re: ya pas une bourde dans le code C?

                Posté par . Évalué à 1.

                (pour le code fouillis c'est po ma faute, c'est mingw32 sous NT, j'avais que ca sous la main en intel.. )

                si tu es en O3 il est probable qu'il déroule ou optimise les boucles de lui meme parce que gcc l'est péchu...



                en bref ta tentative d'optimisation est pertinente sur un compilo qui ne ferait aucune optimisation. En revanche avec des flags d'optimisation, le compilo fait une partie du travail lui meme ( réorganisation de code, déroulement des boucles pour eviter les sauts ...

                trouvé vite fait par google:

                http://www.redhat.com/docs/manuals/enterprise/RHEL-3-Manual/gcc/optimize-options.html



  • # Il y a des fonctions toutes faites pour cela ...

    Posté par (page perso) . Évalué à 3.

    As-tu essayé memcpy au lieu de partir du principe que ton programme ne tournera que sur ta machine ???
    Il faut savoir que memcpy est optimisé exactement pour cela, qu'elle peut tirer profit d'un DMA s'il est disponible, et que sinon on n'utiliserait que des boucles pour copier des tableaux, et que cette fonction n'existerait pas.
    Moralité : utilise memcpy, memset etc (dans string.h).
    • [^] # Re: Il y a des fonctions toutes faites pour cela ...

      Posté par (page perso) . Évalué à 2.

      Mince je n'avais pas lu la dernière phrase. Mais tu veux vraiment te passer de toute bibliothèque, mais de la libc ????
      C'est un sacré boulot que tu fais là, et dans ce cas-là tu devrais faire ta routine directement en assembleur, mais la tu perds complètement la portabilité...
      • [^] # Re: Il y a des fonctions toutes faites pour cela ...

        Posté par (page perso) . Évalué à 0.

        au contraîre je gagne la portabilité si je reste en c.

        C'est une optim qui m'interresse pour des cas où je n'ai pas de libc disponible.

        Il ya des environnement où la libc n'est pas disponible, ça existe.

        En utilisant la libc, je sui dépendant d'un OS, comment je fait, si je veux écrire mon propre OS ?

        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

        • [^] # Re: Il y a des fonctions toutes faites pour cela ...

          Posté par . Évalué à 1.

        • [^] # Re: Il y a des fonctions toutes faites pour cela ...

          Posté par . Évalué à 2.

          En utilisant la libc, je sui dépendant d'un OS, comment je fait, si je veux écrire mon propre OS ?
          Ben t'utilise une micro libc que tu compile statiquement...
          Pas besoin de reinvente le memcpy pour ca : d'autre on deja fait le boulot pour toi...
          • [^] # Re: Il y a des fonctions toutes faites pour cela ...

            Posté par (page perso) . Évalué à 2.

            Effectivement, mais c'est limitatif au niveau de ton choix d'architecture pour l'OS : Dans ce cas cela t'oblige à concevoir un énième OS basé sur du procédural.
            Cela t'oblige à conserver une logique grosso-modo basé sur le concept dépassé de processus appelant des fonctions systèmes dans un seul sens.

            Si tu veux faire un OS objet uniquement composé d'objets dialoguant les un avec les autres sans couche d'abstraction, tu ne peux utiliser la libc...

            Donc c'est à éviter pour un OS objet...

            « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

            • [^] # On peut savoir

              Posté par . Évalué à 1.

              comment il s'appelle, ton OS objet ? Je connais bien unununium mais il est sensé être écrit en python...
              • [^] # Re: On peut savoir

                Posté par (page perso) . Évalué à 1.

                http://isaacos.loria.fr/(...)

                « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

                • [^] # Re: On peut savoir

                  Posté par . Évalué à 2.

                  Je me trompe ou bien c'est pas trop libre ?

                  (c'est juste une info, hein... Pas d'aggressivite, zen, chakras ouverts, toussa...)
                  • [^] # Re: On peut savoir

                    Posté par (page perso) . Évalué à 1.

                    Non ça ne l'est pas. La décision dépend de l'INRIA, c'est à elle de décider. J'ai beaucoup réfléchi à la question, je suis pour mais dans certaines conditions permettant de sauvegarder les intérêts de son auteur ,de l'INRIA , et donc de la recherche française.

                    Je suis très heureux de ne pas être tombé sur un intégriste :-)

                    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.