标题说明了一切:
我创建和阵列,比如ARRAY [10000], 我设置了界限,我只需要访问1-100和900-2000中的数据。
访问和/或更改数据的时间是否会以这种方式花费更多时间,而不是我将数组声明为ARRAY [2001]
如果我的阵列只有1-100和900-2000的数据,是否会更改访问和/或更改时间?
我已经看过一些关于这方面的文章,但他们对我并不清楚,希望我能在这里得到更简洁的答案。
答案 0 :(得分:2)
如果不经常访问数组,那么数组的大小可能会因为你无论如何都会得到缓存未命中而产生很大的不同。在这种情况下,时间将取决于CPU可以多快地执行任何虚拟地址到物理地址"转换并从RAM中获取数据。
您访问数组中的内容越频繁,缓存效果就越重要。这些缓存效果在很大程度上取决于不同缓存的数量,大小和速度。
但是,它还取决于您的访问模式。例如,如果你有一个1 GiB数组并经常访问它的5个字节,那么大小不会产生很大的不同,因为你经常访问的5个字节将在缓存中。再举一个例子,如果你使用顺序访问模式(例如"对于数组{...}")中的每个元素,那么它很可能是CPU可以进行硬件预取而你赢了& #39; t支付缓存未命中的全部费用。
对于典型的80x86系统,具有随机访问模式和频繁访问;大约有5种不同的尺寸。第一个(最小的)是L1数据高速缓存大小 - 如果阵列适合L1数据高速缓存,那么无论数组是20字节还是20 KiB,它都会相对快速。下一个大小是L2数据高速缓存大小 - 当数组变大时," L1命中与L2命中的比率"降低和性能变差直到(可能是"比L1和#34大两倍;)L1命中变得可以忽略不计。然后(对于一些具有L3高速缓存的CPU),L3高速缓存大小也会发生同样的情况,其中当阵列变得更大时," L2命中与L3命中的比率"减小。
一旦你比最大的缓存大,那么"缓存命中与缓存未命中的比率"减小。
可能重要的下一个尺寸是TLB尺寸。大多数现代操作系统都使用分页,大多数现代CPU都会缓存虚拟地址到物理地址的转换"在通常称为翻译旁视缓冲区的东西中。如果阵列很大,那么你开始得到TLB未命中(除了缓存未命中),这会使性能变差(因为CPU在将虚拟地址转换为物理地址时无法避免额外的工作)。
最后,最重要的是你实际拥有多少RAM。如果你有一个10 TiB阵列,4 GiB的RAM和20 TiB的交换空间;然后,操作系统将与磁盘交换数据,磁盘IO的开销将主导性能。
当然,您经常为许多不同的计算机创建可执行文件(例如,#34; 64位80x86,从古代Athlon到现代Haswell")。在这种情况下,您无法了解大多数重要的细节(如缓存大小),并且它会成为猜测之间的折衷(由于"数组太大而导致的缓存未命中估计的开销"与估计的开销相比来自"阵列太小")引起的其他事情。
答案 1 :(得分:1)
不,无论数组的大小如何,至少通常访问数组中任何项目的时间都是不变的。
如果(例如)你定义一个大于内存的数组,这可能会改变,所以操作系统(假设你正在使用一个)最终会做一些额外的分页来支持更大的数组。在大多数情况下,即使这不太可能产生太大影响。
答案 2 :(得分:1)
可能是肯定的,但这取决于尺寸。
访问范围的大小将改变延迟。
int ARRAY[10000]
适合L1缓存(32KB)
非常小的访问,适合L1缓存(32KB),它的成本为4个时钟。
但L2缓存访问需要12个时钟。
在此处查看详细信息 http://www.7-cpu.com/cpu/Haswell.html
它的其他核心CPU修改数组中的一些数据,本地缓存行状态将被修改为Invalid
状态。
Invalid
声明缓存行花费的延迟要多得多。
主板上有多个CPU插槽的某些环境,它被称为non-uniform memory access
环境。
那可能有很大的内存容量,但内存的某些地址可能驻留在CPU1中,其他内存地址可能驻留在CPU2中。
int huge_array[SOME_FUGE_SIZE]; // it strides multiple CPU's DIMM
// suppose that entire huge_array is out of cache.
huge_array[ADDRESS_OF_CPU1] = 1; // maybe fast for CPU1
huge_array[ADDRESS_OF_CPU2] = 1; // maybe slow for CPU2
但是我想知道巨大的阵列会占用多个CPU的内存。 大阵列的分配可能会失败。 这取决于操作系统。
答案 3 :(得分:0)
在其他人所说的信息理论中,数组访问是恒定的,因此根据数组大小的不同,开销不会增加或减少。这个问题似乎与实际现场表演有关,并且阵列的大小肯定很重要。 @Brendan接受的答案很好地说明了这一点。
在实践中要考虑的事项:
*数组中的元素有多大:bool[1000]
,MyStruct[1000]
和MyStruct*[1000]
的访问性能可能有很大不同
*尝试使用两种方式编写代码,一次使用大数组,一次将所需的数据保存在较小的数组中。然后在目标硬件上运行代码,并比较性能。您常常会惊讶地发现,优化尝试会使性能变差,并且您在此过程中了解到很多有关硬件及其怪异之处的信息。
答案 4 :(得分:-1)
我不相信它应该。
当你访问一个元素时,你将会记住位置0 +(元素),无论它在同一时间内到达同一个内存位置的大小。