代码优化,C代码无响应缓存阻塞

时间:2014-03-25 22:52:19

标签: c performance caching optimization processor

我正在一个让我们优化C代码的类中的项目。但是,我们运行代码的服务器似乎不能很好地响应通常的优化技术或者至少是我们已经教过的那些技术。该作业建议使用代码动作,循环展开和阻止。 以下是一些结构定义:

#ifndef _DEFS_H_
#define _DEFS_H_

#include <stdlib.h>

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

typedef struct {
  char *team;
  char *name1, *email1;
  char *name2, *email2;
} team_t;

extern team_t team;

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

typedef void (*lab_test_func) (int, pixel*, pixel*);

void smooth(int, pixel *, pixel *);
void rotate(int, pixel *, pixel *);

void register_rotate_functions(void);
void register_smooth_functions(void);
void add_smooth_function(lab_test_func, char*);
void add_rotate_function(lab_test_func, char*);

#endif /* _DEFS_H_ */

这是我正在处理的功能,它将图像旋转90度:

char naive_rotate_descr[] = "naive_rotate: Naive baseline implementation";
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)];
}

这是基线效率低下的实施。

char rotate_descr[] = "rotate: Current working version";
void rotate(int dim, pixel *src, pixel *dst) 
{
    int i, j;
    int ii, jj;
    int dim_min_one = dim - 1;

    for (i = 0; i < dim; i+=8){
        for (j = 0; j < dim; j+=8){
            for(ii = 0; ii < 8; ii++){
                for(jj = 0; jj < 8; jj+=8){
                    dst[RIDX(dim_min_one-(jj+j), (i+ii), dim)] = src[RIDX((i+ii), (j+jj), dim)];
                    dst[RIDX(dim_min_one-(jj+j+1), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+1), dim)];
                    dst[RIDX(dim_min_one-(jj+j+2), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+2), dim)];
                    dst[RIDX(dim_min_one-(jj+j+3), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+3), dim)];
                    dst[RIDX(dim_min_one-(jj+j+4), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+4), dim)];
                    dst[RIDX(dim_min_one-(jj+j+5), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+5), dim)];
                    dst[RIDX(dim_min_one-(jj+j+6), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+6), dim)];
                    dst[RIDX(dim_min_one-(jj+j+7), (i+ii), dim)] = src[RIDX((i+ii), (j+jj+7), dim)];

                }
            }
        }
    }
}

这是阻止和展开的组合。

char rotate1_descr[] = "rotate1: Simple 16 blocking";
void rotate1(int dim, pixel *src, pixel *dst) 
{
    int i, j;
    int ii, jj;
    int dim_min_one = dim - 1;

    for (i = 0; i < dim; i+=16){
        for (j = 0; j < dim; j+=16){
            for(ii = 0; ii < 16; ii++){
                for(jj = 0; jj < 16; jj++){
                    dst[RIDX(dim_min_one-(jj+j), (i+ii), dim)] = src[RIDX((i+ii), (j+jj), dim)];
                }
            }
        }
    }
}

这只是阻止。 现在,正在测试代码的服务器上有24个Intel(R)Xeon(R)X5660 @ 2.80GHz CPU。对于阻塞和展开循环,测试代码的速度提高了1.2,对于简单的阻塞,速度提高了1.4。

在我自己的计算机上,这是一台Core i7 2.7GHz,另一台学校服务器是24英特尔®至强®处理器E5-2420,频率为1.9GHz,阻塞和展开以及阻塞的速度都是1.9。

同样在所有系统上,8对16块的大小似乎没有性能差异,但是,32会对性能造成损害。

现在其他ES-2420的缓存为15mb,而X5660的缓存为12mb,但我觉得这不足以使阻塞这么多的效果相形见绌,或者使展开效果降低很多。我无法在网上找到任何关于优化X5660的技术以及它能够很好地响应的技术。所以我的问题是处理器的不同之处在于对缓存阻塞的响应会产生如此大的差异,以及我可以从这种差异中拿走什么来编写能够在其上运行得更好的代码。教科书和讲座并没有真正给我提供解决这个问题的工具,因为他们建议的所有技术都不能与我们必须运行它的服务器配合使用。

1 个答案:

答案 0 :(得分:0)

如果您可以在每台计算机上安装oprofile,则可以测量缓存未命中率和其他有趣的参数,以确定每种计算机获得不同加速比的原因。