计算二维数组的页面错误数

时间:2013-04-12 01:22:24

标签: arrays operating-system paging page-fault

我正在努力学习考试......我找到了这个例子但却无法理解他们是如何得到答案的。有人能解释一下吗?

问题:

  

考虑二维数组A:   int A [] [] = new int [100] [100];   其中A [0] [0]位于页面大小为200的分页存储器系统中的位置200处。操作矩阵的小进程驻留在页面0(位置0到199)中。因此,每次取指令都来自第0页。   对于两个页面框架,以下数组初始化循环生成了多少页面错误,使用LRU替换并假设第一个页面框架包含进程而另一个最初是空的?

A:

for (int j=0;j<100;j++)
   for (int i=0; i<100; i++)
     A[i][j] = 0;

B:

for(int i=0; i<100; i++)
  for (int j=0; j<100; j++)
      A[i][j] = 0;

给出的正确答案是: a:100 x 50 = 5000 b:50

我有点理解第一部分。共有50页。 (10000/200 = 50)并且每次j发生变化时,都会发生页面错误...总共有100页错误...但为什么会乘以50?为什么第二个50?

谢谢!

4 个答案:

答案 0 :(得分:6)

假设您的系统为您的流程分配了两个框架,以便一次可以将200 * sizeof(int)矩阵保留在内存中。矩阵的分配发生在Row Major Order中。

在第一个循环 A

for (int j=0;j<100;j++)
   for (int i=0; i<100; i++)
     A[i][j] = 0;

循环访问存储器单元,用于矩阵列式,如:

A[0][0], A[2][0], A[3][0], ...A[0][2], A[0][3], A[0][4], ......
  ^        ^         ^   
      row changes,               

在每次迭代行更改并且分配在行major中,每行占用一页。因此代码A将导致每个备选A [i] [j]访问的页面错误,因此页面错误总数= 100 * 100/2)= 5000.

第二个代码 B ::

for(int i=0; i<100; i++)
  for (int j=0; j<100; j++)
      A[i][j] = 0;

在每次迭代时循环访问用于矩阵的存储器单元,如:

A[0][0], A[0][5], A[0][6],...,A[1][0], A[1][7], A[1][8],...,A[2][0], A[2][9],
     ^        ^        ^  
  column changes, row are same 

逐行访问(读取读取时行的列更改仅在100次读取后更改),一次加载一行,以便在行更改(对于外部循环)和每个备用行访问时发生页面错误发生页面错误,因此页面错误数= 100/2 = 50.

我们可以通过另一种方式理解:
在行专业中,行索引更改的次数我们需要新页面访问,因为页面数量很小,每个备用索引的页面错误在第一个循环行索引中更改100 * 100次,如在B循环行索引中更改100因此,A / B = 100 * 100/100 = 100时的页面错误率,如果A = 50,00中发生页面错误次数,则B页面错误数量= 50,00 / 100 = 50。

类似地,您可以计算Column-major order的页面错误数,因为矩阵具有相同的行数,而cols结果将相同。

我的书中给出了类似的例子:
下载pdf:operating system book Galvin阅读第9章:虚拟内存部分:9.9.5程序结构。

答案 1 :(得分:2)

这里的关键是看看从线性存储器地址读取时所有数组访问的外观。还必须假设行主(C)顺序才能使答案有意义。问题还遗漏了单位,我们假设这些单位是字节(因此A必须以1字节类型保存)。

char *B = &(A[0][0]); (memory address 200)

访问A[i][j]现在相当于B[i*100 + j]*(200 + i*100+j)(行主要订单)。 两页可以放在内存中。一个由程序采用(字节0-199 - 也是C约定)。另一种是访问A,它跨越100 * 100字节/(200字节/页)= 50页。

由于0-199始终在内存中,另一页将寻址n * 200到(n + 1)* 200-1,其中n是某个整数 - 一次对应于2行A.

最后,在页面错误时,最近最少使用(LRU)算法只读取第0-199页的指令,因此总是会丢弃持有A的旧部分的页面来读取A的新部分(当n改变时,每2行)。

因此,您可以通过读取100x100矩阵的行来轻松查看正在发生的事情 - 每2行交换页面,并且在外部循环中重复100次(从一行到左右)。这导致100x50页面错误。

在现实世界中,您可以使用linux commandsgetrusage跟踪网页错误。

答案 2 :(得分:1)

因此,在逐行或逐列存储的二维数组中总共有50页。

如果您逐行存储页面并逐行访问它们,那么您将一遍又一遍地访问同一页面,直到进入下一页,因此您只能切换页面(导致页面错误)50次因为有50页。

如果您逐行存储页面,并逐列(或vise-verse)访问它们,您将从一个页面获取元素,切换页面,从另一个页面获取一个页面,切换页面等等。所以你的仍然经历50页,但你为每一页切换100次。

对您的阅读成像进行成像。如果您一次只阅读一页,则每页都会翻页一次。如果你在每一页上读掉一行,那么重新开始阅读第二行,第三行等,你必须反复翻阅整篇论文,对于页面上的每一行(假设所有页面都有相同的编号)像数组一样的行...)每次翻页都是页面错误。

答案 3 :(得分:1)

让我们来看一个人为的但信息丰富的例子。假设页面是 128字的大小。考虑一个C程序,其功能是初始化为0 128×128阵列的每个元素。以下代码是典型的:

int i, j;
int[128][128] data;
for (j = 0; j < 128; j++)
  for (i = 0; i < 128; i++)
data[i][j] = 0;

注意数组存储行主要;也就是说,存储了数组 data [0] [0],data [0] [1],...,data [0] [127],data [1] [0],data [1] [1],..., 数据[127] [127]。对于128个单词的页面,每行占用一页。从而, 前面的代码在每个页面中将一个单词归零,然后在每个单词中输入另一个单词 页面,等等。如果操作系统分配少于128帧 整个程序,然后执行将导致128×128 = 16,384个页面错误。

相反,假设我们将代码更改为

int i, j;
int[128][128] data;
for (i = 0; i < 128; i++)
for (j = 0; j < 128; j++)
data[i][j] = 0;

此代码在开始下一页之前将所有单词归零, 将页面错误数量减少到128个。