# lab4 Cache Geometries 深入理解计算机系统——高速缓存

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 and j 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

1. What are the source code differences among the two Java implementations?

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.)

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;
}

## 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 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. */

/** 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;
}


/** Lookup an address in the cache. Returns TRUE if the access hits,
FALSE if it misses. */
bool_t access_cache(addr_t address);

int get_block_size(void) {
int count=0;
flush_cache();
access_cache(0);
while(access_cache(count))
count++;
return count;
}

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;
}
}

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;
}
}

10-10 8973

05-17 7839
07-18 2万+
11-14 6079
03-25
01-07