由腾讯的一个笔试题牵涉的知识点,自己之前没有接触过,就总结了一下:
题目原文:
在程序设计中,要对两个16K×16K的多精度浮点数二维数组进行矩阵求和时,行优先读取和列优先读取的区别是()
A、没区别
B、行优先快
C、列优先快
D、2种读取方式速度为随机值,无法判断
【解析】若在内存中,则数据可以”随机存取”,但内存数据被读取或写入时,所需要的时间与这段信息所在的位置无关.但是在读取和写入磁盘时,其所需要的时间与位置就会有关系.因为在BASIC,PASCAL和C/C++语言中,数组的存放是按照行优先来存放的,按行号第一行第二行…以此类推.本体关键是考察内存抖动的问题,如果按列访问则需要跳过一大串内存地址,这样可能需求的内存地址不在当前页中则需要进行页置换,这样便需要硬盘IO,减低速度.
【知识点】
一、关于多维数组在内存中的存放问题(出处多维数组在内存中的存放)
1、数组(向量)——常用数据类型
一维数组(向量)是存储于计算机的连续存储空间中的多个具有统一类型的数据元素。
同一数组的不同元素通过不同的下标标识。
(a1,a2,…,an)
2、二维数组
二维数组Amn可视为由m个行向量组成的向量,或由n个列向量组成的向量。
二维数组中的每个元素aij既属于第i行的行向量,又属于第j列的列向量。
3、多维数组
三维数组Amnp可视为以二维数组为数据元素的向量。四维数组可视为以三维数组为数据元素的向量……
三维数组中的每个元素aijk都属于三个向量。四维数组中的每个元素都属于四个向量……
4、数组的顺序存储方式
由于计算机内存是一维的,多维数组的元素应排成线性序列后存人存储器。
数组一般不做插入和删除操作,即结构中元素个数和元素间关系不变化。一般采用顺序存储方法表示数组。
(1)行优先顺序
将数组元素按行向量排列,第i+1个行向量紧接在第i个行向量后面。
【例】二维数组Amn的按行优先存储的线性序列为:
a11,a12,…,a1n,a21,a22,…,a2n,……,am1,am2,…,amn
注意:
①PASCAL和C语言中,数组按行优先顺序存储。
②行优先顺序推广到多维数组,可规定为先排最右的下标。
(2)列优先顺序
将数组元素按列向量排列,第i+1个列向量紧接在第i个列向量后面。
【例】二维数组Amn的按列优先存储的线性序列为:
a11,a21,…,am1,a12,a22,…,am2,……,a1n,a2n,…,amn
注意:
①FORTRAN语言中,数组按列优先顺序存储。
②列优先顺序推广到多维数组,可规定为先排最左的下标。
5、数组元素的地址计算公式
(1)按行优先顺序存储的二维数组Amn地址计算公式
LOC(aij)=LOC(a11)+[(i-1)×n+j-1]×d
其中:
①LOC(a11)是开始结点的存放地址(即基地址)
②d为每个元素所占的存储单元数
③由地址计算公式可得,数组中任一元素可通过地址公式在相同时间内存取。即顺序存储的数组是随机存取结构。
(2)按列优先顺序存储的二维数组Amn地址计算公式
LOC(aij)=LOC(a11)+[(j-1)×m+i-1]×d
(3)按行优先顺序存储的三维数组Amnp地址计算公式
LOC(aijk)=LOC(a111)+[(i-1)×n×p+(j-1)×p+k-1]×d
(4)下界不为1的二维数组的地址计算公式
①二维数组A[c1..d1,c2..d2]的地址计算公式:
LOC(aij)=LOC(ac1c2)+[(i-c1)×(d2-c2+1)+j-c2]×d
②下界为0的二维数组的地址计算公式(C语言中使用)
LOC(aij)=LOC(a00)+[i×(d2+1)+j]×d
注意:
以下讨论的数组存储结构都以C语言下标表示。
二、关于缺页中断的问题
由于程序可能会远大于内存,需要引入虚拟内存。基本思想是:每个程序都拥有自己的地址空间,这个空间被分割成很多块,每一块称作为一个页面,每一页有连续的地址范围,这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件立刻执行必要的映射,而当程序引用到一部分不在内存的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的指令。如果一个页面没有映射,内存管理单元注意到它没有映射时,使CPU陷入到操作系统,这个陷阱称为缺页中断。
三、内存抖动的问题
1.1 最少内存块数
分配给进程的内存块数目是受到限制的,分配的总块数不能超出可用块的总量(除非存在页共享的情况)。另一方面,每个进程也需要有起码最少的块数。很显然,随着分给每个进程块数的减少,缺页率将上升,降低了进程的执行速度。
分给每个进程的最少块数是指能保证进程正常运行所需的最少内存数,它是由指令集结构决定的。因为正在执行的指令被完成之前出现缺页时,该指令必须被重新启动,与此相应,必须有足够的块把一条指令所访问的各个页都存放起来。
而每个进程的最多块数是由可用内存的总量决定的。
1.2 固定分配和可变分配
请求分页系统支持虚拟存储器,可以采用两种内存块分配策略,即固定分配和可变分配。
(1)固定分配策略是分配给进程的内存块数是固定的,并在最初装入时(即进程创建时)确定块数。分给每个进程的内存块数基于进程类型(交互式、批处理型、应用程序型等),或者由程序员或系统管理员提出 的建议。当进程执行过程中出现缺页时,只能从分给该进程的内存块中进行页面置换。
(2)可变分配策略允许分给进程的内存块数随进程的活动而改变。如果一个进程在运行过程中持续缺页率太高,这就表明该进程的局部化行为不好,需要给它分配另外的内存块,以减少它的缺页率。如果一个进程的缺页率特别低,就可以减少分配的内存块,但不要显著增加缺页率。
可变分配策略的功能更强,但需要操作系统估价出各活动进程的行为,这就增加了操作系统的软件开销,并且依赖于处理器平台所提供的硬件机制。
1.3 全局置换与局部置换
内存块分配的另一个重要问题是页面置换范围。多个进程竞争内存块时,可以把页面置换分为两种主要类型:全局置换和局部置换。全局置换允许一个进程从全体存储块的集合中选取置换块,尽管该块当前已分给其他进程,但还是能强行剥夺。而局部置换是每个进程只能从分给它的一组块中选择置换块。
采用局部置换策略,分给进程的块数是不能变更的。采用全局置换策略,一个进程可以只从分给其他进程的块里挑选。这样,如果没有别的进程挑选它的块,那么分给该进程的块数就增加了。可以由一个核心进程专门负责页面置换工作。
全局置换算法存在的一个问题是,程序无法控制自己的缺页率。一个进程在内存中的一组页面不仅取决于该进程的页面走向,而且也取决于其他进程的页面走向。因此,相同程序由于外界环境不同会造成执行上的很大差别。使用局部置换算法就不会出现这种情况,一个进程在内存中的页面仅受本进程页面走向的影响。
1.4 内存块分配算法
为每个进程分配内存块的算法主要有三种:等分法、比例法和优先权法。
(1)等分法
为每个进程分配存储块的最简单的办法是平分,即若有m块、n个进程,则每个进程分m/n块(其值向下取整)。
等分法不区分具体进程的需求,“一视同仁”地进行分配。其结果造成:有的进程用不了那么多块,而另外进程却远远不够用。为解决这个问题,可采取按需成比例分配的办法。
(2)比例法
分给进程的块数=进程地址空间大小 / 全部进程的总地址空间 * 可用块总数
上述两种情况下,分给每个进程的块数依据多道程序数目而变。多道程序数增加了,每个进程就要少分一些块。相反,多道程序数少了,分给每个进程的块数可多一些。
(3)优先权法
在上面两种算法中没有考虑优先级问题,即把高优先级进程和低优先级进程一样对待。为加速高优先级进程的执行,可以给高优先级进程分较多内存。如使用比例分配法时,分给进程的块数不仅取决于程序的相对大小,而且也取决于优先级的高低。
2 抖动(Thrashing)问题
置换算法的优劣,直接影响到系统的效率。若选用算法不合适,可能会出现这种现象:刚被置换出去的页,很快又要访问,因而要把它重新调入;可是调入不久又再次被置换出去,这样再访问、再调入,如此反复,使得整个系统的页面替换非常频繁,以致大部分的机器时间都花在来回进行的页面调度上,只有一小部分时间用于进程的实际运算。这种局面就称为系统“抖动”。
产生抖动的原因是系统中多道程序度过高,进程运行缺页率严重。一般情况下,在多道程序度较小时,随着它的增加,CPU利用率会缓慢增加。当到达最大值后,多道程序度进一步增大,就出现了抖动,导致CPU利用率急剧下降。
防止抖动发生或者限制抖动影响的方法有多种,但一般都基于调节多道程序度。
(1)采用局部置换策略。如果一个进程出现抖动,它不能从另外的进程那里夺取内存块,从而不会引发其他进程出现抖动,使抖动局限于一个小的范围内。然而这种方法并未消除抖动的发生,而且在一些进程发生抖动的情况下,等待磁盘I/O的进程增多,使得平均缺页处理时间加长,从而延长了有效存取时间。
(2)利用工作集策略防止抖动。
(3)挂起某些进程。当出现CPU利用率、而磁盘I/O非常频繁的情况时,就可能因为多道程序度太高而造成抖动。为此,可挂起一个或几个进程,以便腾出内存空间供抖动进程使用,从而消除抖动现象。被挂起进程的选择策略有多种,如优先权最低的进程、缺页进程、最近激活的进程、驻留集最小的进程和最大的进程等。
(4)采用缺页频度法(PFF,Page Fault Frequency)。抖动发生时缺页率必然很高。这样,通过控制缺页率就可预防抖动。当缺页率太高时,表明进程需要更多的内存块。反之,如果缺页率很低,表示进程可能占用的内存块太多。规定一个缺页率,依此设置相应的上限和下限。如果实际缺页率超出上限值,就为该进程分配另外的内存块;如果实际缺页率低于下限值,就从该进程的驻留集中取走一个内存块。通过直接测量和控制缺页率,就可以预防抖动。
3 工作集
一个页面置换算法的好坏与进程运行的页面走向有很大的关系。虚拟存储系统的有效操作依赖于程序中访问的局部化程度。对于LRU算法而言,局部化程度愈突出,进程运行效率愈高。
局部化可分为两类:时间局部化和空间局部化。时间局部化是指一旦某条指令或数据被访问了,它常常很快又被再次访问,如程序中的循环部分。空间局部化指的是一旦某个位置被访问到,那么它附近的位置也可能很快要用到,如程序中的顺序指令串。这种情况反映在页面走向上,就是在任何一小段时间里,进程运行只集中于访问某几页。
工作集就是一个进程在某一小段时间内访问页面的集合。它是程序局部性的近似表示。
操作系统监督每个进程的工作集并给它分配足够工作集所需的内存块。若有足够多的额外块,就可装入并启动另外的进程。如果工作集的大小增加了,超出可用块的总数,操作系统要选择一个进程让它挂起,把它原来占的块分给别的进程。
这种工作集策略可防止抖动,同时保持尽可能高的多道程序度,从而使CPU的利用最优。实现工作集模型的困难是怎样保持工作集的轨迹。