现在我被困描述如下书中的“计算机系统从程序员的角度来看”性能优化实验室:性能优化矩阵旋转
在N * N矩阵M,其中N是多如图32所示,旋转操作可被表示为: 移调:交换元件M(I,J)和M(J,I) 交换行:行i与行N-1-i的
阿例如用于交换矩阵旋转(为简单起见,N为3而不是32):
------- -------
|1|2|3| |3|6|9|
------- -------
|4|5|6| after rotate is |2|5|8|
------- -------
|7|8|9| |1|4|7|
------- -------
一个天真的实现是:
#define RIDX(i,j,n) ((i)*(n)+(j))
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)];
}
我想出了通过内环路UNROLL的想法。其结果是:
Code Version Speed Up
original 1x
unrolled by 2 1.33x
unrolled by 4 1.33x
unrolled by 8 1.55x
unrolled by 16 1.67x
unrolled by 32 1.61x
我也是从pastebin.com得到一个代码段似乎可以解决这个问题:
void rotate(int dim, pixel *src, pixel *dst)
{
int stride = 32;
int count = dim >> 5;
src += dim - 1;
int a1 = count;
do {
int a2 = dim;
do {
int a3 = stride;
do {
*dst++ = *src;
src += dim;
} while(--a3);
src -= dim * stride + 1;
dst += dim - stride;
} while(--a2);
src += dim * (stride + 1);
dst -= dim * dim - stride;
} while(--a1);
}
后仔细阅读代码,我觉得这个解决方案的主要思想是对待32行作为数据区,并分别执行旋转操作。加速这个版本是1.85倍,压倒所有的循环展开版本。
这里有几个问题:
在内环-UNROLL版本,为什么不增加减慢,如果展开因素增加,特别是展开系数从8更改为16,这不影响从4切换到8时是否一样?结果与CPU管道的深度有关系吗?如果答案是肯定的,增量的降低是否反映了管道长度?
优化数据区版本的可能原因是什么?看起来与原始的天真版本没有太大的本质区别。
编辑:
我的测试环境是英特尔迅驰双核架构和gcc的优化版本是4.4
任何意见,将不胜感激!
亲切的问候!
实际上,它也有助于思考为什么你这样做。数学优化从简化数学表达式开始。为什么需要此操作? – 2010-06-03 14:19:23
你说得对。但我认为,这个问题与系统架构的关系比数学简化更多。 – 2010-06-03 14:31:11