Avatar billede ruma1974 Nybegynder
04. august 2006 - 09:56 Der er 26 kommentarer og
1 løsning

Gemme list af char i mindre type end char

Hej,

Er der nogen der af et eksemple på hvordan man kan gemme en array af char som kun kan antager 20 forskellige char værdier i en array af en mindre type.

I princippet burde jeg kunne gemme data'erne i 5 bit per bogstav. Men hvordan?

Mvh,

Rune
Avatar billede martinlind Nybegynder
04. august 2006 - 10:12 #1
Du kan lave en Enum eller du kan bruge Typen Bits eller en helt 3'ede måde, du skal bare ha' en måde hvorpå du kan vide at værdien f.eks. 1 = A
Avatar billede ruma1974 Nybegynder
04. august 2006 - 11:24 #2
Ja, Jeg kan lave en type som er smallchar:array[1..5] of boolean

og en tabel med 0 til 19 bogstaver. Jeg mangler så en lyn hurtig rutine til at kovertere til en værdi ml 0 og 19.

Jeg kan selvfølgelig lave et for loop der beregner værdien af smallchar men kan det gøres hurtigere med noget inline assembler code i delphi?
Avatar billede martinlind Nybegynder
04. august 2006 - 13:56 #3
du kan måske bruge en enum type, den kan du definere sådan

MyType = (mtA=3,mtB=5) osv.

også måske bruge noget rtti eller lign, men ligefrem at bruge inline det virker lidt overkill ??? hvorfor alt det optimering ?? hvad skal du lave
Avatar billede ruma1974 Nybegynder
04. august 2006 - 14:27 #4
Jeg skal beregne masserne på en lange række aminosyrer. Hver bogstav repræsentere en aminosyre som har en bestemt masse. Da jeg skal beregne masseren på mere end 1.000.000 rækker af amino syre under runtime skal det gå så hurtigt som muligt.

Jeg kender ikke til rtti og Enum. Tror du det er hurtigere end at bruge array[1..5] of boolean?
Avatar billede a_nor Nybegynder
04. august 2006 - 14:31 #5
Til ruma1974:  Din Smallchartype duer ikke. En boolean fylder stadig 1 byte.

Ingen tvivl om at det blir noget værre bøvleri med en masse bitmanipulationer.
Anvendelse af 5 bytes kan selvfølgelig lagre 8 af "dine tal" men at få det kodet og dekodet kræver for mange programliner.
Avatar billede a_nor Nybegynder
04. august 2006 - 15:19 #6
Er dit program kørende så du har konstateret at der er et problem ?
Avatar billede ruma1974 Nybegynder
04. august 2006 - 15:23 #7
ah, ja jeg tror faktisk jeg har lavt den fjel med boolean engang før - jeg bør skamme mig

hmm, jeg har overvejet 5 byte løsningen men jeg er bange for at det tager for lang tid at dekode (kodningstiden er irrlevant for mig).
Avatar billede martinlind Nybegynder
04. august 2006 - 16:14 #8
Det kan da ikke være det store problem at ha 1 mill. char's i hukommelsen, også bare køre løs, hvor alle de krumspring, brug dog bare en alm char. RAM er jo ikke et problem i vore dage, så alt det med asm og det ikke må fylde osv. det er spild af tid :)
Avatar billede ruma1974 Nybegynder
04. august 2006 - 16:38 #9
Der er 1000000 rækker som hver indeholder omkring 500-1000 bogstaver så vi taler let om 500-1000 Mb. Derudover skal programmet også have lidt ram at lege med under runtime.

Det er muligt at det ikke er værd at bruge tid på optimering her.
Avatar billede ruma1974 Nybegynder
04. august 2006 - 16:58 #10
Lukker og takker
Avatar billede hrc Mester
04. august 2006 - 16:59 #11
En Windows XP kan allokere 4Gb ram uanset hvad der er i maskinen (eller er det 2Gb; synes der er et eller andet der). Resten puttes i swapdisken så alloker du bare løs. Din maskine bør dog nok mindst have 2Gb ram for ellers bliver det nok ikke så lynhurtigt som du ønsker.
Avatar billede hrc Mester
04. august 2006 - 17:00 #12
Det lød ellers som en sjov opgave at pakke tingene ned i bidder på 5 bit, men hvis det er hastighed du ønsker så er det i hvert fald ikke den rette måde.
Avatar billede ruma1974 Nybegynder
04. august 2006 - 17:33 #13
Ja winXP 32 bit kan allokere 4 Gb

winXP 64 kan allokere 16 Gb

Jeg ønsker både hastighed og optimering af data størrelse

Med hensyn til hastighed har jeg lige nu to muligheder som virker lige hurtigt når jeg konvertere bogstaverne til tal:

type aaR=record
  aa:char
  m:real;
  end;


AAm:array of [0..20]

for hver bogstav (amino syre) looper jeg så igennem denne array for at finde dens masse (den mest hyppige har jeg i toppen af array AAm).

Jeg har derudover prøvet med en anden løsning som nok vil se mærkelig ud for jer eksperter men den virker lige så hurtigt.

mA:array of [0..255] of real;

For at finde massen m af bogstav aa bruger jeg så 

m:=mA[ord(aa)]

Jeg håbede at denne sidst løsning var hurtigere men den gav den samme hastighed.

Kan jeg skrive direkte til swapdisken fra delphi?
Avatar billede martinlind Nybegynder
04. august 2006 - 18:31 #14
men inden du så standhaftigt ævler om størelse osv. så check lige delphi måde at allokere mem. på og deres compiler's måde at håndtere de forskellige typer på, bare et godt råd
Avatar billede arne_v Ekspert
05. august 2006 - 01:21 #15
32 bit windows har et 4 GB virtuelt adresse rum

default er det fordelt med 2 GB til process space og 2 GB til system space

Windows Server kan booted med et 3GB flag som ændrer 2+2 til 3+1 - det forlyder
at man også kan på XP
Avatar billede hrc Mester
05. august 2006 - 23:18 #16
martinlind: Hvad er der med dig? Synes det lyder som om du kender nogle svagheder i Delphis ramallokering som vi åbenbart ikke gør.
Hvorfor bruger du ordet "ævler" - og om hvem gør du det? Hvis vi kommer med urette oplysninger så ret dem, men vær' ikke flabet - hvis karma ellers skulle have en virkning, så ville det trække ned.
Avatar billede hrc Mester
05. august 2006 - 23:33 #17
ruma: Nu aner jeg intet om aminosyrer, men er der linier hvor visse syrer ikke forekommer, eller er der altid 20?

Hvis det er variabelt så er den første løsning bedst - hvis du kun registrerer de målte syrer og allokerer ram derefter.
Hvis ikke, så er den sidste løsning bedst, men du skal lige ændre lidt hist og her: Den er nemlig spild af ram.
Hvis aminosyrerne er i store bogstaver (A,B,C...) så var det smartere at lave en array[0..19] of real og tilgå den vha. m := mA[ord(aa)-65]; Så sparede du ialt fald 236 bytes pr. linie. Du sparer også en char i din record.

Du kan godt allokere ram direkte til swap-disken, men hvorfor bekymre dig om det? Hvis du allokerer 1Gb så klarer XP det for dig. Prøv den letteste løsning først og se hvordan det går. Opgradér eventuelt til en større processor...
Avatar billede ruma1974 Nybegynder
06. august 2006 - 12:52 #18
hrc: Der er altid 20 aminosyrer. En aminosyre er en byggeklods som bliver brugt til at bygge proteiner i levende organismer. Eksemple, dit hår består af proteinet keratin. Et andet protein kaldet alkohol dehydrogenase omdanner alkohol til  acetaldehyde i vores mave og lever. Acetaldehyde skal helst hurtigt nedbrydes da vi ellers får de kendt tømmermænd ;-)   

Grunden til at jeg valgte at lave en array[0..255] er at så spare jeg en substraction operation for hver aminosyre og den forskel der er i ram som array[0..255] sammenlignet med array[0..20] er lille. Hov, jeg tror det er fordi jeg ikke har forklaret ordenligt hvordan det virker. Jeg gemmer ikke masserne for hver aminosyre på hver position jeg beregner dem under runtime hver gang da en float er større end en char. Dvs. jeg har brug for den hurtigst mulige rutine til at konverter en char til en float. Grunden til at jeg beregner hver gang er masserne skal adderes forskelligt fra gang til gang. Nogen gange skal alle subsequences masser beregnes andre gang alle subsequencer som ender på char "K".

Tak, jeg vil prøve at øge ram allokeringen til mit program.

Jeg kan muligvis lave noget optimering ved at bruge en anden type end real på bekostning af præcision.
Avatar billede ruma1974 Nybegynder
06. august 2006 - 13:00 #19
Martinlind jeg håber ikke jeg har irreteret dig med mine spørgsmål – det har ikke værret hensigten. Jeg har generelt haft stor gælde af dinne kommentarere i dette forum.
Avatar billede hrc Mester
06. august 2006 - 15:11 #20
du tager helt fejl om du mener min løsning ikke gør nogen stor forekel i forhold til din. En subtraktion er noget nær det simpleste for en CPU at udføre. Det forholdsmæssigt lang tid at allokere ram.
Et andet sted hvor du kan spare noget er ved at begrænse antallet af decimaler således at du kan rumme det i en integer. Hvis du har værdien 3.124 så er det mere økonomisk at gemme det som 3124 og så dividere. På den måde sparer du yderligere 4 bytes. Jeg erkender at en multiplikation og en division er anderledes tunge at danse med, men når du summerer skal du jo først dividere til sidst.
Avatar billede martinlind Nybegynder
06. august 2006 - 18:27 #21
det er stadig din compiler der styrer langt det meste, og hvis den er god, er din kode god :)
Avatar billede martinlind Nybegynder
06. august 2006 - 18:29 #22
hvis jeg var dig ville jeg kode det som jeg fandt nemest og så optimere det hvis det bliver nødvendigt !
Avatar billede ruma1974 Nybegynder
06. august 2006 - 21:16 #23
martinlind -> Jeg tror din point er at jeg får mest ud af selv at læse mere om kompileren. Jeg har dog ikke fundet noget som var godt at læse. De simple ting med ikke at checke out of bounds har jeg naturligvis slået fra i compiler option.
Avatar billede ruma1974 Nybegynder
06. august 2006 - 21:43 #24
Jeg fandt dog følgende artikel.

http://www.drbob42.com/delphi/perform.htm

Bortset fra de simple on/off option i compiler settings var min konklusion på den artikel at Delphi klare det meste optimering selv.
Avatar billede ruma1974 Nybegynder
06. august 2006 - 21:50 #25
martinlind -> jeg ville dog godt lære noget mere om enum. Har du en god reference?
Avatar billede martinlind Nybegynder
06. august 2006 - 22:07 #26
Det er er "værd at optimere", ja :)

Ref.: F1 - online hjælp :)
Avatar billede martinlind Nybegynder
06. august 2006 - 22:41 #27
og så glemte jeg lige delphi's source, der er også et og andet at hente :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester