1

私は 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(&current_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 に変化をもたらすかについての洞察をいただければ幸いです。

ありがとう!

4

0 に答える 0