lab4 Cache Geometries 深入理解计算机系统——高速缓存
这个实验主要是将高速缓存命中的一点东西,意在告诉我们平常多注意这方面的东西。
不懂java的,所以只管C的部分。
You will do this several times, making small modifications to see what differences they make—how the choice of language affects performance and how effective the compiler can be at optimizing your code when you:
- interchange the order of the
i
andj
loops - uncomment the commented line
- change the size of the array being copied from 2048 x 2048 to 4096 x 4096
#include <stdio.h> int src[2048][2048];
int dst[2048][2048]; /* Copies the contents of one 2048-by-2048 array (src) into another (dst). */
int main(int argc, char* argv[])
{
// declare all variables before the code (conform to an older C standard...)
int rep;
int i, j; for ( rep = 0; rep < 10; rep++ )
{
for ( i= 0; i < 2048;i++ )
{
for ( j= 0; j< 2048; j++ )
{
//src[i][j] = i * rep;
dst[i][j] = src[i][j];
}
}
} return 0;
}
要做的就是测试三种不同情况下的程序运行时间:
不优化 | O2优化 | |
原始程序 | 0.163 | 0.167 |
调换i,j顺序 | 1.332 | 1.305 |
加上src数组赋值 | 1.814 | 1.815 |
改变数组大小为4096 | 8.424 | 8.487 |
上诉结果都是在保持上一个改变的基础上得出的结果,也就是加上src数组赋值这一步骤时,i和j的顺序还是调换的。
- What are the source code differences among the two Java implementations?
由于不懂java,所以只能编译一下C的程序,对java的就暂时不管了。
2.Pick a single pair of results that most surprised you. What is it about the results that surprised
you? (That is, from the 32 pairs of measurement results, pick one pair whose relationship is least
like what you would have guessed.)
最大的震惊就是gcc的-O2优化什么用也没有啊,有时候甚至是反而比不优化的都要来的慢啊。真是……(看看当i,j调换的时候-o2和-o1的区别)
3.[Optional extra credit] None
of these programs appear to actually do anything, so one is tempted to optimize them by simply eliminating all code (resulting in an empty main()
).
Is that a correct optimization? Related to that, try compiling this C program, with and without optimization, and then time running it:
#include <stdio.h> #define SIZE 1000000 int main() {
int i, j, k;
int sum = 1; for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
for (k = 0; k < SIZE; k++) {
sum = -sum;
}
}
} printf("hello, world\n"); return 0;
}
这个问题说main函数的参数会对程序产生速度上的影响,这个就一个栈的问题,会有什么影响?个人认为没有什么影响吧。
还有 这个程序确定个人PC跑的完?出这个题的耍人的吧。估计是要让计算机冬天煮鸡蛋,多散散热的……
Part II: Inferring Mystery Cache Geometries
Your job is to fill in the function stubs in cache-test-skel.c
which,
when linked with one of these cache object files, will determine and then output the cache size, associativity, and block size. Some of the provided object files are named with this information (e.g. cache_64c_2a_16b.o
is
a 64 KB capacity, 2-way set-associative cache with 16B blocks)
程序如下:
#ifndef __MYSTERY_CACHE_H
#define __MYSTERY_CACHE_H typedef unsigned long long addr_t;
typedef unsigned char bool_t;
#define TRUE 1
#define FALSE 0 /** Initializes the cache. This function must be called so that the
cache can initialize its data structures, though the mystery
caches will ignore the provided arguments (as their parameters are
hard-coded). */
void cache_init(int size, int block_size); /** Lookup an address in the cache. Returns TRUE if the access hits,
FALSE if it misses. */
bool_t access_cache(addr_t address); /** Clears all words in the cache (and the victim buffer, if
present). Useful for helping you reason about the cache
transitions, by starting from a known state. */
void flush_cache(void); #endif
#include <stdlib.h>
#include <stdio.h> #include "mystery-cache.h" Returns the size (in B) of each block in the cache.
*/
int get_block_size(void) {
<span style="white-space:pre"> </span>int count=0;
<span style="white-space:pre"> </span>flush_cache();
<span style="white-space:pre"> </span>access_cache(0);
<span style="white-space:pre"> </span>while(access_cache(count))
<span style="white-space:pre"> </span>count++;
<span style="white-space:pre"> </span>return count;
} /*
Returns the size (in B) of the cache.
*/
int get_cache_size(int block_size) {
unsigned long long count=0;
unsigned int i=0;
while(1)
{
count=count+block_size;
flush_cache();
for(i=0;i<count;i=i+block_size)
{
access_cache(i);
}
if(!access_cache(0))
return count-block_size;
}
} /*
Returns the associativity of the cache.
*/
int get_cache_assoc(int cache_size) {
/* YOUR CODE GOES HERE */
int assoc=0;
int i;
while(1)
{
assoc++;
for(i=0;i<=assoc;i++)
access_cache(i*cache_size);
if(!access_cache(0))
return assoc;
}
} int main(void) {
int size;
int assoc;
int block_size; cache_init(0,0); block_size=get_block_size();
size=get_cache_size(block_size);
assoc=get_cache_assoc(size);
printf("Cache block size: %d bytes\n", block_size);
printf("Cache size: %d bytes\n", size);
printf("Cache associativity: %d\n", assoc); return EXIT_SUCCESS;
}
这道题主要让你用mystery-cache.h头文件里面的三个函数,来对4个高速缓存的的模拟文件进行分析,得到高速缓存的块大小,缓存总容量和高速缓存行的大小。
这里主要注意这个函数:
/** Lookup an address in the cache. Returns TRUE if the access hits,
FALSE if it misses. */
bool_t access_cache(addr_t address);
这个函数是有两个作用,1.把address放入高速缓存。2.检查高速缓存中有没有address这个地址。
这个函数比较坑,主要是它会把在高速缓存中的地址也压入高速缓存。
解释下,就是当高速缓存的块是4的时候,地址0,1,2,3四个地址是一起的,是在一个高速缓存行里面的。假设高速换存一组有4行,当对一个空的高速缓存进行操作时(执行flush_cache()函数),执行access_cache(0),access_cache(1),access_cache(2),access_cache(3)时,此时高速缓存第0组的缓存行是:0,1,2,3
理论上来说,应该进行了那个操作之后,缓存行应该只有0,因为1,2,3三个数据都可以在0这个缓存行中访问到,他们是在一个块里面的。这感觉是这个高速缓存模拟文件的一个不好的地方。对后面那三个函数编写,很麻烦啊。
求解缓存块大小:
思路:假设块的大小为N,首先先把0放入缓存区中,则执行access_cache(0)~access_cache(N-1)的过程中,这些地址全都会缓存在在第0组中,由于有先把0放入了缓存区,所以在查询asscess_cache(add)的过程中(add>0&&add<N),会一直返回1.而N由于和前面的数字不是在一个块里面的,N会被缓存在第1组,而第一组本来是空的,读取N会有冷不命中,所以查询时会返回0,由此可以得出块的大小N。
int get_block_size(void) {
int count=0;
flush_cache();
access_cache(0);
while(access_cache(count))
count++;
return count;
}
求解缓存区的总容量:
思路很简单,就是往缓存区里面一直存入地址,根据缓存区相关知识,当缓存区存满时,会删除一个缓存区中的地址,以放入新的地址。所以程序的编写按照这个思路,一直往缓存区中存入数据的过程中,一直查询0是否在缓存区中,如果0不在,则缓存区因为缓存区容量已满,把0删除。但是因为asscess_cache(add)函数的特性,所以每次asscess_cache(0)的时候会把0写入,所以要用一个比较麻烦的方法。就是每次查询完0之后,要清空缓存区,并且重新写入地址。
int get_cache_size(int block_size) {
unsigned long long count=0;
unsigned int i=0;
while(1)
{
count=count+block_size;
flush_cache();
for(i=0;i<count;i=i+block_size)
{
access_cache(i);
}
if(!access_cache(0))
return count-block_size;
}
}
求解缓存区高速缓存行的大小:
求解思路:由于已经求接触缓存区的总容量cache_size,所以可以知道地址cache_size,2*cache_size,3*cache_size……n*cache_size和0总是在同一个缓存组里面的。利用这个性质,可以比较容易的得到assoc的值。
首先,存入0的地址,然后依次存入cache_size,2*cache_size,3*cache_size……,在存入的过程中,查询0是否在缓存区中,如果0不在缓存区中,则第0组空间已满,这是最后的n*cache_size中的n,就是assoc的大小。这里需要注意的就是access_cache()函数的特性。和上面一个函数的过程一样,查询过了,就要清空缓存区,重新写入,重新查询。
int get_cache_assoc(int cache_size) {
/* YOUR CODE GOES HERE */
int assoc=0;
int i;
while(1)
{
assoc++;
for(i=0;i<=assoc;i++)
access_cache(i*cache_size);
if(!access_cache(0))
return assoc;
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
lab4 Cache Geometries 深入理解计算机系统——高速缓存的更多相关文章
- 《深入理解计算机系统》(CSAPP)读书笔记 —— 第一章 计算机系统漫游
本章通过跟踪hello程序的生命周期来开始对计算机系统进行学习.一个源程序从它被程序员创建开始,到在系统上运行,输出简单的消息,然后终止.我们将沿着这个程序的生命周期,简要地介绍一些逐步出现的关键概念 ...
- 深入理解计算机系统家庭作业汇总 20135301&&20135328
深入理解计算机系统家庭作业 深入理解计算机系统第二章家庭作业 题目2.64 题目要求 判断二进制数偶数位是否有任意一位位为1,有的话返回1,否则返回0 解题过程 int any_even_one(un ...
- 《深入理解计算机系统》【PDF】下载
<深入理解计算机系统>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382303 内容提要 本书主要介绍了计算机系统的基本概念,包 ...
- 4.2《深入理解计算机系统》笔记(五)并发、多进程和多线程【Final】
该书中第11章是写web服务器的搭建,无奈对web还比较陌生.还没有搞明白. 这些所谓的并发,其实都是操作系统做的事情,比如,多进程是操作系统fork函数实现的.I/O多路复用需要内核挂起进程.多线程 ...
- 深入理解计算机系统_3e 第九章家庭作业 CS:APP3e chapter 9 homework
9.11 A. 00001001 111100 B. +----------------------------+ | Parameter Value | +--------------------- ...
- 《深入理解计算机系统V2》学习指导
<深入理解计算机系统V2>学习指导 目录 图书简况 学习指导 第一章 计算机系统漫游 第二章 信息的表示和处理 第三章 程序的机器级表示 第四章 处理器体系结构 第五章 优化程序性能 第六 ...
- 深入理解计算机系统(4.1)---X86的孪生兄弟,Y86指令体系结构
引言 各位猿友们好,计算机系统系列很久没更新了,实在是抱歉之极.新的一年,为了给计算机系统系列添加一些新的元素,LZ将其更改为书的原名<深入理解计算机系统>.这本书非常厚,而且难度较高,L ...
- 深入理解计算机系统(1.2)---hello world的程序是如何运行的
在写本章的内容之前,LZ先做个小广告.其实也不算是什么广告,就是LZ为了和各位猿友交流方便,另外也确实有个别猿友留言或者在博客里发短消息给LZ要联系方式.因此LZ斗胆建立了一个有关<深入理解计算 ...
- 《深入理解计算机系统》 Chapter 7 读书笔记
<深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...
随机推荐
- rem布局
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- IEnumerable和IEnumerator 详解 【转】
初学C#的时候,老是被IEnumerable.IEnumerator.ICollection等这样的接口弄的糊里糊涂,我觉得有必要切底的弄清楚IEnumerable和IEnumerator的本质. 下 ...
- HDU 1010Tempter of the Bone(奇偶剪枝回溯dfs)
Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- LCD与ARM,具体
一 实验内容简要描写叙述 1.实验目的 学会驱动程序的编写方法,配置S3C2410的LCD驱动,以及在LCD屏上显示包含bmp和jpeg两种格式的图片 2.实验内容 (1)分析S3c2410实验箱 ...
- DevExpress学习1
为了程序的美观设计,决定用dev控件. 第一步,去官网下载了试用30天的安装包,官网地址:https://www.devexpress.com/,安装完成. 第二步,开始程序下找到DevExpress ...
- 共享器 TS ERROR WINDOWS-FAILED 错误解决方法
问题:TS ERROR WINDOWS-FAILED 原因:微软操作系统自动更新补丁(KB956572)与终端机软件有冲突. 解决方法: .打开“开始菜单”: .打开“控制面板”: .打开“添加/删 ...
- oracle ORA-00913: 值过多
--oracle中查看表是否被锁 查看表是否被锁 SELECT /*+ rule*/ a.sid, b.owner, object_name, object_type FROM v$loc ...
- Linux程序设计 读笔2 Shell脚本
第二章 Shell程序设计 四.管道和重定向 1 重定向输出 ls -l > lsoutput.txt ps >> lsoutput.txt >>表示附加到一个文件中 文 ...
- 内存管理之二——Cocos2d-x学习历程(六)
1.工厂方法 工厂方法是程序设计中一个经典的设计模式,指的是基类中只定义创建对象的接口,将实际的实现推迟到子类中. CCObject* factoryMethod() { CCObject* ret ...
- prob5 of 140
#include<stdio.h>int main(){ int n,i=1,j=1; double s=1,s1=0;; //scanf("%d",&n); ...