目录
例题:
0. BaseAddress
1. 行存储方式(Row-major order)
2. 列存储方式(Column-major order)
3. 解方程找到 i 和 j
行存储和列存储方式的区别
行存储方式(Row-major order):
列存储方式(Column-major order):
优缺点
行存储方式的优点:
行存储方式的缺点:
列存储方式的优点:
列存储方式的缺点:
行存储方式的应用场景
列存储方式的应用场景
混合存储方式
另一道计算例题:
从填充的角度去理解上道题:
二维数组 N 的元素是 4 个字符(每个字符占一个存储单元)组成的串,行下标 i 的范围从 0 到 4,列下标 j 的范围从 0 到 5,N 按行存储时元素 N[3][5]的起始地址与 N 按列存储时元素( )的起始地址相同。
我们需要理解二维数组在内存中的行存储和列存储方式,并找到对应元素的地址。
在内存中,BaseAddress
是数组的起始地址,即数组中第一个元素(通常是 N[0][0])的内存地址。所有数组元素的地址计算都是基于这个起始地址进行的。
在行存储方式中,数组的元素是按行顺序存储的。对于数组 N[5][6](行数为5,列数为6),元素 N[i][j] 在内存中的位置可以通过下面的公式计算: N[i][j] =BaseAddress + (i *列数+ j) *元素大小 其中,元素大小是由于每个元素由4个字符组成,所以是 4 字节。
对于 N[3][5],地址计算为:
N[3][5] = BaseAddress + (3 * 6 + 5) * 4
N[3][5] = BaseAddress + 23 * 4
N[3][5] = BaseAddress + 92
在列存储方式中,数组的元素是按列顺序存储的。对于同样的数组 N[5][6],元素 N[i][j] 的地址计算公式变为:
N[i][j] = BaseAddress + (j * 行数 + i) * 元素大小
我们需要找到一个元素 N[i][j],使得它在列存储方式中的地址与行存储方式中 N[3][5] 的地址相同:
N[i][j] = BaseAddress + (j * 5 + i) * 4 = BaseAddress + 92
(j * 5 + i) * 4 = 92 ===> (j * 5 + i) = 23
我们需要找到满足 (j * 5 + i) = 23 的 i 和 j 的整数解,其中 i 的范围是 0 到 4,j 的范围是 0 到 5。通过试验或解方程,我们找到:
因此,N[3][4] 是按列存储时与按行存储的 N[3][5] 起始地址相同的元素。
行存储方式的主要缺点通常是在需要频繁访问列数据的场景中性能降低。这种性能下降主要由以下几个因素引起:
缓存未命中(Cache Misses):
内存带宽利用不足:
预取策略的效率降低:
多线程和并行处理的复杂性增加:
游戏开发:
应用程序开发:
传统关系数据库:
大数据分析和数据仓库:
科学计算和工程应用:
现代列式数据库:
一些现代系统甚至采用混合存储方式,结合行存储和列存储的优点,以适应多变的数据访问模式。例如,南大通用 GBase数据库和Microsoft SQL Server 的某些版本就支持这种混合模式,可以根据应用需求动态优化数据存储和访问。
总结来说,选择行存储还是列存储取决于数据访问模式。了解和选择合适的存储方式可以显著影响程序的性能和效率。
设有数组 A[i,j],数组的每个元素长度为 3 字节,i 的值为 1 到 8,j 的值为 1 到 10,数组从内存首地址 BA 开始顺序存放,当以列为主序存放时,元素 A[5,8]的存储首地址是 BA+?
此数组是一个8行10列的数组,元素大小为3字节,但i,j分别都是从1开始计数的。
如果死套公式,列存储:
A[i][j] = A[5][8] = BA + (j * 行数 + i) * 元素大小 = BA + (8*8+5)*3 = BA + 69*3 = BA + 207。就会得到错误答案 。
我们的来计算元素 A[5,8] 的地址是基于列主序存储的正确公式,但是在计算过程中有一点小错误需要纠正。公式本身是正确的,但应用时需要注意细节。让我们一步步来检查和应用这个公式:
在此题中,正确公式是:A[i][j] = BaseAddress + ((j-1)* 行数 + (i-1)) * 元素大小
这里的 (i) 和 (j) 是从1开始的索引,因此要计算以0为基的索引,我们需要从 (i) 和 (j) 中分别减去1。
对于元素 A[5,8],使用以下参数:
因为我们是从1开始计数的,而在计算内存地址时需要以0为基数。这样的细节在处理数组和内存地址计算时非常重要。
在列主序存储中,数组的元素是按列填充的,也就是说,首先填充第一列的所有行,然后是第二列的所有行,依此类推。
给定的数组 A[i, j] 的维度是 i = 1 到 8 和 j = 1 到 10,每个元素占用 3 字节。我们需要找到元素 A[5,8] 的存储首地址。
按列主序,第一列的元素 A[1,1], A[2,1], ..., A[8,1] 都先被存储,每个元素占用 3 字节。因此,第一列占用的总字节数是 8 * 3 = 24 字节。同理,每列都占用 24 字节。
元素 A[5,8] 位于第 8 列,第 5 行。要找到这个元素的地址,我们需要先计算前 7 列的总字节数,然后加上到第 5 行的偏移量。
因此,元素 A[5,8] 的存储首地址 = 基地址 BA + 168 字节 + 12 字节 = BA + 180 字节。
所以,元素 A[5,8] 的存储首地址是 BA + 180 字节。