webForumDet fria alternativet

Prestandavinst med asm

10 svar · 516 visningar · startad av pettsson

pettssonMedlem sedan jan. 20021 122 inlägg
#1

Jag utför fyra flyttalsmultiplikationer i en loop som körs ca. 70 miljoner ggr per slinga, vilken ligger i en while(true) loop. I dagsläget tar det ~200 millisek, vilket är lite för långsamt för att applikationen ska flyta på (animation av en fraktal).
Frågan är nu ungefär hur mycket snabbare jag kan räkna med att det går om jag kör inline asm istället för vanlig C? Och om någon har koll på en bra tutorial/motsv., jar har hittat ett par som inte lyckades guida mig till en fungerande "Hello World"... :OO

PeWMedlem sedan juni 200010 432 inlägg
#2

Anledningen till att assembler är snabbare i vanliga user-mode program beror mest på hur kompilatorn har översatt annan kod till maskinkod vs assemblatorns översättning. Dagens kompilatorer är bra och det ger ofta inte så stor skillnad. Egentligen är det sällan motiverat att skriva inlineassembler som optimering.. det kan däremot vara en vits med det om man skriver program som ligger nära hårdvaran och/eller kernel.

Ditt programmerarmässiga problem ligger nog mer i flaskhalsen mellan processorn och minnet. Jag tror inte du kan optimera bort det helt genom assembler utan du kanske först ska titta till hur dina variabler är deklarerade. Variabler som ligger långt ifrån scope ger att varje iterering medför en massa overhead för cacheminnet som swappar mot RAM i hela block, vilket tar tid. Så i en loop bör man i optimeringssyfte hålla sig till små scope och använda lokala variabler så långt det bara går.. nu är det ju flyttal du arbetar med och det är ett kapitel för sig eftersom det i sin tur anropar flyttalsprocessorn och en massa annat jox.. där kan det vara jättesvårt att hitta en bra optimering. Därför kanske du ska titta till alternativa lösningar där du använder flyttal så lite som möjligt... en array kan ju göras stor nog för att rymma stora tal och representera ett flyttal utan decimaltecknet som du kanske kan konvertera till lite senare. (Bara en idé, jag vet ju inte exakt vad du gör eller hur koden ser ut).

pettssonMedlem sedan jan. 20021 122 inlägg
#3
for(renY = ymin; coordY < scrY; renY += deltaY, coordY++) {
 coordX = 0;
 for(renX = xmin; coordX < scrX; renX += deltaX, coordX++, coordAr++) {
  it = 0;
  zRe = renX;
  zIm = renY;
  while (true) {
   zReo = zRe;
   zRe = (zRe+zIm)*(zRe-zIm)+cRe;
   // ^-- borde väl vara snabbare än --v?
   //zRe * zRe - zIm * zIm + cRe;
   zIm = 2 * zReo * zIm + cIm;
   if ((zRe * zRe + zIm * zIm) > 4) {
    break;
   }
  it++;
  if (it >= itMax) {
   break;
  }
 }
 itArray[coordAr] = it;
}
}

Alla variabler utom de med namn it* är av typ double. Skulle det alltså gå snabbare att flytta in deklarationen av variablerna till den inre for-loopen?

PeWMedlem sedan juni 200010 432 inlägg
#4

Möjligen, för nu anropas adresser som ligger utanför scope, vilket medför det jag ovan nämnde. Jag är dock inte säker på att det gör så jättestor skillnad. Kompilatorn kan ju ha fixat till det på bästa sätt redan. Problemet för dig är nog snarare att du använder flyttal ö.h.t. Det blir en hel del overhead för processorn, vid varje uttryck.

pettssonMedlem sedan jan. 20021 122 inlägg
#5

Gjorde lite försök med att dela upp flyttalen i två int-arrayer, men hade lite svårt att få till räknandet. Tog heltalsdelen i en array och decimaldelen * 10^16 i den andra. Men som jag fått till det måste man ha en massa if-satser för att kolla om resultatet i decimaldelen blir större än ett så att man ökar i heltalsarrayen. Hur pass snabba är if-ar egentligen?

PeWMedlem sedan juni 200010 432 inlägg
#6

Rätt översatt är de inte mer långsammare än "cmp x,x : bge NEXT" eller liknande i assembler. Antagligen är det ivf betydligt snabbare än ett anrop till flyttalsprocessorn. Tider på såna anrop bör väl finnas att läsa om på processortillverkarens produktblad. Som redan sagts så hänger en hel del på kompilatorn och hur den översätter till maskinkod. De är numera bra på att optimera redan från början, men det finns fall som är svåra att optimera och det är bl.a på cache-delen. Att få koden att exkeverera i cache på bästa sätt.

PeWMedlem sedan juni 200010 432 inlägg
#7

Jag antar att det är Intel Pentium du använder. Så jag tittade runt lite efter exekvereringstider med flyttal, men det var så mycket att leta i och det finns en del tjusiga tekniker på processorsidan för att komma över flaskhalsar, beroende på vilken processor som används, så jag gav upp. Det behövs väl även en rätt inställd kompilator för att få till det med just den processorn. Men jag hittade ivf ett intressant pdf-blad, som beskriver lite mer ingående det jag nämnt om optimering:

http://www.intel.com/products/services/intelsolutionservices/success/techdocs/wp/coding.pdf

Sang-draxMedlem sedan juli 2002581 inlägg
#8

Vilket värde har du på itMax?
Det behöver inte vara så stort.

pettssonMedlem sedan jan. 20021 122 inlägg
#9

PeW: Tackar, ska läsa igenom den.
Sang-drax: Jag har 300 som brytvärde för de koordinater som bedöms vara intressanta, dvs. koordinater som inte är del av Mandelbrot-mängden (då dessa blir en samlad klump som alltid kommer att gå mot oändligheten).
För att det ska se bra ut i fullskärm behövs ungefär så många.

Sang-draxMedlem sedan juli 2002581 inlägg
#10

Kanske kan du köra fler itereringar åt gången innan du kör testet med två multiplikationer.

Annars är lösningen att helt enkelt ha en bild med färre pixlar i sig. Vill du visa den på fullskärm får du skala upp den med någon lämplig algoritm.

Har du en processor med HyperThreading (eller ännu bättre, flera kärnor) kan du dela upp beräkningen i två trådar.

För övrigt kan du nog glömma att göra om din kod till heltal.
Dagens processorer är bra på flyttal och och om du skall konvertera talen till heltal för att göra räkneoperationer så kommer det med all säkerhet att gå långsammare.

PeWMedlem sedan juni 200010 432 inlägg
#11

Sang-drax skrev:

För övrigt kan du nog glömma att göra om din kod till heltal.
Dagens processorer är bra på flyttal och och om du skall konvertera talen till heltal för att göra räkneoperationer så kommer det med all säkerhet att gå långsammare.

Beror på när man konverterar. Är det bara att skyffla data är heltal snabbare, vilket är poängen. Nu har jag inte sagt att det är en bättre lösning (eftersom jag inte satt mig in i exakt vad som ska göras) eftersom det beror ju helt på hur ofta en konvertering mot flyttal ska ske, utan det jag svarat på är prestanda rent generellt - utan hänsyn till vilken typ av processor som används. :)

135 ms totalt · 3 externa anrop · v20260731065814-full.91fd2ad2
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)