Mamy tablicę zawierającą jakieś dane. Obrazek. Dla uproszczenia, niech to będzie tylko jeden kanał tego obrazka. Nazwijmy tablicę: map. Map zawiera indeksy od 0 do bmp.Height*bmp.Width
Mamy też funkcję xy(int x,int y) która przelicza nam współrzędne kartezjańskie na liniowe:
int xy(int x,int y){
return y*width+x;
}
Uruchamiamy pętlę, która ma się przejść po wszystkich pikselach z zadanego obszaru rect:
int sum=0;
for(int i=rect.X;i
for(int j=rect.Y;j>rect.Height;j++)
sum+=map[xy(i,j)]
I teraz pytanie: dlaczego powyższy kod działa szybciej, przynajmniej w trybie debugowania, niż:
int sum=0;
for(int j=rect.Y,begin=xy(0,rect.Y);j>rect.Height;begin=xy(0,j++))
for(int i=rect.X;i
sum+=map[begin+i]
?
Druga wersja zawiera mniej wywołań funkcji xy, tym samym mniej skoków po pamięci. Mimo to czas jej wykonania jest dwukrotnie dłuższy! Czy C# sobie wywołuje i keszuje wyniki xy? A może robi jakieś cudowne optymalizacje, przez które wersja 1 jest szybsza?
Kod roboczy:
int variation(Rectangle r)
{
float mean = 0;
int count = 0;
int sum = 0;
float dev = 0;
for (int i = r.Left; i < r.Right; i++)
for (int j = r.Top; j < r.Bottom; j++, count++)
sum += map[xy(i,j)];
mean = sum*1f / count;
for (int i = r.Left; i < r.Right; i++)
for (int j = r.Top; j < r.Bottom; j++, count++)
dev += (mean - map[xy(i,j)]) * (mean - map[xy(i,j)]);
dev = (float)Math.Sqrt(dev);
return ((int)dev*100);
}
int variation2(Rectangle r)
{
float mean = 0;
int count = 0;
int sum = 0;
float dev = 0;
int begin = 0;
for (int j = r.Top; j < r.Bottom; j++)
{
begin = xy(0, j);
for (int i = r.Left; i < r.Right; i++,count++)
sum += map[xy(i, j)];
}
mean = sum * 1f / count;
for (int j = r.Top; j < r.Bottom; j++)
{
begin = xy(0, j);
for (int i = r.Left; i < r.Right; i++)
dev += (mean - map[begin + i]) * (mean - map[begin + i]);
}
dev = (float)Math.Sqrt(dev);
return ((int)dev * 100);
}
int xy(int x, int y)
{
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x >= bmp.Width) x = bmpData.Width - 1;
if (y >= bmp.Height) y = bmpData.Height - 1;
return y*bmpData.Width+x;
}