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;
}