我不确定我还能如何优化这段代码以使其高效。到目前为止,我已经将关于 j 的内部 for 循环展开 16,它产生的平均 CPE 为 1.4。我需要通过优化技术使平均 CPE 达到 2.5 左右。我已经阅读了与此相关的其他问题,与涉及的代码问题相比,它们有些不同。代码的第一部分显示了我给出的内容,然后是我尝试展开循环。给定的代码将扫描源图像矩阵的行并复制到目标图像矩阵的翻转行。任何帮助将不胜感激!
RIDX 宏:
#define RIDX(i,j,n) ((i)*(n)+(j))
给定:
void naive_rotate(int dim, struct pixel_t *src, struct pixel_t *dst)
{
int i, j;
for(i = 0; i < dim; i++)
{
for(j = 0; j < dim; j++)
{
dst[RIDX(dim-1-i, j, dim)] = src[RIDX(i, j, dim)];
}
}
}
我的尝试:这确实优化了它,但随着平均 CPE 从 1.0 上升到 1.4 而只优化了一点。我希望它在 2.5 左右,我尝试了各种类型的阻塞和我在网上阅读过的东西,但没有设法对其进行更多优化。
for(i = 0; i < dim; i++){
for(j = 0; j < dim; j+=16){
dst[RIDX(dim-1-i,j, dim)] = src[RIDX(i,j,dim)];
dst[RIDX(dim-1-i,j+1, dim)] = src[RIDX(i,j+1,dim)];
dst[RIDX(dim-1-i,j+2, dim)] = src[RIDX(i,j+2,dim)];
dst[RIDX(dim-1-i,j+3, dim)] = src[RIDX(i,j+3,dim)];
dst[RIDX(dim-1-i,j+4, dim)] = src[RIDX(i,j+4,dim)];
dst[RIDX(dim-1-i,j+5, dim)] = src[RIDX(i,j+5,dim)];
dst[RIDX(dim-1-i,j+6, dim)] = src[RIDX(i,j+6,dim)];
dst[RIDX(dim-1-i,j+7, dim)] = src[RIDX(i,j+7,dim)];
dst[RIDX(dim-1-i,j+8, dim)] = src[RIDX(i,j+8,dim)];
dst[RIDX(dim-1-i,j+9, dim)] = src[RIDX(i,j+9,dim)];
dst[RIDX(dim-1-i,j+10, dim)] = src[RIDX(i,j+10,dim)];
dst[RIDX(dim-1-i,j+11, dim)] = src[RIDX(i,j+11,dim)];
dst[RIDX(dim-1-i,j+12, dim)] = src[RIDX(i,j+12,dim)];
dst[RIDX(dim-1-i,j+13, dim)] = src[RIDX(i,j+13,dim)];
dst[RIDX(dim-1-i,j+14, dim)] = src[RIDX(i,j+14,dim)];
dst[RIDX(dim-1-i,j+15, dim)] = src[RIDX(i,j+15,dim)];
最佳答案
这是一个快速的老式 memcpy 优化。这通常非常有效。应该不需要展开。
来自 RIDX:
#define RIDX(i,j,n) ((i)*(n)+(j))
我们知道递增“j”组件转化为简单的指针递增。
struct pixel_t* s = src[RIDX(0, 0, dim)];
struct pixel_t* d = dst[RIDX[dim - 1, 0, dim];
for (int i = 0; i < dim; ++i, d -= (2 * dim))
{
for (int j = 0; j < dim; ++j, ++s, ++d)
{
//dst[RIDX(dim-1-i, j, dim)] = src[RIDX(i, j, dim)];
*d = *s;
// you could do it the hard way and start loop unrolling from here
}
}
在上面代码的内部循环中,++s,++d
提示可以进行 memcpy 优化。请注意,只有当我们正在复制的类型可以安全移动时,才可能进行 memcpy 优化。大多数类型是。但这是必须考虑的事情。使用 memcpy 确实稍微改变了 c++ 的严格规则,但 memcpy 很快。
然后循环变成:
struct pixel_t* s = src[RIDX(0, 0, dim)];
struct pixel_t* d = dst[RIDX[dim - 1, 0, dim];
for (int i = 0; i < dim; ++i, d -= dim, s += dim)
{
memcpy(d, s, dim * sizeof(pixel_t));
// or...
std::copy(s, s + dim, d); // which is 'safer' but could be slower...
}
在大多数现代 STL 实现中,std::copy 在大多数情况下将转换为 memcpy。 memcpy 使用书中的所有技巧来加快复制速度 - 循环展开、缓存前瞻等...
关于c++ - 通过循环展开和阻塞进行优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45226742/