Optimizacija programskog koda. Osnovne mogućnosti za optimizaciju koda od strane programera i kompajlera

Ponekad može biti teško odlučiti da li koristiti i++ ili ++i, ili izabrati između if-else i switch. Ovaj članak, napisan posebno za IT Works zajednicu, predstavlja najrealnije alate za optimizaciju koda koje bi svaki profesionalni programer trebao znati.

Neki ljudi misle da su dani optimizacije na nivou koda zauvijek prošli, ali to nije istina. Sada postoje mnoge platforme koje nemaju tako moćne kompajlere kao u Microsoft Visual Studio. Na primjer, shader jezici (hlsl, glsl) ili kod za CUDA, PlayStation3, SPU ili mobilne platforme. U zavisnosti od organizacije koda, njegova efikasnost može se razlikovati desetine puta, ponekad zbog neefikasnosti kompajlera, češće zbog pristupa memoriji.

Kada programirate za različite platforme, proučite mogućnosti vašeg kompajlera i karakteristike arhitekture procesora (ako pišete za određenu konzolu). Provedite testove performansi različitih opcija optimizacije. Često je teško predvidjeti koje će metode biti najefikasnije. A ovaj članak će vam reći različite tehnike koje vam mogu pomoći. Međutim, ne biste trebali optimizirati naslijepo, bez prethodne analize i profiliranja. Zapamtite da je prerana optimizacija zlo.

Ako ste VS programer na Windows-u, onda će se najvjerovatnije kompajler efikasno nositi sa mnogim opisanim tehnikama optimizacije. Obratite pažnju na točke rada s memorijom, a preporučujem i upoznavanje s tehnologijom Dizajn orijentisan na podatke. U članku ćete pronaći nekoliko savjeta za njegovu upotrebu.

Dakle, počnimo:

1. Koristite komande za vektorizaciju podataka i vektorsku obradu (na primjer, SSE u CPU-u ili pakirajte podatke ako koristite shadere ili CUDA). Ovo će omogućiti korištenje SIMD (Single Instruction, Multiple Data) arhitekture, što će značajno povećati brzinu proračuna. Ako odlučite koristiti ovu metodu, pazite da podaci budu usklađeni u memoriji.

2. Efikasnije je zbrkano sabirati i množiti nego prvo sve sabrati pa sve pomnožiti. To se događa zato što sabiranje i množenje izvode različiti procesorski moduli i mogu se izvoditi istovremeno.
int a,b,c,k,m,n,t,f1,f2,f3,g1,g2,g3; a = b + c; k = m + n; t = a + k; f1 = f2 * f3; g1 = g2 * g3; Manje efektivno od: a = b + c; f1 = f2 * f3; k = m + n; g1 = g2 * g3; t = a + k;

3. Nema razlike u brzini kada radite sa float-om i duplom prilikom sabiranja i množenja. Izvršavaju se u istom broju procesorskih ciklusa i koriste iste registre. Prilikom dijeljenja i ukorjenjivanja, plutanje je brže. Međutim, ako koristite velike količine podataka, onda zbog cache-a tip koji zauzima manje memorije(tj. plutaju), pa je općenito poželjno koristiti ga. Odabir dvostrukog ima smisla kada je potrebna veća preciznost.

4.
Recimo da postoji. const float a = 100.0f; float some1 = some3 * 1.0f/a; float some2 = some4 * 1.0f/a; efikasnije je napisati ne: const float a_inv = 1.0f / a; neki1 = neki3 * a_inv; neki2 = neki4 * a_inv; i tako: neki1 = neki3 * (1.0f / a); neki2 = neki4 * (1.0f/a); Zašto će ovo biti efikasnije? Operatori sa jednakim prioritetom se izvršavaju sekvencijalno. To znači da će se prvo izvršiti množenje, a zatim dijeljenje. Ako operaciju dijeljenja stavite u zagrade, kompajler će je izvršiti, a samo će operacija množenja biti izvedena u realnom vremenu. Što se tiče razlika između opcije 3 i opcije 2, u opciji 3 se ne kreira dodatna varijabla, nema potrebe gledati u kod da bi razmišljali o kakvoj se varijabli radi. I efikasnost 2. i 3. opcije će biti ista.

5. Za velike količine podataka i kalkulacije na njima, float je isplativiji nego duplo (zbog promašaja keša, vidi tačku 3).

6.
a, b - bilo koji izraz Func1, Func2 - funkcije koje će biti pozvane da izračunaju uslov if(a && b) - potrebno je da prvo stavite manje verovatan uslov, za veću efikasnost if(a || b) - morate prvo stavite vjerovatniji uvjet, za efikasniji if(Func1() && Func2()) - trebate staviti brži operator na prvo mjesto

7.
void Func(int* a) ( int b = 10; Sljedeći redovi su jednaki po efikasnosti (u smislu vremena izvršenja): b = 100; *a = 100; ) Ovo se dešava zato što se varijabli steka pristupa pomoću pokazivača na stek. Pokazivač se također dereferencira.

8. Ako postoji veliki niz struktura, tada morate učiniti veličinu njegovih elemenata jednakom potenciji dva. Tada će prolazak kroz takav niz biti mnogo brži (4-6 puta), zbog poravnanja pokazivača na svaku strukturu u nizu.

9.
int a[1000]; for(int i =0; i= b ? -1: 0); Može se zamijeniti sa: 1. int x = (b - a) >> 31; 2. int x = (b - a) & 0x80000000;

25.
i32 iIndex; Uvjet: if(iIndex< 0 && iIndex >= iSize) Može se zamijeniti sa ovim: if((u32)iIndex >= iSize) Uvjet: if(i >= min && i

Učitavanje...
Top