Cache Lab:Part B(52.6/53分)【矩阵转置的分块算法】

目录

任务描述

32 × 32

baseline

try1:给对角线上的块再次细分块

try2:对角块依次错位

成功:对角块两两交换 

成功:其他方法

64 × 64 

baseline

对角线优化+普通块转置顺序调整(7.6/8分)

61 × 67

成功:bsize=16*16

测试


任务描述

要求在trans.c中编写一个转置函数,从而导致尽可能少的miss。缓存的参数是 (s = 5, E = 1, b = 5)。三种测试用例的矩阵大小分别为:
        • 32 × 32 (M = 32, N = 32)
        • 64 × 64 (M = 64, N = 64)
        • 61 × 67 (M = 61, N = 67)

规定:仅使用12个局部变量,不能使用递归,不能修改A数组(可任意修改B数组),不允许使用malloc。

提示:你的代码只需要针对这三种情况是正确的,并且你可以针对这三种情况进行专门优化。特别是,你的函数完全可以显式检查输入大小并实现针对每种情况优化的单独代码。

32 × 32

baseline

下图是32*32数组的分块情况,每一个小格代表一个block(由前提条件b=5,得出一个块是32字节,由于是int数组,所以一个block能存8个元素)

上面是16个大块。

转置时依次扫描大块1~16,将块内元素转置后放在数组B对应的位置。可以发现,除了对角块,其余都是没有冲突未命中的。

int i, j, k, q, tmp;
if (M == 32 && N == 32)
{for (k = 0; k < 4; k++){for (q = 0; q < 4; q++){for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 + j][k * 8 + i] = tmp;}}}}
}

 由于PartA我们已经实现了模拟器了,所以miss的值肯定是能手算出来的。我们先大概算一下。

对于图上未着色的12个大块,12*16=192;对于对角线上的4个大块(着色的),4*(10+4+4+4+4+4+4+3)=144;故大约是192+144=336。

测试程序算的是344,大差不差。但仍需优化。 修改思路就是对于对角线进行进一步优化。

try1:给对角线上的块再次细分块

本来一个大块是8*8的,对于对角线,再一分为四,变为4*4。

还是先来预算一下结果:12个大块跟baseline一样是192;对角线上8个4*4块:8*(6+4+4+3)=138;其余8个4*4块:8*8=64;总计192+138+64=392。

测试程序计的数也是392,这种方法更差了。

int i, j, k, q, i2, j2, k2, q2, tmp;
if (M == 32 && N == 32)
{for (k = 0; k < 4; k++){for (q = 0; q < 4; q++){if (k == q){for (k2 = 0; k2 < 2; k2++){for (q2 = 0; q2 < 2; q2++){for (i2 = 0; i2 < 4; i2++){for (j2 = 0; j2 < 4; j2++){tmp = A[k * 8 + k2 * 4 + i2][q * 8 + q2 * 4 + j2];B[q * 8 + q2 * 4 + j2][k * 8 + k2 * 4 + i2] = tmp;}}}}}else{for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 + j][k * 8 + i] = tmp;}}}}}
}

try2:对角块依次错位

具体来说,转置完的1号大块存在6号大块,6号存在11号,11号存在16号。16号进行普通转置。

int i, j, k, q, tmp;
if (M == 32 && N == 32)
{for (k = 0; k < 4; k++){for (q = 0; q < 4; q++){if (k == q && k != 3){for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 + 8 + j][k * 8 + 8 + i] = tmp;}}for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = B[k * 8 + i + 8][q * 8 + j + 8];B[k * 8 + i][q * 8 + j] = tmp;}}}else{for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 + j][k * 8 + i] = tmp;}}}}}
}

现象:变好,m=305(只差一点点) 

成功:对角块两两交换 

具体来说,A的1号转置完成后存到B的6号,A的6号转置完存到B的1号去。然后,B的1号和6号交换。11号和16号同理。

现象:m=276,成功。

int i, j, k, q, tmp;
if (M == 32 && N == 32)
{for (k = 0; k < 4; k++){for (q = 0; q < 4; q++){if (k == q && k % 2 == 0){for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 + 8 + j][k * 8 + 8 + i] = tmp;}}}else if (k == q && k % 2 == 1){for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 - 8 + j][k * 8 - 8 + i] = tmp;}}for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = B[k * 8 + i][q * 8 + j];B[k * 8 + i][q * 8 + j] = B[k * 8 - 8 + i][q * 8 - 8 + j];B[k * 8 - 8 + i][q * 8 - 8 + j] = tmp;}}}else{for (i = 0; i < 8; i++){for (j = 0; j < 8; j++){tmp = A[k * 8 + i][q * 8 + j];B[q * 8 + j][k * 8 + i] = tmp;}}}}}
}

成功:其他方法

以上思路是我独立想出的。看了其他人的解法,在此补充一下:

对角线处发生的较多conflict miss的原因是,A和B相同大块之间是占有相同索引位置的cache的。如果先把A的对角线上的大块原封不动的挪到对应位置的B大块,然后让B大块原地转置,原地转置是不存在conflict miss的。

问题就变成了怎么实现“把A的对角线上的大块原封不动的挪到对应位置的B大块”,因为同时访问AB的对应位置就会发生conflict miss。

其实示例程序的tmp变量是个提示。可以多来几个局部变量,当做一个临时数组。也就是将循环最内层完全展开。

这种方法的代码请见 https://zhuanlan.zhihu.com/p/410662053

64 × 64 

baseline

现象:m=1892(满分1300)

对角线优化+普通块转置顺序调整(7.6/8分)

对角线转置方法:

普通块:

	if (M == 64 && N == 64){//k q 将64*64棋盘分为64个8*8的小格for (k = 0; k < 8; k++){for (q = 0; q < 8; q++){//处理对角线if (k == q){int bias = 8;if (k % 2 == 1) bias = -8;for (i = 0; i < 4; i++)for (j = 0; j < 4; j++)B[k * 8 + bias + j][q * 8 + bias + i] = A[k * 8 + i][q * 8 + j];for (i = 0; i < 4; i++)for (j = 4; j < 8; j++)B[k * 8 + bias + j][q * 8 + bias + i] = A[k * 8 + i][q * 8 + j];for (i = 4; i < 8; i++)for (j = 4; j < 8; j++)B[q * 8 + bias + j][q * 8 + bias + i] = A[k * 8 + i][q * 8 + j];for (i = 4; i < 8; i++)for (j = 0; j < 4; j++)B[k * 8 + bias + j][q * 8 + bias + i] = A[k * 8 + i][q * 8 + j];}else{// 对于不在对角线上的12个8*8的普通格,每个格还是一分为四,每小格为4*4,按照1,2,4,3的顺序从A转置存到Bfor (i = 0; i < 4; i++)for (j = 0; j < 4; j++)B[q * 8 + j][k * 8 + i] = A[k * 8 + i][q * 8 + j];for (i = 0; i < 4; i++)for (j = 4; j < 8; j++)B[q * 8 + j][k * 8 + i] = A[k * 8 + i][q * 8 + j];for (i = 4; i < 8; i++)for (j = 4; j < 8; j++)B[q * 8 + j][k * 8 + i] = A[k * 8 + i][q * 8 + j];for (i = 4; i < 8; i++)for (j = 0; j < 4; j++)B[q * 8 + j][k * 8 + i] = A[k * 8 + i][q * 8 + j];}// 交换if (k == q && k % 2 == 1){for (i = 0; i < 4; i++)for (j = 0; j < 4; j++)swap(&B[k * 8 + i][q * 8 + j], &B[k * 8 - 8 + i][q * 8 - 8 + j]);for (i = 0; i < 4; i++)for (j = 4; j < 8; j++)swap(&B[k * 8 + i][q * 8 + j], &B[k * 8 - 8 + i][q * 8 - 8 + j]);for (i = 4; i < 8; i++)for (j = 0; j < 4; j++)swap(&B[k * 8 + i][q * 8 + j], &B[k * 8 - 8 + i][q * 8 - 8 + j]);for (i = 4; i < 8; i++)for (j = 4; j < 8; j++)swap(&B[k * 8 + i][q * 8 + j], &B[k * 8 - 8 + i][q * 8 - 8 + j]);}}}}

61 × 67

要求m<2000,比较宽松。

成功:bsize=16*16

    if (M == 61 && N == 67){int bsize_x = 16;int bsize_y = 16;for (k = 0; k <= 67/bsize_x; k++)for (q = 0; q <= 61/bsize_y; q++)for (i = 0; i < bsize_x && k*bsize_x+i<67; i++)for (j = 0; j < bsize_y && q*bsize_y+j < 61; j++)B[q * bsize_y  + j][k * bsize_x  + i] = A[k * bsize_x  + i][q * bsize_y  + j];}

测试

注意测试程序driver.py要用python2运行,python3是报错的 

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

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

相关文章

Vue3+vite搭建基础架构(3)--- 使用dayjs

Vue3vite搭建基础架构&#xff08;3&#xff09;--- 使用dayjs 说明官方文档vite.config.js别名配置安装dayjs安装命令 使用dayjs将dayjs封装为自己的日期工具类使用dataUtil.js日期工具类示例 说明 这里记录下自己在Vue3vite的项目使用dayjs的过程&#xff0c;不使用ts语法&a…

最新XC主题 支持六种主题样式 去除域名授权全解密源码 一款多样式主题

Typecho 最新XC主题 去除域名授权全解密源码 这是一款多样式主题&#xff0c;首页支持六种主题样式&#xff0c;支持Pjax优化访问速度&#xff0c;多种单页&#xff0c;如友链、说说等。评论支持表情&#xff0c;自定义编辑器&#xff0c;支持其他样式功能。该主题功能性挺高&…

SQL中的left join和right join及具体实例

LEFT JOIN&#xff08;或称为左连接&#xff09;是SQL中的一种连接类型&#xff0c;它用于从两个或多个表中基于共同的列将数据组合起来。在使用LEFT JOIN时&#xff0c;查询的结果集包含左表&#xff08;LEFT JOIN语句中指定的第一个表&#xff09;的所有记录&#xff0c;以及…

音视频数字化(音频数字化)

在音视频领域,人们始终追求无限还原现场效果,因此音频越逼真越好,视频越清晰越好。之所以我们需要将音视频信号由模拟转为数字,目的是在录制、存储、编辑、复制、回放等环节的不失真,尽量保持原有细节,不因以上操作,导致音画的质量下降。 为此,视频系统分辨率越来越高,…

【Java程序设计】【C00207】基于(JavaWeb+SSM)的宠物领养管理系统(论文+PPT)

基于&#xff08;JavaWebSSM&#xff09;的宠物领养管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的宠物领养系统 本系统分为前台系统、管理员、收养者和寄养者4个功能模块。 前台系统&#xff1a;游客打开系统…

k8s-HPA

前提条件 安装有**Metrics Server**,HPA的运行监控指标需要由Metrics Server 提供 文档&#xff1a;https://github.com/kubernetes-sigs/metrics-server?tabreadme-ov-file#readme 快速自动缩放&#xff0c;每15秒收集一次指标(可配置)。 资源效率&#xff0c;为集群中的每…

网络防御安全:2-6天笔记

第二章&#xff1a;防火墙 一、什么是防火墙 防火墙的主要职责在于&#xff1a;控制和防护。 防火墙可以根据安全策略来抓取流量之后做出对应的动作。 二、防火墙的发展 区域&#xff1a; Trust 区域&#xff0c;该区域内网络的受信任程度高&#xff0c;通常用来定义内部…

计算机中的缓存与内存

在现代计算机系统中&#xff0c;缓存和内存扮演着至关重要的角色&#xff0c;它们共同协作以实现高性能和高效率的数据处理。本文将深入探讨缓存和内存的概念、功能以及它们在计算机系统中的作用。 缓存与内存&#xff1a;概念与功能 1. 内存&#xff08;RAM&#xff09;&…

代码随想录算法训练营第三十二天| 738.单调递增的数字 ,968.监控二叉树

738.单调递增的数字 代码随想录 从后往前遍历 class Solution {public int monotoneIncreasingDigits(int n) {String s String.valueOf(n);char[] chars s.toCharArray();int start s.length();for (int i s.length() - 2; i > 0; i--) {if (chars[i] > chars[i 1…

数据库管理-第142期 DBA?DBA!(20240131)

数据库管理142期 2024-01-31 数据库管理-第142期 DBA&#xff1f;DBA&#xff01;&#xff08;20240131&#xff09;正文总结 数据库管理-第142期 DBA&#xff1f;DBA&#xff01;&#xff08;20240131&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09…

VSCode 设置代理

Open Visual Studio Code, click the settings icon in the lower left corner, and click Settings.

yii2 mongodb 操作

->where([<>,review,""]) 不等于空 $where [newstypeid>[$in>$categoryIdArr]]; 类似mysql in操作 &#xff08;$categoryIdArr是数组&#xff09; ->where([label>[$regex >赞美诗]]) 模糊搜索操作 $where [status>1,name>[$rege…

C++语法 内存区域 和 引用

代码区 存放函数体的二进制代码 由操作系统进行管理 全局区 存放全局变量和静态变量以及常量 存放全局变量 静态变量 常量&#xff08;字符串常量 全局const常量&#xff09; 栈区 由编译器自动分配释放&#xff0c;存放函数的参数值&#xff0c;局部变量等。不要返回局部…

【论文笔记】Multi-Chain Reasoning:对多思维链进行元推理

目录 写在前面1. 摘要2. 相关知识3. MCR方法3.1 生成推理链3.2 基于推理链的推理 4. 实验4.1 实验设置4.2 实验结果 5. 提及文献 写在前面 文章标题&#xff1a;Answering Questions by Meta-Reasoning over Multiple Chains of Thought论文链接&#xff1a;【1】代码链接&…

【yarn】 kill 一个spark任务

要关闭一个正在运行的Spark任务&#xff0c;你可以使用以下命令来终止执行&#xff1a; yarn application -kill <application_id>将 <application_id> 替换为你要关闭的Spark应用程序的ID。这个ID通常以 application_ 开头&#xff0c;后面跟着一串数字。 请确保…

【数据分享】1929-2023年全球站点的逐日最高气温数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01; 之前我们分享过1929-2023年全球气象站…

LRU(Least Recently Used)

在 Vue.js 中&#xff0c;<keep-alive> 组件使用了 LRU&#xff08;Least Recently Used&#xff09;算法来缓存组件。LRU 算法是一种缓存淘汰策略&#xff0c;它根据最近使用的时间来确定哪些数据被保留在缓存中。 <keep-alive> 组件是 Vue.js 提供的一个抽象组件…

Git 怎么设置用户的权限

在团队协作的软件开发中&#xff0c;对于版本控制系统Git来说&#xff0c;确保代码与数据的安全性至关重要。为了实现这一目标&#xff0c;Git提供了灵活且可定制的用户权限管理机制。下面将简单的探讨一下Git如何设置用户的权限&#xff0c;以及如何保护代码和数据。 用户身份…

Nginx 多项目部署,vue刷新404 解决方案

网上找的资料大多都解决不了&#xff0c;废话不多说直接告诉你解决方法。 环境是 TP6 VUE前端官网 VUE 后台管理 部署 两个项目 刷新 404 解决方案 Nginx 配置 直接贴图 如果解决了&#xff0c;给我顶起来&#xff0c;让更多人 快速的解决。

Elasticsearch的使用场景深入详解

Elasticsearch的使用场景深入详解 在当今数据驱动的时代&#xff0c;随着数据量的爆炸式增长&#xff0c;对于快速、高效的数据检索和分析的需求越来越迫切。Elasticsearch作为一种分布式搜索和分析引擎&#xff0c;以其强大的全文搜索、实时分析功能和易用性&#xff0c;广泛…