LÖST Inline assembleroptimering. Hjälp!

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
agehall
Inlägg: 418
Blev medlem: 12 augusti 2020, 19:27:54

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av agehall »

Så länge loopen får plats i processorcachen så spelar det nästan ingen roll vad den gör - det går så fort ändå numera.

Om man verkligen har prestanda problem med en så här pass enkel operation (även om GCC verkar spotta ur sig massor av kod för en enkel operation) så är alternativet för att komma upp en nivå i prestanda nog enbart att gå till någon hårdvaruaccelererad lösning.
Findecanor
Inlägg: 982
Blev medlem: 2 juli 2010, 23:04:07

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Findecanor »

Jag tror att looparnas prestanda begränsas mest av att minnesaccesserna i arrayerna. De är mycket långsammare än instruktioner mellan register, särskilt när datat inte ligger i cache:n. Så länge som man håller variablerna i register och inte spiller till stacken i onödan.

Det stod inte vilka typer som används, men jag stoppade in koden från första inlägget i Compiler Explorer med alla variabler som ints och såg att med -O3 så kunde GCC omvandla den till att använda SSE (SIMD)-instruktioner för att göra flera operationer samtidigt.
Det borde kunna gå snabbare, men det blev mer kod totalt eftersom SSE-instruktioner bara kan läsa och skriva hela vektor-register, så kompilatorn behöver generera en vanlig loop också för resten.

Vad som är bästa sättet att optimera på har förändrats en hel del under åren. Jag tror inte att loop unrolling och instruktions-ordning är lika viktigt som tidigare nu när processorer är out-of-order.
De som skriver kompilatorer har nog bättre koll på optimering det än de flesta andra. Å andra sidan så missar kompilatorer ibland. Jag skrev om for-looparna till ekvivalent do-while, och då blev det samma resultat med -O3 som -O1.
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6888
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Nu har jag gjort ett test med hela rutinen där den aktuella loopen ingår. 100k rundor.

Ingen inline
ingen optimering 22 sek
O2 20 sek
O3 20 sek
Os 20 sek

Med inline
Ingen optimering 22 sek
O2 20 sek
O3 20 sek
Os 20 sek

Resultat: :( :( :( :( :( :( :( :( :( :(

Nåväl, det var i varje fall lärorikt. Fullständigt meningslöst att försöka pressa tiden. I varje fall utan att först verkligen ta reda på var långsamheten finns. Förslag på lämplig profiler?

Tack till alla som engagerat sig i det här. Alla resultat pekar i samma riktning: Låt compilern sköta sitt utan inblandning, det blir bäst så...
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1339
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av baron3d »

Det påminner mig om min 3D-motor, en gång i tiden.
Samma sak där. Hur jag än optimerade gick det inte fortare. Då var det minnes access som ställde till det. Lösningen var att läsa data ur array:en ett varv innan datan skulle användas. Det gav cash-minnes-controllern tid att hämta data.
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6888
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Ja, optimering är svårt.

Ett par gånger har jag verkligen lyckats, men det var var för lääääänge sedan.
En var på en ABC800. Först tog en statistikberäkning 3 timmar. Sedan köptes ett svindyrt kort för disk-cache. Då tog det 45 minuter. Sedan assembleroptimerades datainsamlingen och tiden sjönk till 1.5 minuter. Men att överträffa en BASIC-interpreter är ju extremt lätt...

Hittade gprof och körde ett par tester. Utan asm-rutin blir det 100% 3.68 sek på hela rutinen. med asm får jag detta:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
 78.41      3.05     3.05   103500     0.00     0.00  tested
 21.34      3.88     0.83                             LLL1
  0.26      3.89     0.01        1     0.01     2.96  testLoop
Men var blir all den andra tiden av upp till 20 sek? Kan det vara så att mätningen stannar när den hoppar in i en systemrutin som ingår i "tested"? Det är ju obra, vill ju veta hur mycket tid en funktion förbrukar som helhet. Det är bara när den sitter fast i XNextEvent som den bör sluta mäta. Allt annat är ju exekveringstid som förbrukas.
Användarvisningsbild
Jan Almqvist
Inlägg: 1580
Blev medlem: 1 oktober 2013, 20:48:26
Ort: Orust

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Jan Almqvist »

Skulle det gå att dela arbetet mellan flera kärnor?
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6888
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Där är inget problem alls på min gamla i7. Med moderna datorer är det ett icke-problem. Tidsåtgången sitter nog i XPutImage. Har ingen aning om vad denna hittar på. Kanske ingår en formatkonvertering som är seg. Vad det än är så förbrukas över 15 av de 20 sekunder testet tar av något som gprof inte redovisar. Finns antagligen inget att göra åt det och med 0.2ms är den alldeles tillräckligt snabb med god marginal, så finns ingen anledning att göra något mer åt det.

Hur som, det har varit en lärorik erfarenhet...
Nerre
Inlägg: 26655
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Nerre »

Som flera är inne på är det nog oftast minnesaccessen som är problemet. Nu är jag inte helt säker på hur moderna minnen fungerar, men är det inte så med DRAM att man måste skicka två adresser, en rad-adress och en kolumn-adress? Och då antar jag att varje läsning eller skriv är tre steg: Skriv rad-adress, skriv kolumn-adress och sen läs eller skriv från adressen. Det blir då tre gånger så lång tid som att använda ett register.

Men sen är det väl också kanske så att minnesaccessen använder en långsammare klocka än vad processorn använder internt?

Därför vill man oftast göra "read-ahead", så adressering av minnet görs medans processorn kör annan kod, och sen läser man från minnet lite senare.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av sodjan »

Access av register har ingen extra fördröjning utöver tiden det tar att exekvera instruktionerna.
Hittade en sida https://cvw.cac.cornell.edu/codeopt/memtimes där latency är som exempel:
Register: 0 (utöver tiden för att exekvera instruktioners).
L1 cache: 2 ns (4 cyc.)
L2 cache: 7 ns (14 cyc.)
L3 cache: 26 ns
Main RAM: 90 ns.

Så för RAM så har vi en fördröjning på nästan 200 cykler, eller ungefär lika många instruktioner eller lika många gånger mer än en register access.

En read-ahead förutsätter att men kan gissa vilken nästa minnes adress det är som man önskar.
Annars skrivs cachen över av en massa data som man ändå inte behöver. Processorer med OOO
kan ändra ordningen för att hämta data som man vet behövs tidigare. Men störst fördelar får
man av kod som är optimerar för att använda data som ligger nära varandra eller i sekvens.
T.ex. i vilken ordning man läser i en flerdimensionell matris.
Skriv svar