perflab 课程设计

news2024/12/25 20:28:05

初始状态

rotate

版本I

因为本题步步都在寻址而寻址的目标每一步又不同,并且在一个地址的值一次就赋值完毕,不会对同一个地址进行二次寻址,所以我首先想的改进方向就是使得寻址更加快速,于是我使得寻址的地址更加连续。

int i, j, t,n;
    n = dim - 1;
    for (j = 0; j < dim; j++){
        t = (n-j)*dim;
        for (i = 0; i < dim; i++)
            dst[t+i] = src[RIDX(i, j, dim)];
    }

 

 

 

 版本II

为了降低CPE,可以降低cache miss,所以可以用块化即通过不断使用一些数据块,而不是完整地遍历一行和一列,来改进空间局部性。

int i,j,ki,kj;
   for (i = 0; i < dim; i+=8) 
    for (j = 0; j < dim; j+=8)
        for(ki=i; ki<i+8; ki++) 
            for(kj=j; kj<j+8; kj++) 
                    dst[RIDX(dim-1-kj, ki, dim)] = src[RIDX(ki, kj, dim)];

 

Rotate的Summary由5.0提高至7.9,Dim规模较小时CPE优化不明显,当Dim规模较大时CPE明显下降

版本III

将前两种方法结合

int i, j, a, b, t;
    int sdim = dim - 1;
    for (i = 0; i < dim; i += 8)
    {
        for (j = 0; j < dim; j += 8)
        {
            for (b = j; b < j + 8; b++)
            {
                t = (sdim - b)*dim; 
                for (a = i; a < i + 8; a++)
                {
                    dst[t+a] = src[RIDX(a, b, dim)];
                }
            }
        }
    }

 

 版本IV

考虑到程序过多次调用RIDX函数,故消除该函数的调用。此外,改善读写顺序。具体来说,先处理矩阵第一列的前32个元素,再处理第二列前32个元素,以此类推直到处理完毕矩阵的前32行,再以相同的方法继续处理余下的矩阵元素。

int i,j,k;
for (i = 0; i < dim; i+=32)
    for (j = 0; j < dim; j++)
        for(k=0; k<32; k++) {
        dst[(dim-1-j)*dim+i+k] = src[(i+k)*dim+j];
        }

最终版本

smooth

版本I

虽然不同位置的像素点需要取相邻的不同数目的像素点的平均值,但数目只有4、6、9。对于四个顶点,取相邻四个像素点的平均值;对于和顶点接壤的像素点,取相邻六个像素点的平均值;剩下的取相邻九个像素点的平均值。

	int i=1,j=0;
	//左上角
	dst[0].red=(src[0].red+src[1].red+src[dim].red+src[dim+1].red)/4;
	dst[0].green=(src[0].green+src[1].green+src[dim].green+src[dim+1].green)/4;
	dst[0].blue=(src[0].blue+src[1].blue+src[dim].blue+src[dim+1].blue)/4;
	//第一行其他非右上角顶点
	for(j=1; j<dim-1; j++) {
		dst[j].red=(src[j-1].red+src[j].red+src[j+1].red+src[dim+j-1].red+src[dim+j].red+src[dim+j+1].red)/6;
		dst[j].green=(src[j-1].green+src[j].green+src[j+1].green+src[dim+j-1].green+src[dim+j].green+src[dim+j+1].green)/6;
		dst[j].blue=(src[j-1].blue+src[j].blue+src[j+1].blue+src[dim+j-1].blue+src[dim+j].blue+src[dim+j+1].blue)/6;
	}
	//右上角顶点
	dst[j].red=(src[j].red+src[j-1].red+src[dim+j].red+src[dim+j-1].red)/4;
	dst[j].green=(src[j].green+src[j-1].green+src[dim+j].green+src[dim+j-1].green)/4;
	dst[j].blue=(src[j].blue+src[j-1].blue+src[dim+j].blue+src[dim+j-1].blue)/4;
	//1至dim-2行
	for(; i<dim-1; i++) {
		//每行第一个像素点
		dst[i*dim].red=(src[(i-1)*dim].red+src[(i-1)*dim+1].red+src[i*dim].red+src[i*dim+1].red+src[(i+1)*dim].red+src[(i+1)*dim+1].red)/6;
		dst[i*dim].green=(src[(i-1)*dim].green+src[(i-1)*dim+1].green+src[i*dim].green+src[i*dim+1].green+src[(i+1)*dim].green+src[(i+1)*dim+1].green)/6;
		dst[i*dim].blue=(src[(i-1)*dim].blue+src[(i-1)*dim+1].blue+src[i*dim].blue+src[i*dim+1].blue+src[(i+1)*dim].blue+src[(i+1)*dim+1].blue)/6;
		//每行第二个至第dim-1个像素点
		for(j=1; j<dim-1; j++) {
			dst[i*dim+j].red=(src[(i-1)*dim+j-1].red+src[(i-1)*dim+j].red+src[(i-1)*dim+j+1].red+src[i*dim+j-1].red+src[i*dim+j].red+src[i*dim+j+1].red+src[(i+1)*dim+j-1].red+src[(i+1)*dim+j].red+src[(i+1)*dim+j+1].red)/9;
			dst[i*dim+j].green=(src[(i-1)*dim+j-1].green+src[(i-1)*dim+j].green+src[(i-1)*dim+j+1].green+src[i*dim+j-1].green+src[i*dim+j].green+src[i*dim+j+1].green+src[(i+1)*dim+j-1].green+src[(i+1)*dim+j].green+src[(i+1)*dim+j+1].green)/9;
			dst[i*dim+j].blue=(src[(i-1)*dim+j-1].blue+src[(i-1)*dim+j].blue+src[(i-1)*dim+j+1].blue+src[i*dim+j-1].blue+src[i*dim+j].blue+src[i*dim+j+1].blue+src[(i+1)*dim+j-1].blue+src[(i+1)*dim+j].blue+src[(i+1)*dim+j+1].blue)/9;
		}
		//每行最后一个像素点
		dst[i*dim+j].red=(src[(i-1)*dim+j-1].red+src[(i-1)*dim+j].red+src[i*dim+j-1].red+src[i*dim+j].red+src[(i+1)*dim+j-1].red+src[(i+1)*dim+j].red)/6;
		dst[i*dim+j].green=(src[(i-1)*dim+j-1].green+src[(i-1)*dim+j].green+src[i*dim+j-1].green+src[i*dim+j].green+src[(i+1)*dim+j-1].green+src[(i+1)*dim+j].green)/6;
		dst[i*dim+j].blue=(src[(i-1)*dim+j-1].blue+src[(i-1)*dim+j].blue+src[i*dim+j-1].blue+src[i*dim+j].blue+src[(i+1)*dim+j-1].blue+src[(i+1)*dim+j].blue)/6;
	}
	//左下角
	dst[i*dim].red=(src[(i-1)*dim].red+src[(i-1)*dim+1].red+src[i*dim].red+src[i*dim+1].red)/4;
	dst[i*dim].green=(src[(i-1)*dim].green+src[(i-1)*dim+1].green+src[i*dim].green+src[i*dim+1].green)/4;
	dst[i*dim].blue=(src[(i-1)*dim].blue+src[(i-1)*dim+1].blue+src[i*dim].blue+src[i*dim+1].blue)/4;
	//最后一行非左下角、非右下角的像素点
	for(j=1; j<dim-1; j++) {
		dst[i*dim+j].red=(src[(i-1)*dim+j-1].red+src[(i-1)*dim+j].red+src[(i-1)*dim+j+1].red+src[i*dim+j-1].red+src[i*dim+j].red+src[i*dim+j+1].red)/6;
		dst[i*dim+j].green=(src[(i-1)*dim+j-1].green+src[(i-1)*dim+j].green+src[(i-1)*dim+j+1].green+src[i*dim+j-1].green+src[i*dim+j].green+src[i*dim+j+1].green)/6;
		dst[i*dim+j].blue=(src[(i-1)*dim+j-1].blue+src[(i-1)*dim+j].blue+src[(i-1)*dim+j+1].blue+src[i*dim+j-1].blue+src[i*dim+j].blue+src[i*dim+j+1].blue)/6;
	}
	//右下角像素点
	dst[i*dim+j].red=(src[(i-1)*dim+j-1].red+src[(i-1)*dim+j].red+src[i*dim+j-1].red+src[i*dim+j].red)/4;
	dst[i*dim+j].green=(src[(i-1)*dim+j-1].green+src[(i-1)*dim+j].green+src[i*dim+j-1].green+src[i*dim+j].green)/4;
	dst[i*dim+j].blue=(src[(i-1)*dim+j-1].blue+src[(i-1)*dim+j].blue+src[i*dim+j-1].blue+src[i*dim+j].blue)/4;	

版本II

由于上个版本程序运行过程中比较多的重复计算区域,基于动态规划的思想,将每一个像素点的计算转换为一个块(2x2或2x3或3x2或3x3)内的各个像素点取平均值,并将每一块纵向分开为2或3个纵向块,用动规数组记录每一列(2个或3个像素点)的RGB之和,其中相邻的两个纵向块之间的递推关系通式为:dp[i][j]=dp[i-1][j]-src[(i-1)*dim+j]+src[(i+2)*dim+j]

	int i,j;
	int r2[2][dim],g2[2][dim],b2[2][dim];
	int r3[dim][dim],g3[dim][dim],b3[dim][dim];
	for(j=0; j<dim; j++) {
		//第j列一开始的大小为2的子块
		r2[0][j]=src[j].red;
		g2[0][j]=src[j].green;
		b2[0][j]=src[j].blue;
		r2[0][j]+=src[dim+j].red;
		g2[0][j]+=src[dim+j].green;
		b2[0][j]+=src[dim+j].blue;
		//第j列一开始的大小为3的子块
		r3[0][j]=r2[0][j]+src[(dim<<1)+j].red;
		g3[0][j]=g2[0][j]+src[(dim<<1)+j].green;
		b3[0][j]=b2[0][j]+src[(dim<<1)+j].blue;
		//其他子块
		for(i=1; i<dim-2; i++) {
			r3[i][j]=r3[i-1][j]-src[(i-1)*dim+j].red+src[(i+2)*dim+j].red;
			g3[i][j]=g3[i-1][j]-src[(i-1)*dim+j].green+src[(i+2)*dim+j].green;
			b3[i][j]=b3[i-1][j]-src[(i-1)*dim+j].blue+src[(i+2)*dim+j].blue;
		}
		//最后一个长度为2的子块
		r2[1][j]=r3[dim-3][j]-src[(dim-3)*dim+j].red;
		g2[1][j]=g3[dim-3][j]-src[(dim-3)*dim+j].green;
		b2[1][j]=b3[dim-3][j]-src[(dim-3)*dim+j].blue;
	}
	//处理左上角顶点
	dst[0].red=(r2[0][0]+r2[0][1])/4;
	dst[0].green=(g2[0][0]+g2[0][1])/4;
	dst[0].blue=(b2[0][0]+b2[0][1])/4;
	//处理第一行其他非右上角顶点
	for(j=1; j<dim-1; j++) {
		dst[j].red=(r2[0][j-1]+r2[0][j]+r2[0][j+1])/6;
		dst[j].green=(g2[0][j-1]+g2[0][j]+g2[0][j+1])/6;
		dst[j].blue=(b2[0][j-1]+b2[0][j]+b2[0][j+1])/6;
	}
	//右上角顶点
	dst[j].red=(r2[0][j-1]+r2[0][j])/4;
	dst[j].green=(g2[0][j-1]+g2[0][j])/4;
	dst[j].blue=(b2[0][j-1]+b2[0][j])/4;
	//1至dim-2行
	for(i=1; i<dim-1; i++) {
		//每行的第一个像素点
		dst[i*dim].red=(r3[i-1][0]+r3[i-1][1])/6;
		dst[i*dim].green=(g3[i-1][0]+g3[i-1][1])/6;
		dst[i*dim].blue=(b3[i-1][0]+b3[i-1][1])/6;
		//每行第二个至第dim-1个像素点
		for(j=1; j<dim-1; j++) {
			dst[i*dim+j].red=(r3[i-1][j-1]+r3[i-1][j]+r3[i-1][j+1])/9;
			dst[i*dim+j].green=(g3[i-1][j-1]+g3[i-1][j]+g3[i-1][j+1])/9;
			dst[i*dim+j].blue=(b3[i-1][j-1]+b3[i-1][j]+b3[i-1][j+1])/9;
		}
		//每行最后一个像素点
		dst[i*dim+j].red=(r3[i-1][j-1]+r3[i-1][j])/6;
		dst[i*dim+j].green=(g3[i-1][j-1]+g3[i-1][j])/6;
		dst[i*dim+j].blue=(b3[i-1][j-1]+b3[i-1][j])/6;
	}
	//左下角像素点
	dst[i*dim].red=(r2[1][0]+r2[1][1])/4;
	dst[i*dim].green=(g2[1][0]+g2[1][1])/4;
	dst[i*dim].blue=(b2[1][0]+b2[1][1])/4;
	//最后一行非左下角、非右下角的像素点
	for(j=1; j<dim-1; j++) {
		dst[i*dim+j].red=(r2[1][j-1]+r2[1][j]+r2[1][j+1])/6;
		dst[i*dim+j].green=(g2[1][j-1]+g2[1][j]+g2[1][j+1])/6;
		dst[i*dim+j].blue=(b2[1][j-1]+b2[1][j]+b2[1][j+1])/6;	
	}
	//右下角像素点
	dst[i*dim+j].red=(r2[1][j-1]+r2[1][j])/4;
	dst[i*dim+j].green=(g2[1][j-1]+g2[1][j])/4;
	dst[i*dim+j].blue=(b2[1][j-1]+b2[1][j])/4;	

版本III

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【面试题】 javaScript 进阶之路 --- 《加深理解回调函数》

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 一. 函数 回调函数的基本概念我之前的文章虽然有些过&#xff0c;但是为了引入下文&#xff0c;在这里还是简单再提一嘴…

苹果电脑ntfs如何打开硬盘?mac能读取的硬盘格式

如今&#xff0c;使用Mac电脑的用户越来越多&#xff0c;但是不少用户却面临着一个问题&#xff0c;那就是Mac无法正常读写自己的NTFS格式的外置硬盘&#xff0c;硬盘上面保存着很多重要的文件数据&#xff0c;想要进行复制或者是编辑等&#xff0c;压根没有办法在Mac电脑上进行…

axios和SpringMVC数据交互(一维二维数组,JSON/form形式,@RequestBody/@RequestParam)

目录需求环境准备前端后端成功实现的案例以JSON形式发送double数组以JSON形式发送对象&#xff0c;对象中有数组以JSON形式发送对象&#xff0c;对象中有二维数组以x-www-form-urlencoded形式发送一维数组需求 前端或postman发送数组&#xff0c;后端controller做为入参接收 …

汽车专场 | 新能源汽车动力电池PACK CAE分析实例解读

一、PACK为什么需要CAE分析&#xff1f; PACK是新能源汽车最重要的组成部分&#xff0c;可称之为心脏&#xff0c;电池系统需要满足汽车运营条件下的苛刻力学环境的要求。按照传统研发方式&#xff0c;设计-样包-测试-优化-样包-测试&#xff0c;反复循环&#xff0c;这种传统…

学完高性能计算后的发展怎么样?

高性能计算行业是指从事高性能计算相关性质的生产、服务的单位或个体的组织结构体系的总称。深刻认知高性能计算行业定义&#xff0c;对预测并引导高性能计算行业前景&#xff0c;指导行业投资方向至关重要。 一、什么是高性能计算&#xff1f; 高性能计算指通常使用很多处理…

音视频学习(十四)——rtsp详解

概念 rtsp&#xff08;Real Time Streaming Protocol&#xff0c;RFC2326&#xff09;&#xff0c;实时流传输协议&#xff0c;是TCP/IP协议体系中的一个应用层协议。 该协议主要规定了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP体系结位于RTP和RTCP之上&#…

etsy账号被封的原因有哪些?

Etsy之所以让人又爱又恨&#xff0c;是因为它的流量大&#xff0c;但缺点是规则限制&#xff0c;尤其是对于中国卖家。根据各大社交媒体的留言和评论&#xff0c;大多数电商人最关心Etsy关店的问题。   为什么Etsy会被封号&#xff1f;首先&#xff0c;我们需要了解封号的原因…

高压放大器的输入和输出阻抗为啥是50欧的

选择高压放大器的时候&#xff0c;经常会看到有些高压放大器的输入和输出阻抗都是50欧&#xff0c;今天就来说说高压放大器和无处不在的50欧姆&#xff0c;来聊聊它们的关系。 电子测量仪器在使用的时候会出现电子信号幅度突然加倍或者减少一半的情况&#xff0c;原因是几乎所有…

用echarts实现柱状图

目录前言&#xff1a;什么是 Echarts 插件柱状图成品展示步骤&#xff1a;柱状图代码&#xff1a;前言&#xff1a; 大家都知道&#xff0c;一般情况下&#xff0c;想要使用前端设置一个 柱状图 需要使用 canvas 画布进行编写&#xff0c;不仅代码多&#xff0c;逻辑处理麻烦&…

搭建Nacos集群

nacos的默认端口是8848&#xff0c;但是他还占用了另外两个接口&#xff1a;9848、9849。因此&#xff0c;在单机配置集群时&#xff0c;不可使用三个连续的端口&#xff0c;否则会导致 gRPC端口冲突。 端口与主端口&#xff08;8848&#xff09;偏移量作用98481000客户端gRPC…

7.javase_数组1

一. 数组定义格式 格式1&#xff1a;数据类型[] 变量名; 范例&#xff1a;int[] arr; 格式2&#xff1a;数据类型 变量名[]; 范例&#xff1a; int arr[];二. 数组初始化方式 1.1静态初始化&#xff1a;【初始化时指定每个数组元素的初始值&#xff0c;由系统决定数组长度】格…

ARFoundation系列讲解 - 89 适配华为机型

一、简介 使用 ARCore 开发安卓应用的时候,由于谷歌的制裁和鸿蒙系统的不兼容,导致华为大部分机型无法使用,而国内使用华为设备的群体占比较大的比例所以兼容华为设备是一个绕不过的坎。这个章节我们将学习使用 HuaweiAREngine 结合 ARFoundation 兼容使用来解决这个问题。 …

职业教育数字化成行业发展新方向

2022年,职业教育正迎来新的风口。随着与普通教育同等重要的地位得到确认,职业教育将肩负起建设与我国经济结构转型需求相匹配的人才供给的重任,在社会服务业、战略新兴行业等各大领域中大放异彩。 一、职业教育是什么? 1、职业教育定义 联合国教科文组织认为职业教育(Vocat…

PID控制器的远程设定点功能及其应用

摘要&#xff1a;远程设定点功能是超高精度PID控制器的重要拓展功能之一&#xff0c;其在实际自动控制中有着广泛的应用。本文详细介绍了远程设定点的功能和操作设置过程&#xff0c;同时还介绍了远程设定点功能在跟踪控制、串级控制和比值控制中的具体应用。 原文阅读&#x…

争议不断的AI绘画,靠啥成为了顶流?

今年以来&#xff0c;AIGC迅速崛起。所谓AIGC&#xff0c;即AI-Generated Content&#xff0c;指的是利用人工智能来生成内容&#xff0c;被认为是继专业产出内容&#xff08;PGC&#xff09;、用户产出内容&#xff08;UGC&#xff09;后的新型内容创作方式。不久前掀起热议的…

品牌化、跨境电商、专注细分赛道,平台助力品牌快速出海

国内国外产品都面临着日趋激烈的竞争&#xff0c;卖家越来越意识品牌的效应的重要作用。在竞争激烈的大环境之下&#xff0c;卖家必须采取有效的产品品牌营销策略来提高自身产品的市场竞争力。品牌营销在一定程度上可以增强产品在激烈的市场竞争的影响力。同时&#xff0c;口碑…

【DL】Windiws10系统下安装CUDA和CUDNN实践教程

Windiws10系统下安装CUDA和CUDNN实践教程(手把手系列,不错过任何一个环节): 一、查看需要的CUDA版本 点击开始菜单栏右侧的放大镜,输入NVIDIA 然后点击NVIDIA Control Panel,进入NVIDIA控制面板 点击管理3D设置->系统信息 弹出以下界面框 点击组件,就可以看到驱动对…

工业CT检测技术及工业CT基本组成

工业CT基本组成 由重建CT图像的基本过程出发&#xff0c;我们可以想象一下组成一台工业CT设备的基本要求&#xff1a;它应该能够量 X射线穿透被检物体以后射线的强度&#xff0c;同时能够完成X射线机-探测器系统与被检测物体之间的扫描运动&#xff0c;从而获得重建CT图像所需的…

如何将u盘两个分区合并?u盘怎么合并一个区

U盘是我们日常工作中应用得很广泛的便携式存储设备&#xff0c;具有体积小、便携易带、容量大、随插随拔等优势。为了方便存储数据&#xff0c;不少的用户都会对U盘分区&#xff0c;那么&#xff0c;如何将u盘两个分区合并&#xff1f; 一、合并U盘分区的应用与说明 合并U盘分…

Java高效率复习-MySQL下篇

前言 本文章的语言描述会比上篇多一些 数据库的创建修改与删除 标识符命名规则 数据库名、表名不得超过30个字符&#xff0c;变量限制为29个必须只能包含A-Z&#xff0c;a-z&#xff0c;0-9&#xff0c;_等63个字符数据库名、表名、字段名等对象名中间不要包含空格同一个My…