通过循环展开和阻止进行优化

时间:2017-07-20 23:33:35

标签: c++ optimization

我不确定如何优化这段代码以使其高效。到目前为止,我已经针对j展开了内部for循环16,并且它产生的平均CPE为1.4。我需要通过优化技术获得2.5左右的平均CPE。我已经阅读了有关此问题的其他问题,与代码中的问题相比,它们有点不同。代码的第一部分显示了我给出的内容,然后我尝试展开循环。给定代码将扫描源图像矩阵的行并复制到目标图像矩阵的翻转行。任何帮助将不胜感激!

RIDX Macro:

#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)];   

1 个答案:

答案 0 :(得分:1)

这是一个快速的老式memcpy优化。这通常是非常有效的。不应该需要展开。

来自RIDX:

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

我们知道增加&#39; j&#39;组件会转换为简单的指针增量。

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使用书中的所有技巧使复制更快 - 循环展开,缓存预览等...