/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Udfordring for bit freaks
Fra : Klaus Petersen


Dato : 18-10-04 22:51


Hej med Jer.

Jeg sidder roder med bits. Jeg skal finde et udtryk/algoritme, der kan
følgende:

bits er et tal i intervallet [0;32]

Hvis bits er 1, tændes bit 32.
Hvis bits er 2, tændes bit 32 og 31.
Hvis bits er 3, tændes bit 32 og 31 og 30.
o.s.v.

For bits = 0, er ingen bits tændt.
For bits = 32, er alle bits tændt.

Kan nogen hjælpe?

Jeg har lavet et lille program til at teste om udtrykket/algoritmen er
rigtig - resultatet af udtrykket/algoritmen skal tildeles result (ved
kommentaren):

#include <stdio.h>

// her er de korrekte vaerdier for bits [0;32]
unsigned int _fetch [33] = { 0x00000000,
0x80000000, 0xC0000000, 0xE0000000, 0xF0000000, 0xF8000000, 0xFC000000,
0xFE000000,
0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000, 0xFFF80000,
0xFFFC0000,
0xFFFE0000, 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
0xFFFFF800,
0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0,
0xFFFFFFF0,
0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF };

char buf [33] = {0};
char* do_binary ( unsigned int result )
{
int i = 0; while ( i < 32 ) { if ( result & 0x80000000 ) buf [i] = '1'; else
buf [i] = '0'; result <<= 1; i++; };
return &buf [0];
};
int main(int argc, char* argv[])
{
int charcount;
unsigned int result;
bool errors = false;
int bits = 0;
while ( bits < 33 )
{
// lav udregning til result - nedstaaende er et eksempel der ikke virker
result = (0x1 << bits)-1;
printf ( "for %u bits: %u (%08X) - %n", bits, result, result, &charcount );
charcount = 50 - charcount;
while ( charcount-- )
printf ( " " );
printf ( "binary: %s\n", do_binary (result) );
if ( result == _fetch [bits] ) printf ( "Resultatet er korrekt!\n" ); else
{ printf ( "Resultatet er IKKE korrekt\n"); errors = true; };
bits++;
};
printf ( "%s\n", errors ? "Beklager. Den algoritme duer ikke!" : "Tillykke.
Dette er et rigtigt svar." );
return 0;
}



 
 
Bertel Brander (18-10-2004)
Kommentar
Fra : Bertel Brander


Dato : 18-10-04 23:08

Klaus Petersen wrote:
> Hej med Jer.
>
> Jeg sidder roder med bits. Jeg skal finde et udtryk/algoritme, der kan
> følgende:
>
> bits er et tal i intervallet [0;32]
>
> Hvis bits er 1, tændes bit 32.
> Hvis bits er 2, tændes bit 32 og 31.
> Hvis bits er 3, tændes bit 32 og 31 og 30.
> o.s.v.
>
> For bits = 0, er ingen bits tændt.
> For bits = 32, er alle bits tændt.
>

Det ser ud til at dette virker:

if(bits == 0)
result = 0;
else if(bits == 32)
result = 0xFFFFFFFFUL;
else
result = 0xFFFFFFFFUL << (32 - bits);

--
Juliet: What's in a name? that which we call a rose
By any other name would smell as sweet; ...
Romeo: I take thee at thy word:
Call me but love, and I'll be new baptized;

Klaus Petersen (18-10-2004)
Kommentar
Fra : Klaus Petersen


Dato : 18-10-04 23:19

> Det ser ud til at dette virker:
>
> if(bits == 0)
> result = 0;
> else if(bits == 32)
> result = 0xFFFFFFFFUL;
> else
> result = 0xFFFFFFFFUL << (32 - bits);

Ja. Efter at have skrevet mit indlæg og dermed få det tænkt igennem, er jeg
selv kommet frem til:

result = bits ? 0xffffffff << (32-bits) : 0;

... som jo ligner din en del. Men jeg tror det kan skrives bedre.

Jeg tror godt jeg kan lempe lidt på reglerne og sige at:

bits er i intervallet [1;32] eller omvendt, så 32 tænder een bit, 31 tænder
2 o.s.v. - da funktionen bliver kaldt med bits som en konstant.



Klaus Petersen (18-10-2004)
Kommentar
Fra : Klaus Petersen


Dato : 18-10-04 23:22

> Men jeg tror det kan skrives bedre.

Med bedre mener jeg så et udtryk uden betingelser.



Bertel Brander (18-10-2004)
Kommentar
Fra : Bertel Brander


Dato : 18-10-04 23:58

Klaus Petersen wrote:
Jeg tror godt jeg kan lempe lidt på reglerne og sige at:
>
> bits er i intervallet [1;32] eller omvendt, så 32 tænder een bit, 31 tænder
> 2 o.s.v. - da funktionen bliver kaldt med bits som en konstant.
>

Hvis man kan nøjes med 1 til 32 kan man godt gøre det uden betingelser.
Man kunne også blot slå op i en tabel, du har jo lavet den.

--
Juliet: What's in a name? that which we call a rose
By any other name would smell as sweet; ...
Romeo: I take thee at thy word:
Call me but love, and I'll be new baptized;

Klaus Petersen (19-10-2004)
Kommentar
Fra : Klaus Petersen


Dato : 19-10-04 08:35


> Hvis man kan nøjes med 1 til 32 kan man godt gøre det uden betingelser.
> Man kunne også blot slå op i en tabel, du har jo lavet den.

Jeg gik i gang med at lave et udtryk som kunne udregne de værdier i tabellen
under den formodning, at det ville være hurtigere.

Men det viser sig at det er temmeligt hurtigt at slå op i en tabel og at det
godt kan betale sig selv for så små ting.

Det er måske nok tvivlsomt at man kan finde et udtryk der er hurtigere end
at slå det op.



Ukendt (19-10-2004)
Kommentar
Fra : Ukendt


Dato : 19-10-04 20:40

Hej Klaus.

"Klaus Petersen" <spectual2@getTOnet.dk> skrev i en meddelelse
news:6s3dd.1351$DM5.920@news.get2net.dk...
> Men det viser sig at det er temmeligt hurtigt at slå op i en tabel og at
> det
> godt kan betale sig selv for så små ting.
>
> Det er måske nok tvivlsomt at man kan finde et udtryk der er hurtigere end
> at slå det op.

Jeg vil godt stille spørgsmålstegn ved om det kan betale sig at lave en
tabel for denne operation. En 32 bit shift operation kan foretages i een
clock cyklus på de fleste CPU'er idag et tabelopslag koster betydeligt mere.

Hvad får díg til at mene at din tabelimplementering er hurtigere end
shiftoperationen ?

Prøv at lade compileren generere assembler for de to implementeringer og se
hvad det er der sker. (husk også at lege med optimizeren

Med venlig hilsen
Jesper Wolf Jespersen



Klaus Petersen (20-10-2004)
Kommentar
Fra : Klaus Petersen


Dato : 20-10-04 19:07

> Jeg vil godt stille spørgsmålstegn ved om det kan betale sig at lave en
> tabel for denne operation. En 32 bit shift operation kan foretages i een
> clock cyklus på de fleste CPU'er idag et tabelopslag koster betydeligt
mere.
>
> Hvad får díg til at mene at din tabelimplementering er hurtigere end
> shiftoperationen ?

Speed-tests. Men det er vist værd at lave en ny speedtest - denne gang med
gprof.

> Prøv at lade compileren generere assembler for de to implementeringer og
se
> hvad det er der sker. (husk også at lege med optimizeren

Apropos optimizeren. Jeg så at g++ har et væld af optimizing mulighed - jeg
går ud fra de alle er slået fra pr. default - men hvilke af dem er gode?
Skal man have dem alle sammen med?



Klaus Petersen (20-10-2004)
Kommentar
Fra : Klaus Petersen


Dato : 20-10-04 19:39

> Jeg vil godt stille spørgsmålstegn ved om det kan betale sig at lave en
> tabel for denne operation. En 32 bit shift operation kan foretages i een
> clock cyklus på de fleste CPU'er idag et tabelopslag koster betydeligt
mere.

Jeg har udført nogle speedtests med gprof og er kommet frem til, at:

0xffffffff << (n-32) er en smule hurtigere end tabel opslag.

At det så ikke lige er dén funktion, der er tungest er en anden sag.

Den kan i flg. gprof udføre 319820 kald på mellem 10 og 20 ms. for tabel
opslag og under 10 ms. for 319820 med bitshift metoden.

Den tunge funktion i programmet er en funktion til at konvertere en buffer
fra little endian til big endian ( det er i øvrigt et bitstream objekt jeg
har lavet ) - den står for hele 65%-85% af programmets levetid.



Bertel Brander (20-10-2004)
Kommentar
Fra : Bertel Brander


Dato : 20-10-04 22:15

Klaus Petersen wrote:

> Den tunge funktion i programmet er en funktion til at konvertere en buffer
> fra little endian til big endian ( det er i øvrigt et bitstream objekt jeg
> har lavet ) - den står for hele 65%-85% af programmets levetid.
>

Måske skulle vi se den funktion, for at checke om den kan
optimeres.

Man kan vist bruge htonl(), den er implementeret i asm
på cygwin, så den burde være hurtig.
   
--
Juliet: What's in a name? that which we call a rose
By any other name would smell as sweet; ...
Romeo: I take thee at thy word:
Call me but love, and I'll be new baptized;

Per Abrahamsen (21-10-2004)
Kommentar
Fra : Per Abrahamsen


Dato : 21-10-04 08:50

"Klaus Petersen" <ng@spectual.ra.bnaa.dk> writes:

> Apropos optimizeren. Jeg så at g++ har et væld af optimizing mulighed - jeg
> går ud fra de alle er slået fra pr. default - men hvilke af dem er gode?
> Skal man have dem alle sammen med?

-O3: Giver "maksimal optimering for kørehastighed"

-ffast-math: Tillad transformeringer der ændrer værdien af visse
matematiske udtryk. Som oftest giver det *højere* præcision i
forhold til reel matematik, men ikke altid.

-cpu=pentiumpro: Vælg den CPU type du vil optimere for.

-arch=pentium Vælg den CPU type du vil generere kode for.

Ovenstående kombination giver kode der kører bedst på en PentiumPro
(og Pentium II), men som kan køre på enhver Pentium. Du skal
selvfølgelig vælge efter dit eget behov.

Du kan overveje at bruge -Os i stedet for -O3, hvis det er vigtigt for
dig at få en lille eksekverbar i stedet for en hurtig eksekverbar.

Hvis du er villig til at gå et ekstra skridt, kan du oversætte to
gange. Først brug -fprofile-generate, kør programmet på et "typisk"
input, og oversæt igen med -fprofile-use.


Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408176
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste