CSAPP Lab4- PerfLab

这篇具有很好参考价值的文章主要介绍了CSAPP Lab4- PerfLab。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代码优化 

CSAPP Lab4- PerfLab

CSAPP Lab4- PerfLab

CSAPP Lab4- PerfLab

CSAPP Lab4- PerfLab

typedef struct { 
    unsigned short red; /* R value */ 
    unsigned short green; /* G value */ 
    unsigned short blue; /* B value */ 
} pixel

图像用一维数组表示,第(i,j)个像素表示为I[RIDX(i,j,n)],n为图像的维数

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

目标:使用代码优化技术使旋转操作运行的更快

平滑操作

void naive_smooth(int dim, pixel *src, pixel *dst) { 
    int i, j; 
    for(i=0; i < dim; i++) 
    for(j=0; j < dim; j++) 
        dst[RIDX(i,j,dim)] = avg(dim, i, j, src); /* Smooth the (i,j)thpixel */ 
    return; 
} 

目标:使用代码优化技术使平滑操作运行的更快

性能评判方法

CPE or Cycles per Element

如果一个函数使用C个周期去执行一个大小为N*N的图像,那么CPE=C/(N*N),因此CPE越小越好

如何定义函数

在kernel.c中有rotate的实现方法,我们需要添加自己的rotate实现,函数名自己命名,然后通过

void register_rotate_functions() { 
    add_rotate_function(&rotate, rotate_descr); 
    add_rotate_function(&my_rotate,my_rotate_descr);
} 

把自己实现的函数注册进去

编码规则

只能用ANSI C,不能用嵌入式汇编

不能修改测量时间的机制(CPE)

只能修改kernels.c,可以定义宏,全局变量,函数


旋转

在旋转过程中,源图像(src)的每一列被逆序复制到目标图像(dst)的每一行。因此,源图像的左上角(src[0])被复制到目标图像的左下角(dst[0]),源图像的第二列的顶部(src[dim])被复制到目标图像的第二行的底部(dst[1]),以此类推。

这是通过以下步骤完成的:

  1. 初始时,dst指针被移动到目标图像的底部(dst += (dim * dim - dim))。

  2. 然后,开始两层循环。外层循环按32像素的步长遍历源图像的列(i);内层循环遍历每列的所有像素(j)。

  3. 在内层循环中,源图像的每一列(src[i])被逆序复制到目标图像的对应行(dst[j])。这是通过将src的当前元素复制到dst的当前元素,然后递增src指针(src++)并递减dst指针(dst -= dim)实现的。这样,dst指针总是指向目标图像的上一行,而src指针总是指向源图像的下一列。

  4. 在外层循环的每次迭代结束时,src和dst指针都被调整,以便在下一次迭代中处理源图像的下一组32列和目标图像的下一组32行。

因此,这段代码实现了将源图像旋转90度并复制到目标图像的功能。

/*
 * rotate - Your current working version of rotate
 * IMPORTANT: This is the version you will be graded on
 */
char rotate_descr[] = "rotate: Current working version";
void rotate(int dim, pixel *src, pixel *dst)
{
    // naive_rotate(dim, src, dst);
    int i, j;
    dst += (dim * dim - dim); // dst指针被移动到目标图像的底部
    for (i = 0; i < dim; i += 32)
    {
        for (j = 0; j < dim; j++)
        {
            dst[0] = src[0];
            dst[1] = src[dim];
            dst[2] = src[2 * dim];
            dst[3] = src[3 * dim];
            dst[4] = src[4 * dim];
            dst[5] = src[5 * dim];
            dst[6] = src[6 * dim];
            dst[7] = src[7 * dim];
            dst[8] = src[8 * dim];
            dst[9] = src[9 * dim];
            dst[10] = src[10 * dim];
            dst[11] = src[11 * dim];
            dst[12] = src[12 * dim];
            dst[13] = src[13 * dim];
            dst[14] = src[14 * dim];
            dst[15] = src[15 * dim];
            dst[16] = src[16 * dim];
            dst[17] = src[17 * dim];
            dst[18] = src[18 * dim];
            dst[19] = src[19 * dim];
            dst[20] = src[20 * dim];
            dst[21] = src[21 * dim];
            dst[22] = src[22 * dim];
            dst[23] = src[23 * dim];
            dst[24] = src[24 * dim];
            dst[25] = src[25 * dim];
            dst[26] = src[26 * dim];
            dst[27] = src[27 * dim];
            dst[28] = src[28 * dim];
            dst[29] = src[29 * dim];
            dst[30] = src[30 * dim];
            dst[31] = src[31 * dim];
            src++;      // src指针指向源图像的下一列
            dst -= dim; // dst指针指向目标图像的上一行
        }
        // 源图像的下一组32列
        src += 31 * dim;
        // 目标图像的下一组32行
        dst += dim * dim + 32;
    }
}

平滑

smooth函数的目标是通过对每个像素及其邻近像素的平均值来“平滑”图像,因为它降低了像素与像素之间颜色的突变,使得图像的颜色变得更为均匀。其中涉及到处理图像边界(角落和边缘)的特殊情况,因为这些像素的邻近像素较少。对于图像的其他部分,smooth会计算每个像素及其8个邻居的平均值,并将该平均值分配给输出图像的相应像素。

/*
 * smooth - Your current working version of smooth.
 * IMPORTANT: This is the version you will be graded on
 */
char smooth_descr[] = "smooth: Current working version";
void smooth(int dim, pixel *src, pixel *dst)
{
    // naive_smooth(dim, src, dst);
    int i, j, myJ;

    // 处理四个角
    dst[0].red = (src[0].red + src[1].red + src[dim].red + src[dim + 1].red) >> 2;
    dst[0].blue = (src[0].blue + src[1].blue + src[dim].blue + src[dim + 1].blue) >> 2;
    dst[0].green = (src[0].green + src[1].green + src[dim].green + src[dim + 1].green) >> 2;

    i = dim * 2 - 1;
    dst[dim - 1].red = (src[dim - 2].red + src[dim - 1].red + src[i - 1].red + src[i].red) >> 2;
    dst[dim - 1].blue = (src[dim - 2].blue + src[dim - 1].blue + src[i - 1].blue + src[i].blue) >> 2;
    dst[dim - 1].green = (src[dim - 2].green + src[dim - 1].green + src[i - 1].green + src[i].green) >> 2;

    j = dim * (dim - 1);
    i = dim * (dim - 2);
    dst[j].red = (src[j].red + src[j + 1].red + src[i].red + src[i + 1].red) >> 2;
    dst[j].blue = (src[j].blue + src[j + 1].blue + src[i].blue + src[i + 1].blue) >> 2;
    dst[j].green = (src[j].green + src[j + 1].green + src[i].green + src[i + 1].green) >> 2;

    j = dim * dim - 1;
    i = dim * (dim - 1) - 1;
    dst[j].red = (src[j - 1].red + src[j].red + src[i - 1].red + src[i].red) >> 2;
    dst[j].blue = (src[j - 1].blue + src[j].blue + src[i - 1].blue + src[i].blue) >> 2;
    dst[j].green = (src[j - 1].green + src[j].green + src[i - 1].green + src[i].green) >> 2;

    // 处理四个边
    // 上
    i = dim - 1;
    for (j = 1; j < i; j++)
    {
        dst[j].red = (src[j].red + src[j - 1].red + src[j + 1].red + src[j + dim].red + src[j + 1 + dim].red + src[j - 1 + dim].red) / 6;
        dst[j].green = (src[j].green + src[j - 1].green + src[j + 1].green + src[j + dim].green + src[j + 1 + dim].green + src[j - 1 + dim].green) / 6;
        dst[j].blue = (src[j].blue + src[j - 1].blue + src[j + 1].blue + src[j + dim].blue + src[j + 1 + dim].blue + src[j - 1 + dim].blue) / 6;
    }

    // 下
    i = dim * dim - 1;
    for (j = i - dim + 2; j < i; j++)
    {
        dst[j].red = (src[j].red + src[j - 1].red + src[j + 1].red + src[j - dim].red + src[j + 1 - dim].red + src[j - 1 - dim].red) / 6;
        dst[j].green = (src[j].green + src[j - 1].green + src[j + 1].green + src[j - dim].green + src[j + 1 - dim].green + src[j - 1 - dim].green) / 6;
        dst[j].blue = (src[j].blue + src[j - 1].blue + src[j + 1].blue + src[j - dim].blue + src[j + 1 - dim].blue + src[j - 1 - dim].blue) / 6;
    }

    // 右
    for (j = dim + dim - 1; j < dim * dim - 1; j += dim)
    {
        dst[j].red = (src[j].red + src[j - 1].red + src[j - dim].red + src[j + dim].red + src[j - dim - 1].red + src[j - 1 + dim].red) / 6;
        dst[j].green = (src[j].green + src[j - 1].green + src[j - dim].green + src[j + dim].green + src[j - dim - 1].green + src[j - 1 + dim].green) / 6;
        dst[j].blue = (src[j].blue + src[j - 1].blue + src[j - dim].blue + src[j + dim].blue + src[j - dim - 1].blue + src[j - 1 + dim].blue) / 6;
    }

    // 左
    i = i - (dim - 1);
    for (j = dim; j < i; j += dim)
    {
        dst[j].red = (src[j].red + src[j - dim].red + src[j + 1].red + src[j + dim].red + src[j + 1 + dim].red + src[j - dim + 1].red) / 6;
        dst[j].green = (src[j].green + src[j - dim].green + src[j + 1].green + src[j + dim].green + src[j + 1 + dim].green + src[j - dim + 1].green) / 6;
        dst[j].blue = (src[j].blue + src[j - dim].blue + src[j + 1].blue + src[j + dim].blue + src[j + 1 + dim].blue + src[j - dim + 1].blue) / 6;
    }

    // 处理中间部分
    myJ = dim;  // 第二行的第一个元素

    for (i = 1; i < dim - 1; i++)
    {
        for (j = 1; j < dim - 1; j++)
        {
            myJ++;
            dst[myJ].red = (src[myJ - 1].red + src[myJ].red + src[myJ + 1].red + src[myJ - dim - 1].red + src[myJ - dim].red + src[myJ - dim + 1].red + src[myJ + dim - 1].red + src[myJ + dim].red + src[myJ + dim + 1].red) / 9;
            dst[myJ].green = (src[myJ - 1].green + src[myJ].green + src[myJ + 1].green + src[myJ - dim - 1].green + src[myJ - dim].green + src[myJ - dim + 1].green + src[myJ + dim - 1].green + src[myJ + dim].green + src[myJ + dim + 1].green) / 9;
            dst[myJ].blue = (src[myJ - 1].blue + src[myJ].blue + src[myJ + 1].blue + src[myJ - dim - 1].blue + src[myJ - dim].blue + src[myJ - dim + 1].blue + src[myJ + dim - 1].blue + src[myJ + dim].blue + src[myJ + dim + 1].blue) / 9;
        }

        // 跳过这一行的最后一个像素和下一行的第一个像素
        myJ += 2;
    }
}

运行时要将kernels.c文件中的以下三处修改为自己的信息

CSAPP Lab4- PerfLab

然后依次执行

make driver
./driver

 CSAPP Lab4- PerfLab文章来源地址https://www.toymoban.com/news/detail-458596.html

到了这里,关于CSAPP Lab4- PerfLab的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CSAPP lab1 Data Lab

    前言: 本系列文章用于记录开始学习csapp的过程,奈何感觉自己基础实在太渣渣,系统好好学习一下这本神书以及其对应的lab 这一张的lab是真的干,好几道题卡的我脑壳都卡秃噜了,好歹终于凭借着面向用例编程完成了这一张的lab 很多很多测试用例哦,再也不用担心绞尽脑

    2024年02月10日
    浏览(30)
  • 《计算机网络自顶向下》Wireshark实验 Lab4 TCP

    《计算机网络自顶向下》Wireshark Lab + 套接字编程作业 + 杂项实验室编程作业 全实验博客链接 各位好 啊 学计算机想要学好真的还是挺难的 说实话 科班学计算机如果想要花大量的时间去学 只能把平时的课程大部分时间不去上 如果班级管理严格或者说 各种因素让你不得不去上

    2023年04月09日
    浏览(58)
  • CSAPP的Lab学习——Archlab(Architecture Lab)

    一个本硕双非的小菜鸡,备战24年秋招。刚刚看完CSAPP,真是一本神书啊!遂尝试将它的Lab实现,并记录期间心酸历程。 代码下载 官方网站:CSAPP官方网站 这道题下载完了记得不是完事了,还有一句话需要执行 如果执行make clean; make出现了报错,如: 可参考这位大佬的解决方

    2024年02月09日
    浏览(81)
  • MIT6824——lab4(实现一个分片kv存储)的一些实现,问题,和思考

    和lab3A一样,shardctler也是一个服务,由客户端调用。这个服务建立在raft集群上, 保证容错。 shardctler也应该保证 线性一致性和重复请求的问题 ,因此也需要记录clientid和messageid。 shardctler保存了当前的分片信息,称为配置 Num:当前配置号 Shards:每一个分片对应的副本组id—

    2024年02月07日
    浏览(28)
  • CSAPP Shell Lab 实验报告

    前言:强烈建议先看完csapp第八章再做此实验,完整的tsh.c代码贴在文章末尾了 进程的概念、状态以及控制进程的几个函数(fork,waitpid,execve)。 信号的概念,会编写正确安全的信号处理程序。 shell的概念,理解shell程序是如何利用进程管理和信号去执行一个命令行语句。 sh

    2024年02月04日
    浏览(32)
  • Javaee课程lab4,学生信息管理系统(MVC(JSP+JavaBeans+Servlet)+ JDBC)

    实验目的: 1、熟悉MVC设计模式,掌握编程思路 2、综合运用JSP、Servlet、JavaBean、JDBC等技术实现MIS系统—学生信息管理系统(铁大) JDBC是Java Database Connectivity(Java数据库连接)的缩写,编程人员可以通过这个API接口连接到数据库,并使用结构化查询语言(SQL)完成对数据库的

    2024年02月09日
    浏览(36)
  • CSAPP cache lab - Optimizing Matrix Transpose

    矩阵转置是一种操作,它将矩阵的行和列互换位置,即将原始矩阵的行变为转置矩阵的列,将原始矩阵的列变为转置矩阵的行。转置操作可以通过改变矩阵的布局来方便地进行某些计算和分析。 假设有一个m×n的矩阵A,其转置矩阵为n×m的矩阵B。那么B的第i行第j列的元素就是

    2024年01月22日
    浏览(31)
  • Matlab | Lab4——用LU 分解法、 Jacobi 迭代、 Gauss-Seidel 迭代 解线性病态方程组(系数矩阵为Hilbert矩阵)

    考虑线性方程组Hx=b,其中H为n阶Hilbert矩阵,即 通过先给 定解 (例如取x的各个分量为1),再计算出右端向量b的办法给出一个精确解已知的问题. (1)分别编写Doolittle LU 分解法、 Jacobi 迭代、 Gauss-Seidel 迭代的一般程序; (2) 取阶数n=6,分别用 LU 分解法、 Jacobi 迭代、 Gauss-S

    2024年02月11日
    浏览(32)
  • 【Anaconda】jupyter notebook的升级版jupyter Lab4.0的安装配置,自学Python利器,你值得拥有!新工具你装了没?

    前几天,jupyter lab4.0已经发布,因为chatgpt的火爆,貌似都没太多人关注jupyter lab 新版本的发布这事了。 不过,如果你想自学Python,一定不要错过这个自学Python的利器。 我想每个Python程序员都会知道Jupyter Notebook 这个工具。 Jupyter Notebook 就像是一个神奇的“魔法记事本”,让你

    2024年02月12日
    浏览(56)
  • typedef函数代码段解释以及部分Windows下的系统函数

    在 C/C++ 中,typedef 用于创建类型别名,它可以让你为一个已有的数据类型定义一个新的名称,从而使代码更加清晰、易读,也可以简化类型的声明和使用。 这段代码用 typedef 定义了一个函数指针类型 LPSDOLInitialize ,该函数指针指向一个函数,该函数接受一个指向 SDOLAppInfo 结

    2024年02月12日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包