深入理解计算机系统(第二版) 家庭作业 第六章


6.23
我们可以认为,磁道沿半径方向是均匀分布的。假设半径为r的磁盘总的磁道是K,那么除掉内部的x*r(磁道数为x*K),剩下的磁道数为 (1-x)*K。
那么总容量为  2*pi*x*r*(1-x)*K,其中pi,r和K都是常数,那么只剩下x*(1-x)。
这个函数在x = 0.5的时候取最大。

6.24
T_seek = 3 ms
T_maxrotate = 60*1000/12000 ms = 5 ms
T_avgrotate = 0.5*T_maxrotate = 2.5 ms
T_transfer = T_maxrotate/500 = 0.01 ms
T = T_seek + T_avgrotate + T_transfer = 5.51 ms

6.25
3MB文件,我们假设1MB = 1000KB,而1KB = 1024B(这个好算一些)。
那么3MB文件就有3000个逻辑块(扇区),需要读6个磁道。
T_maxrotate = 5 ms
T_transfer = 0.01 ms
A.最好情况是6个磁道都在一个柱面上,只需要寻一次道,而且文件是顺序存储。
T = T_seek + 0.5*T_maxrotate + 6*T_maxrotate =  35.5ms
B. 最差的情况 3000*(T_seek + 0.5*T_maxroate + T_transfer) = 16530ms

6.26

高速
缓存

m

C

B

E

S

t

s

b

1

32

2048

4

4

128

23

7

2

2

32

2048

4

512

1

30

0

2

3

32

2048

8

1

256

21

8

3

4

32

2048

8

128

2

28

1

3

5

32

2048

32

1

64

21

6

5

6

32

2048

32

4

16

23

4

5


6.27

高速
缓存

m

C

B

E

S

t

s

b

1

32

8192

16

1

512

19

9

4

2

32

4096

4

4

256

22

8

2

3

32

4096

4

8

128

23

7

2

4

32

2048

32

4

16

22

4

5


感觉最后一行答案有错误,C应该是4096,或者t是23,或者E为2。

6.28_6.29

Address_start = (tag<<5) | (set<<2);
Address_end = (tag<<5) | (set<<2) | 3;

 

行1

行2

组0

0x0120-0x0123

-

组1

0x08A4-0x08A7

0x0704-0x0707

组2

-

-

组3

-

0x064C-0x064F

组4

0x18F0-0x18F3

0x00B0-0x00B3

组5

0x0E34-0x0E37

-

组6

0x1238-0x123B

-

组7

-

0x1BDC-0x1BDF



6.30
b = 2, s = 2, t = 12 - b - s = 8;
A.

11

10

9

8

7

6

5

4

3

2

1

0

CT

CT

CT

CT

CT

CT

CT

CT

CI

CI

CO

CO

B.

操作

地址

命中?

读出的值

0x409

No

-

0x40A

Yes

-

0x833

Yes

0xD0


6.31
A. C = E*B*S = 128 字节
B. b = 2, s = 3, t = 13-b-s = 8;

12

11

10

9

8

7

6

5

4

3

2

1

0

CT

CT

CT

CT

CT

CT

CT

CT

CI

CI

CI

CO

CO


6.32
A.0x0718

12

11

10

9

8

7

6

5

4

3

2

1

0

0

0

1

1

1

0

0

0

1

1

0

0

0

B.

参数

块偏移CO

0x00

索引CI

0x6

标记CT

0x38

命中?

Yes

返回值

0xFA


6.33
A.0x16EC

12

11

10

9

8

7

6

5

4

3

2

1

0

1

0

1

1

0

1

1

1

0

1

1

0

0


B.

参数

块偏移CO

0x00

索引CI

0x3

标记CT

0xB7

命中?

No

返回值

-


6.34
0x1314-0x1317
0x1794-0x1797

6.35
对于写分配的高速缓存,每次写不命中时,需要读取数据到高速缓存中。
该高速缓存只有2个组,对于相同的i,j,src[i][j]和dst[i][j]对应相同的组。
src[0] src[2] 对应组0;
src[1] src[3] 对于组1。
dst同src。

dst数组

 

列0

列1

列2

列3

行0

m

h

m

h

行1

m

m

h

m

行2

m

h

m

h

行3

m

m

h

m


src数组

 

列0

列1

列2

列3

行0

m

m

m

m

行1

m

m

m

m

行2

m

m

m

m

行3

m

m

m

m



6.36
缓存能完全容得下两个数组,所以只会出现冷不命中。

dst数组

 

列0

列1

列2

列3

行0

m

h

h

h

行1

m

h

h

h

行2

m

h

h

h

行3

m

h

h

h


src数组

 

列0

列1

列2

列3

行0

m

h

h

h

行1

m

h

h

h

行2

m

h

h

h

行3

m

h

h

h



6.37
A.缓存为1024字节,数组大小为2*256*4=2048,所以x[0]和x[1]的每一个元素(x[0][i]和x[1][i])对应的高速缓存是同一个块。
因此,每次都在加载,驱逐。不命中率为100%。
B. 缓存足够大,只有冷不命中,不命中率为1/8 = 12.5%。
C. 这种情况相当于是只有冷不命中,不命中率为12.5%。
D. 不会降低,因为块大小不变时,冷不命中的概率不可能被减小。
E. 会降低,因为一个块的大小增加,冷不命中的频率就降低。

6.38
写了个程序进行测试的。
结果如下:

函数

N=64

N=60

sumA

0.25

0.25

sumB

1

0.25

sumC

0.5

0.25


程序清单:
unsigned calc_address(unsigned head, int i, int j, int N)
{
    return head + i*N*4 + j*4;
}

unsigned calc_line(unsigned addint block_size, const int line)
{
    return (add / block_size) % line;
}

int isHit(unsigned cache[], unsigned r, unsigned a, int block_size)
{
    a = a / block_size * block_size;
    unsigned tmp = cache[r];
    cache[r] = a;
    return tmp == a;
}

void testA(int block_size, const int line, unsigned addconst int N)
{
    unsigned cache[line];
    memset(cache, -1sizeof(cache));
    int hit = 0, miss = 0;

    for(int i=0; i<N; ++i)
    for(int j=0; j<N; ++j)
    {
        unsigned address = calc_address(add, i, j, N);
        unsigned r = calc_line(address, block_size, line);
        hit += isHit(cache, r, address, block_size);
    }
    miss = N*N - hit;
    cout << "sumA " << hit << " " << miss << endl;
    cout << (double)miss/(N*N) << endl;
}

void testB(int block_size, const int line, unsigned addconst int N)
{
    unsigned cache[line];
    memset(cache, -1sizeof(cache));
    int hit = 0, miss = 0;

    for(int j=0; j<N; ++j)
    for(int i=0; i<N; ++i)
    {
        unsigned address = calc_address(add, i, j, N);
        unsigned r = calc_line(address, block_size, line);
        hit += isHit(cache, r, address, block_size);
    }
    miss = N*N - hit;
    cout << "sumB " << hit << " " << miss << endl;
    cout << (double)miss/(N*N) << endl;
}


void testC(int block_size, const int line, unsigned addconst int N)
{
    unsigned cache[line];
    memset(cache, -1sizeof(cache));
    int hit = 0, miss = 0;

    for(int j=0; j<N; j+=2)
    for(int i=0; i<N; i+=2)
    {
        unsigned a, r;
        a = calc_address(add, i, j, N);
        r = calc_line(a, block_size, line);
        hit += isHit(cache, r, a, block_size);

        a = calc_address(add, i+1, j, N);
        r = calc_line(a, block_size, line);
        hit += isHit(cache, r, a, block_size);

        a = calc_address(add, i, j+1, N);
        r = calc_line(a, block_size, line);
        hit += isHit(cache, r, a, block_size);

        a = calc_address(add, i+1, j+1, N);
        r = calc_line(a, block_size, line);
        hit += isHit(cache, r, a, block_size);
    }
    miss = N*N - hit;
    cout << "sumC " << hit << " " << miss << endl;
    cout << (double)miss/(N*N) << endl;
}

void testHit()
{
    const unsigned start_address = 0x08000000;
    const int cache_size = 4*1024;
    const int block_size = 16;

    int line = cache_size / block_size;
    int N = 64;
    cout << N << endl;
    testA(block_size, line, start_address, N);
    testB(block_size, line, start_address, N);
    testC(block_size, line, start_address, N);
    cout << "-----" << endl;
    N = 60;
    cout << N << endl;
    testA(block_size, line, start_address, N);
    testB(block_size, line, start_address, N);
    testC(block_size, line, start_address, N);
}

6.39
A. 写总数为 16*16*4 = 1024
B C. 这种情况只有冷不命中,一个block能存下16个int,不命中率为1/16。不命中总数为64。


6.40
A. 写总数为 16*16*4 = 1024
B C. 
E = 1024/64 = 16,每4行才能容得下数组的一行,每次j在变化时,都会不断驱逐掉之前的缓存。所以,只有循环内是可以命中的。不命中率为1/4,不命中总数为256。

6.41
A. 写总数为 16*16*4 = 1024
B. 
一行能保持4个square结构体的值,所以第一个双循环不命中率为1/4。
第二个双循环,不命中率为1/12。
总的不命中次数为 16*16/4 + 16*16*3/12 = 16*16/2 = 128。
C. 不命中率为 1/8。
前的缓存。所以,只有循环内是可以命中的。不命中率为1/4,不命中总数为256。

6.42
每行只有4个字节,那只可能是循环中后三个命中,第一个不命中,不命中率为0.25。
感觉这个题目设定应该不是每行4个字节,64个字节也好啊。

6.43
和上题一样,每次要写一个char,不命中率仍然为0.25。

6.44
每次写一个int,每次都不会命中。不命中率为100%。

6.45
固定stride,看吞吐量随着工作集大小改变的情况。
那个mountain的程序不会用,心想还是先看完书,所以也没花功夫看。

6.46 6.47暂时都没想到
可能的想法是,将两层循环都进行二展开,这样至少可以:
dst[j*dim+i] = src[i*dim+j];
dst[(j+1)*dim+i] = src[i*dim+j+1];
dst[j*dim+i+1] = src[(i+1)*dim+j];
dst[(j+1)*dim+i+1] = src[(i+1)*dim+j+1];
只要不是遇到缓存抖动,不命中率最多就是50%,还是会比较低的。
如果加入运算,就可以想办法同时更新 dst[i][j], dst[j][i]。
但是这样读不命中就可能高了。

等待高人回答吧!



  • 14
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值