2

画像内のピクセルの回転をシミュレートするように設計された C コード (私がどちらかというと苦手な言語) を最適化する課題があります。

void naive_rotate(int dim, pixel *src, pixel *dst) {
    int i, j;
    for (i = 0; i < dim; i++)
        for (j = 0; j < dim; j++)
            dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
}

pixelとの定義はRIDX次のとおりです。

typedef struct {
    unsigned short red;
    unsigned short green;
    unsigned short blue;
} pixel;

#define RIDX(i,j,n) ((i)*(n)+(j))

課題の指示には、「このコードを書き直して、コードの移動、ループの展開、ブロックなどの手法を使用して、可能な限り高速に実行するようにする必要があります」というメモが含まれています。

これにアプローチする方法についていくつかのアイデアがあると思いました。ただし、ループ展開の私の試み:

void rotate_unroll(int dim, pixel *src, pixel *dst) {
    int i, j;
    for (i = 0; i < dim; i++) {
        for (j = 0; j < dim; j+=4) {
            dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
            dst[RIDX(dim-1-(j+1), i, dim)] = src[RIDX(i, j+1, dim)];
            dst[RIDX(dim-1-(j+2), i, dim)] = src[RIDX(i, j+2, dim)];
            dst[RIDX(dim-1-(j+3), i, dim)] = src[RIDX(i, j+3, dim)];
        }
    }
}

およびコードの動き (または、少なくとも RIDX を再編成し、内側のループからいくつかの計算を移動します):

void rotate_motion(int dim, pixel *src, pixel *dst) {
    int i, j;
    int dimsquared = dim * dim;
    for (i = 0; i < dim; i++) {
        int dst_temp = dimsquared - dim + i;
        int src_temp = i * dim;
        for (j = 0; j < dim; j++) {
            dst[dst_temp - (dim * j)] = src[src_temp + j];
        }
    }
}
//   dst[RIDX(dim-1-j, i, dim)] 
// = dst[(dim-1-j)dim + i] 
// = dst[(dim * dim) - dim - (dim)j + i]
//   src[RIDX(i, j, dim)]
// = src[(dim)i + j]

機能していないようです。割り当てにパッケージ化されたタイマーは、私のソリューションがプログラムの CPE に影響を与えていないと主張しています。私はおそらく両方の方法に間違って取り組んでいると思われ、正しい方向へのガイダンスを大いに感謝します. (これは宿題なので、完全な解決策を求めているわけではなく、いくつかのヒントを求めているだけです。)

私の他の考えは、アキュムレータを追加しようとすることでした-次の行に沿った何か:

void rotate_acc(int dim, pixel *src, pixel *dst) {
    int i, j;
    pixel temp = dst;
    for (i = 0; i < dim; i++) {
        for (j = 0; j < dim; j++) {
            temp[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
        }
    }
    dst = temp;
}

しかし、私の構文は非常に間違っており、問題の構造体の一時的なバージョンを構築する方法がわかりません。

どんな助けでも大歓迎です。ありがとう!

4

2 に答える 2

1

C のポインターについて十分に理解する必要があります。簡単に言えば、ポインターはデータがメモリに格納されている場所のアドレスを表します (この場合はピクセル構造体)。

コードでは、関数rotate_accはピクセル ポインターを引数として取ります: pixel *dst. 最初は と言いたくなるかもしれませんが、これはシャロー コピーpixel *tmp = dstと呼ばれるものであることを覚えておいてください- アドレスのみがコピーされ、それが指しているデータはコピーされません - したがって、 と言って tmp を変更すると、元のデータが変更されますそれもtmp->red = 0

ディープ コピーが必要な場合は、次のように言う必要があります。pixel tmp = *dst

于 2013-02-01T04:18:30.030 に答える
0

これを試して:

void naive_rotate(int dim, pixel *src, pixel *dst) {
    int dimSq = dim * dim;
    int dstdIxStart = dimSq - dim;
    int endIdx = dimSq - 2 * dim - 2;
    int dstIdx = dimSq - dim;
    for (int i = 0; int < endIdx; ++i)
    {
       dst[dstIdx--] = src[i];
       if (0 == dstIdx)
       {
          dstdIxStart -= dim;
          dstIdx = dstdIxStart;
       }
    }
}

数学を再確認する必要がありますが、理解していただければ幸いです。

すべての乗算を削除します。また、srcシーケンシャルにアクセスされるので、キャッシュにも適しています。

于 2013-02-01T04:42:36.673 に答える