c-Ausdruck schneller abarbeiten



  • Hi,

    wie kann ich diesen Ausdruck noch schneller abarbeiten?

    for(i=0; i<200; i++)
      for(k=0; k<8; k++)
        for(j=0; j<16; j++)
          output |= (array[j][i] >> k) << j;
    

    Ich teile ja durch k und multipliziere mit j -> kann man das noch verkürzen? Mit einer zusätzlichen if-clause in der man abfrägt ob j oder k größer ist, dauert natürlich wieder...

    Gruß
    derSepp



  • derSepp schrieb:

    output |= (array[j][i] >> k) << j;
    

    Ich teile ja durch k und multipliziere mit j

    Nein. Du teilst bzw. multiplizierst durch/mit Zweierpotenzen. Allerdings ist das Ergebnis möglicherweise nicht immer das, was Du erwartest. Zumindest rein rechnerisch wird es nicht immer stimmen, da Du beim >> k möglicherweise schon Bits rechts rausschiebst, die Du durch << j nicht wieder reinbekommst.



  • Belli schrieb:

    derSepp schrieb:

    output |= (array[j][i] >> k) << j;
    

    Ich teile ja durch k und multipliziere mit j

    Nein. Du teilst bzw. multiplizierst durch/mit Zweierpotenzen. Allerdings ist das Ergebnis möglicherweise nicht immer das, was Du erwartest. Zumindest rein rechnerisch wird es nicht immer stimmen, da Du beim >> k möglicherweise schon Bits rechts rausschiebst, die Du durch << j nicht wieder reinbekommst.

    Das ist richtig. Im Prinzip interessiert mich nur das Bit an erster Stelle nach der Teilung. Dieses Bit will ich anschließend um << j nach links verschieben.

    output |= ((array[j][i] >> k) & 1) << j;
    

    Hab allerdings gemerkt, dass ich die &-Verknüpfung scheinbar nicht benötige, um das richtige Ergenis zu erhalten.

    Gruß Sepp



  • for (k = 0; k<8; ++k)
    {
    	for (j = 0; j<16; ++j)
    	{
    		for (i = 0; i<200; ++i)
    		{
    			output |= (array[j][i] >> k) << j;
    		}
    	}
    }
    

    Besonders viel lässt sich da nicht machen.



  • Der Ausdruck ist ok. Aber die Schleifen nicht.

    for(i=0; i<200; i++)
      for(k=0; k<8; k++)
        for(j=0; j<16; j++)
          output |= (array[j][i] >> k) << j;
    

    wird zu

    for(i=0; i<200; i++)
      for(j=0; j<16; j++)
        for(k=0; k<8; k++)
          output |= (array[j][i] >> k) << j;
    

    wird zu

    for(i=0; i<200; i++)
      for(j=0; j<16; j++)
        aij=array[j][i]
        for(k=0; k<8; k++)
          output |= (aij >> k) << j;
    

    wird zu

    for(i=0; i<200; i++)
      for(j=0; j<16; j++)
        aij=array[j][i]
        tmp=aij;
        tmp=(tmp>>1)|tmp;
        tmp=(tmp>>2)|tmp;
        tmp=(tmp>>4)|tmp;
        output |= tmp << j;
    

    wird zu

    for(i=0; i<200; i++)
      for(j=0; j<16; j++)
        aij=array[j][i]
        tmp=aij>>7;
        tmp=(tmp<<1)|tmp;
        tmp=(tmp<<2)|tmp;
        tmp=(tmp<<4)|tmp;
        output |= tmp << j;
    

    wird zu

    for(i=0; i<200; i++)
      for(j=0; j<16; j++)
        aij=array[j][i]
        tmp=aij/128*255;
        output |= tmp << j;
    

    wird zu

    for(i=0; i<200; i++)
      for(j=0; j<16; j++)
        output |= ((array[j][i]>>7)*255)<<j;
    

    alles natürlich ungetestet



  • danke für den Tipp; an die Schleifen hab ich noch gar nicht gedacht, aber wenn man die j-Schleife weglässt und den Ausdruck 16x hinschreibt, hab ich einen Geschwindigkeitsvorteil von 9ms bei einer Frequenz des Controllers von 60MHz.

    😮 nicht schlecht.

    Gruß
    Bernd



  • Ist eine recht häufige Optimierung namens "Loop unrolling". Viele Compiler machen das automatisch, wobei man bei µC mit wenig ROM darauf auch gerne verzichtet (der Code wird ja durch unrolling typischerweise größer).


Anmelden zum Antworten