一、实验准备

下载并解压perflab-handout文件,修改kernels.c文件里面的term结构体内容,粘贴如以下截图

二、完成实验(粘贴如以下结果示例的自己的截图)

img

三、代码调试记录(粘贴如以下结果示例的自己的截图)

Rotato函数

根据要求文件的提示中的信息:dim为32的整数倍,根据此信息,进行2/4/8/16/32路循环展开

寻找出得分最高的分块

32:

image-20231018112324573

16:

image-20231018112337334

8:

image-20231018112356118

……

经过一轮测试当取16分块的时候得分最高

再在此基础上展开循环

第一次展开后发现得分还变少了,再次测试发现程序得分并不稳定

经过多次求取平均值后发现在展开外层循环后得分反而变少了故保留Rotato函数为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
plaintext
`void rotate(int dim, pixel *src, pixel *dst)

{

for (int i = 0; i < dim; i += 16){

for (int j = 0; j < dim; j += 16){

for (int k = i; k < i+16; k++){

for (int s = j; s < j+16; s++){

dst[RIDX(dim-1-s, k, dim)] = src[RIDX(k, s, dim)];

}

}

}

}

}

Smooth函数:

根据题目可知该函数的作用是取目标像素点周围的像素点求平均值是再将其替换目标像素点(边界点需要另做判断)

题目给出的方法是通过构建一个pixel_sum结构体并初始化,遍历目标像素点周围3x3的区域并通过assign_sum_to_pixel()计算出平均值返回到current_pixel中。

分析可知,该函数是通过在每次计算的时候使用

for(ii = max(i-1, 0); ii <= min(i+1, dim-1); ii++)

for(jj = max(j-1, 0); jj <= min(j+1, dim-1); jj++)

函数确保在运算中不会越界,很容易想到这个计算是冗杂的,因为非边界的像素点也需要进行这个运算

故提出解决思路:

取消这个冗杂的运算,分别计算边界点的值计算和非边界点的值

在最初设计此算法的时候思路是将边界点运用原始的算法,再对非边界点使用去掉min和max函数的算法,通过在查阅资料得到更优思路,将非边界点拆分为顶角和上下左右四个边,再分别计算,这样可以优化掉这两个函数:

对四角:

我们计算出四个顶点的值分别为:

1
2
3
4
5
6
7
8
plaintext
(0, 1, dim, dim+1)左上

(dim-1, dim-2, dim+dim-2, dim+dim-1)右上

(RIDX(dim-1, 0, dim), RIDX(dim-1, 1, dim), RIDX(dim-2, 0, dim), RIDX(dim-2, 1, dim))左下

(RIDX(dim-1, dim-1, dim), RIDX(dim-1, dim-2, dim), RIDX(dim-2, dim-2, dim), RIDX(dim-2, dim-1, dim));右下

构建函数将这四个点的值取平均值,再返还给顶点的属性:

1
2
3
4
5
6
7
8
9
10
plaintext
static void vertex(int vertex, int a, int b, int c, pixel *p, pixel *dst){

dst[vertex].red = (p[vertex].red+p[a].red+p[b].red+p[c].red)/4;

dst[vertex].green = (p[vertex].green+p[a].green+p[b].green+p[c].green)/4;

dst[vertex].blue = (p[vertex].blue+p[a].blue+p[b].blue+p[c].blue)/4;

}

对于四边:

以顶边为例:

目标的周围共计有六个点,分别为

1
2
plaintext
i,i-1,i+1,i+dim+1,i+dim-1,i+dim;

与a相加并对各属性求和,故可以写出算法为:

1
2
3
4
5
6
7
8
9
10
plaintext
static void top(int dim, int i, pixel *p, pixel *dst){

dst[i].red = (p[i].red+p[i+dim].red+p[i-1].red+p[i+1].red+p[i+dim-1].red+p[i+dim+1].red)/6;

dst[i].green = (p[i].green+p[i+dim].green+p[i-1].green+p[i+1].green+p[i+dim-1].green+p[i+dim+1].green)/6;

dst[i].blue = (p[i].blue+p[i+dim].blue+p[i-1].blue+p[i+1].blue+p[i+dim-1].blue+p[i+dim+1].blue)/6;

}

对里面的点:

目标点周围一共有九个点:

1
2
plaintext
i,i+1,i-1,i+dim+1,i+dim,i+dim-1,i-dim,i-dim-1,i-dim+1;

由此可写出算法:

1
2
3
4
5
6
7
8
9
10
plaintext
static void in(int dim, int i, pixel *p, pixel *dst){

dst[i].red = (p[i].red+p[i-1].red+p[i+1].red+p[i+dim-1].red+p[i+dim].red+p[i+dim+1].red+p[i-dim-1].red+p[i-dim].red+p[i-dim+1].red)/9;

dst[i].green = (p[i].green+p[i-1].green+p[i+1].green+p[i+dim-1].green+p[i+dim].green+p[i+dim+1].green+p[i-dim-1].green+p[i-dim].green+p[i-dim+1].green)/9;

dst[i].blue = (p[i].blue+p[i-1].blue+p[i+1].blue+p[i+dim-1].blue+p[i+dim].blue+p[i+dim+1].blue+p[i-dim-1].blue+p[i-dim].blue+p[i-dim+1].blue)/9;

}

Smooth函数中分别调用上述方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
plaintext
void smooth(int dim, pixel *src, pixel *dst)

{

````````

vertex(0, 1, dim, dim+1, src, dst);

vertex(dim-1, dim-2, dim+dim-2, dim+dim-1, src, dst);

vertex(RIDX(dim-1, 0, dim), RIDX(dim-1, 1, dim), RIDX(dim-2, 0, dim), RIDX(dim-2, 1, dim), src, dst);

vertex(RIDX(dim-1, dim-1, dim), RIDX(dim-1, dim-2, dim), RIDX(dim-2, dim-2, dim), RIDX(dim-2, dim-1, dim), src, dst);

````````

for(int i = 1; i <= dim-2; i++){

for(int j = 1; j <= dim-2; j++){

in(dim, i*dim+j, src, dst);

}

}

}



for(int j = 1; j <= dim-2; j++){

top(dim, j, src, dst);

bottom(dim, dim*dim-dim+j, src, dst);

right(dim, j*dim+dim-1, src, dst);

left(dim, j*dim, src, dst);

}