[英]Optimizing C code with loop unrolling/code motion
我有一项任务是优化一段旨在模拟图像中旋转像素的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;
}
但是我的语法在那里很错误,我不确定如何构造一个有问题的结构的临时版本。
任何帮助深表感谢。 谢谢!
您需要对C中的指针有透彻的了解。简单地说:指针代表数据存储在内存中的地址(在您的情况下为像素结构)。
在您的代码中,函数rotate_acc
将像素指针作为参数: pixel *dst
。 最初,您可能会想说pixel *tmp = dst
,但是请记住,这就是所谓的浅表复制 -仅复制地址,而不复制其指向的数据-因此,如果您说tmp->red = 0
,它也会修改原始数据
如果需要深层复制 ,则需要说pixel tmp = *dst
尝试这个:
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
被顺序访问,因此对缓存也有好处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.