Оптимизация программ

advertisement
Некоторые вопросы
оптимизации
Содержание
Упрощение алгебраических выражений
 Использование регистров
 Использование быстрых инструкций
 Оптимизация работы циклов
 Эффективное использование памяти

2
Упрощение алгебраических выражений
Исходный код
Оптимизированный код
x = y + 0;
x = y * 0;
x = y / 1;
x = y;
x = 0;
x = y;
3
Упрощение алгебраических выражений
Исходный код
if( a[y*3]<0 || b[y*3]>10)
a[y*3] = 0;
Оптимизированный код
ind=y*3;
if( a[ind]<0 || b[ind]>10)
a[ind] = 0;
4
Упрощение алгебраических выражений
Исходный код
Оптимизированный код
int i, j, k, m;
m = i / j / k;
int i, j, k, m;
m = i / (j * k);
5
Упрощение алгебраических выражений
Исходный код
Оптимизированный код
if(a[i]<a[j])
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
t1=a[i]; t2=a[j];
if(t1<t2)
{
t = t1;
a[i] = t2;
a[j] = t;
}
4 обращения в память
2 обращения в память
6
Упрощение алгебраических выражений
Исходный код
if (a <= max && a >= min && b <= max && b >= min)
Оптимизированный код
if (a > max || a < min || b > max || b < min)
7
Использование регистров
Исходный код
Оптимизированный код
int v;
float t;
register int v;
register float t;
for(v=0;v<1000;v++)
ar[v] += (float)v * t;
for(v=0;v<1000;v++)
ar[v] += (float)v * t;
8
Использование быстрых инструкций
Исходный код
Оптимизированный код
int a, b;
b = a * 10;
int a, b;
b = (a<<3) + (a<<1);
9
Использование быстрых инструкций
Исходный код
Оптимизированный код
const int b=16;
scanf(“%d”,&a);
// a=49;
c = a/b;
const int b=16;
const int d=16/16;
scanf(“%d”,&a);
// a=49;
c = (a>>4)*d;
// c = (a/16)*(16/b)
!!! Проблема выбора d
10
Использование быстрых инструкций
Исходный код
Оптимизированный код
const int b=16;
scanf(“%d”,&a);
// a=49;
c = a%b;
const int b=16;
const int d=-16;
scanf(“%d”,&a);
// a=49;
c = a – (a&d);
N



2
a 
t
t
a %b  a %  k  2   a   
 N  &  2    k
 k 2 

11
Использование быстрых инструкций
Исходный код
Оптимизированный код
char animalname[30];
char *p;
p = animalname;
if ((strlen(p) > 4) &&
(*p == 'y')) { ... }
char animalname[30];
char *p;
p = animalname;
if ((*p == 'y') &&
(strlen(p) > 4)){ ... }
!!! Сначала выполняются простые логические операции
12
Использование быстрых инструкций
Исходный код
double x;
int i;
i = x;
Оптимизированный код
#define DOUBLE2INT(i, d) \
{double t = ((d) + 6755399441055744.0); \
i = *((int *)(&t));}
double x;
int i;
DOUBLE2INT(i, x);
!!! 6755399441055744.0 = 2^52 + 2^51
13
Оптимизация работы циклов
Исходный код
Оптимизированный код
for(i=0;i<10;i++)
a[i]=b[i]+c[i];
for(i=0;i<10;i++)
d[i]=e[i]+f[i];
for(i=0;i<10;i++)
{
a[i]=b[i]+c[i];
d[i]=e[i]+f[i];
}
14
Оптимизация работы циклов
Исходный код
Оптимизированный код
for(i=0;i<1000;i++)
{
if(x<2) y+=i;
else y -=i;
}
if(x<2)
for(i=0;i<1000;i++)
y+=i;
else
for(i=0;i<1000;i++)
y-=i;
15
Оптимизация работы циклов
Исходный код
Оптимизированный код
for(i=0;i<100;i++)
{
if(i%2) a[i]=x;
else a[i]=y;
}
for(i=0;i<100;i+=2)
{
a[i]=y;
a[i+1]=x;
}
16
Оптимизация работы циклов
Исходный код
Оптимизированный код
for(i=0;i<1000;i++)
sum += a[i];
for(i=999;i>=0;i--)
sum += a[i];
!!! Инструкции декремента автоматически
устанавливают флаг zero при достижении нуля,
поэтому явная проверка с нулём не требуется
17
Оптимизация работы циклов
(раскрутка циклов)
Исходный код
// 3D-transform
for (i = 0; i < 4; i++)
{
r[i] = 0;
for (j = 0; j < 4; j++)
{
r[i] += m[j][i] * v[j];
}
}
18
Оптимизация работы циклов
(раскрутка циклов)
Оптимизированный код
// 3D-transform
r[0] = m[0][0] *
v[2] + m[3][0]
r[1] = m[0][1] *
v[2] + m[3][1]
r[2] = m[0][2] *
v[2] + m[3][2]
r[3] = m[0][3] *
v[2] + m[3][3]
v[0] + m[1][0]
* v[3];
v[0] + m[1][1]
* v[3];
v[0] + m[1][2]
* v[3];
v[0] + m[1][3]
* v[3];
* v[1] + m[2][0] *
* v[1] + m[2][1] *
* v[1] + m[2][2] *
* v[1] + m[2][3] *
19
Оптимизация работы циклов
(раскрутка циклов)
Исходный код
double a[100], sum;
int i;
sum = 0.0;
for (i = 0; i < 100; i++)
{
sum += a[i];
}
20
Оптимизация работы циклов
(раскрутка циклов)
Оптимизированный код
double a[100], sum1, sum2, sum3, sum4, sum;
int i;
sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0;
for (i = 0; i < 100; i += 4)
{
sum1 += a[i];
sum2 += a[i+1];
sum3 += a[i+2]; sum4 += a[i+3];
}
sum = (sum4 + sum3) + (sum1 + sum2);
21
Эффективное использование памяти
Исходный код
double x[VECLEN], y[VECLEN], z[VECLEN];
unsigned int k;
for (k = 1; k < VECLEN; k++) {
x[k] = x[k-1] + y[k];
}
for (k = 1; k < VECLEN; k++) {
x[k] = z[k] * (y[k] - x[k-1]);
}
22
Эффективное использование памяти
Оптимизированный код
double x[VECLEN], y[VECLEN], z[VECLEN];
unsigned int k;
double t;
t = x[0];
for (k = 1; k < VECLEN; k++) {
t = t + y[k];
x[k] = t; }
t = x[0];
for (k = 1; k < VECLEN; k++) {
t = z[k] * (y[k] - t);
x[k] = t;}
23
Эффективное использование памяти
(выравнивание данных)
Исходный код
Оптимизированный код
struct
{
char a[5]; // 5b
long k;
// 4b
double x; // 8b
} baz;
struct
{
double x;
long k;
char a[5];
char pad[7];
} baz;
//
//
//
//
8b
4b
5b
7b
24
Эффективное использование памяти
Исходный код
Оптимизированный код
float a_cmplx[500],
b_cmplx[500];
struct complex
{ float a, b;};
complex cmplx[500];
25
Эффективное использование памяти
(выравнивание данных)
Исходный код
Оптимизированный код
short ga, gu, gi;
long foo, bar;
double x, y, z[3];
char a, b;
float baz;
double z[3];
double x, y;
long foo, bar;
float baz;
short ga, gu, gi;
26
Эффективное использование памяти
(выравнивание данных)
Исходный код
short a[15]; /* 2 bytes data */
int b[15], c[15]; /* 4 bytes data */
for (i=0; i<15, i++) a[i] = b[i] + c[i];
27
Эффективное использование памяти
(выравнивание данных)
Оптимизированный код
int b[15], c[15]; /* 4 bytes data */
short a[15]; /* 2 bytes data */
for (i=0; i<15, i++) a[i] = b[i] + c[i];
28
Эффективное использование памяти
(предвыборка данных)
Оптимизированный код
for (ii = 0; ii < 100; ii++) {
for (jj = 0; jj < 24; jj+=8)
{ /* N-1 iterations */
_mm_prefetch((char*)&a[ii][jj+8],_MM_HINT_NTA);
computation(a[ii][jj]);
}
_mm_prefetch((char*)a[ii+1][0],_MM_HINT_NTA);
computation(a[ii][jj]); /* Last iteration */
}
29
Эффективное использование памяти
Исходный код
float **a;
a = new float*[512];
for(int i;i<512;i++) a[i]=new float[512];
a[i][j]; //a(i,j)
Оптимизированный код
float *a;
a = new float[512*512];
a[i*512 + j]; // a(i,j)
30
Эффективное использование памяти
Исходный код
float *memory = new float[4*N];
for(int i=0;i<N;i++)
{
a = *(memory+i*4);
b = *(memory+i*4+1);
c = *(memory+i*4+2);
*(memory+i*4+3) = func(a,b,c);
}
31
Эффективное использование памяти
Оптимизированный код
float
*a = new float[N],
*b = new float[N],
*c = new float[N],
*d = new float[N];
for(int i=0;i<N;i++)
{
d[i] = func(a[i],b[i],c[i]);
}
!!! Может привести к КЭШ - промаху
32
Download