私は C コードを最適化する課題に取り組んでいます。教授は、コード モーションがこの特定の問題に対する主要なツールであるべきだとほのめかしています。
最初の最適化されていないコードは次のとおりです。
void naive_smooth(int dim, pixel *src, pixel *dst) {
int i, j;
for (i = 0; i < dim; i++)
for (j = 0; j < dim; j++)
dst[RIDX(i, j, dim)] = avg(dim, i, j, src);
}
typedef struct {
unsigned short red;
unsigned short green;
unsigned short blue;
} pixel;
#define RIDX(i,j,n) ((i)*(n)+(j))
static pixel avg(int dim, int i, int j, pixel *src) {
int ii, jj;
pixel_sum sum;
pixel current_pixel;
initialize_pixel_sum(&sum);
for(ii = max(i-1, 0); ii <= min(i+1, dim-1); ii++)
for(jj = max(j-1, 0); jj <= min(j+1, dim-1); jj++)
accumulate_sum(&sum, src[RIDX(ii, jj, dim)]);
assign_sum_to_pixel(¤t_pixel, sum);
return current_pixel;
}
static void initialize_pixel_sum(pixel_sum *sum) {
sum->red = sum->green = sum->blue = 0;
sum->num = 0;
return;
}
static void accumulate_sum(pixel_sum *sum, pixel p) {
sum->red += (int) p.red;
sum->green += (int) p.green;
sum->blue += (int) p.blue;
sum->num++;
return;
}
static void assign_sum_to_pixel(pixel *current_pixel, pixel_sum sum) {
current_pixel->red = (unsigned short) (sum.red/sum.num);
current_pixel->green = (unsigned short) (sum.green/sum.num);
current_pixel->blue = (unsigned short) (sum.blue/sum.num);
return;
}
そして、これが私がこれまでに得た最適化されたバージョンです:
void smooth(int dim, pixel *src, pixel *dst) {
int i, j;
int ii, jj;
pixel_sum sum;
pixel current_pixel;
pixel p;
int localDim = dim;
for (i = 0; i < localDim; i++) {
int dimi = localDim * i;
int mini = min(i+1, localDim-1);
int maxi = max(i-1, 0);
for (j = 0; j < localDim; j++) {
int minj = min(j+1, localDim-1);
int maxj = max(j-1, 0);
sum.red = sum.green = sum.blue = sum.num = 0;
for(ii = maxi; ii <= mini; ii++) {
int dimii = localDim * ii;
for(jj = maxj; jj <= minj; jj++) {
p = src[dimii + jj];
sum.red += (int) p.red;
sum.green += (int) p.green;
sum.blue += (int) p.blue;
sum.num++;
}
}
current_pixel.red = (unsigned short) (sum.red/sum.num);
current_pixel.green = (unsigned short) (sum.green/sum.num);
current_pixel.blue = (unsigned short) (sum.blue/sum.num);
dst[dimi + j] = current_pixel;
}
}
}
これまでに行った変更はすべて、コード モーション最適化の原則であると考えていたものです。メソッド呼び出し (avg、initialize_pixel_sum など) をローカル コードに変換し、グローバル変数のローカル バージョンを作成しました。 (dim から localDim)、ループ定義内の関数をループの外に移動しました (min 関数と max 関数、dim/localDim での乗算)。ただし、割り当てに付属のテストスイートは、これが元のコードと同じ結果を生成していることを示していますが、CPE にはまったく変化がないことを示しています...したがって、最適化効果を引き起こさずにコードを書き直しました。
なぜこれがまったく効果がないのか、私は本当に当惑しています。どのような種類のコードの動きが、この一連の関数の CPE に変化をもたらすかについての洞察をいただければ幸いです。
ありがとう!