访问内存中的某个地址
Accessing a certain address in memory
为什么我们可以访问O(1(中内存中的某个位置?
快速回答:你不能!
然而,系统的主存储器,即板上的芯片,可以通过直接访问来寻址。只要给出正确的地址,总线就会返回该位置的内存(可能是在块中(。
然而,一旦你进入CPU,内存访问就大不相同了。有几个缓存,几个带缓存的内核,可能还有其他带缓存的CPU。虽然可以直接访问主内存,但速度很慢,这就是为什么我们有所有这些缓存的原因。但现在这意味着CPU内部的内存无法直接访问。
当CPU需要访问内存时,它就进入查找模式。它还有一个锁定系统,可以在缓存之间正确地共享内存。不同的地址实际上需要不同的访问时间,这取决于您是在读还是在写,以及该内存的最新缓存所在的位置。这就是所谓的NUMA(非均匀内存访问(。虽然这里的时间复杂性可能受常数(所以可能/technolical O(1((的约束,但它可能不是大多数人认为的恒定时间。
事情变得比这更复杂。CPU为内存提供页表,这样操作系统就可以向应用程序提供虚拟内存(也就是说,它可以对地址空间进行分区(,并根据需要加载内存。这些表格是类似地图的结构。当您访问内存时,CPU决定是否加载了您想要的地址,或者操作系统是否必须首先检索它。这些映射是总内存大小的函数,因此不是线性时间,尽管很可能是摊销的恒定时间。(如果您正在运行虚拟机,您可以在上面添加另一层表,这也是VM运行速度稍慢的原因之一(。
这只是一个简短的概述。希望这足以给你一种印象,即记忆访问并不是一个持续的时间,它取决于很多事情。然而,请记住,在这些级别上使用了如此多的优化,以至于高级C程序可能看起来具有恒定的时间访问权限。
现代计算机系统中的内存是随机访问的,因此只要您知道需要访问的内存地址,计算机就可以直接访问该内存位置并对该位置进行读/写。
这与一些[旧]系统(如磁带存储器(相反,在这些系统中,磁带必须以物理方式假脱机才能访问某些区域,因此访问更远的位置需要更长的时间。
不确定您所说的以O(1(分配是什么意思,因为在处理日常计算机上的典型堆时,分配内存通常不是O(1。
这取决于您使用的计算模型,在图灵机模型中,两个操作都不是O(1(,在随机访问模型中,访问是O(1。为了简单起见,我假设您使用的模型也允许O(1(分配,这与在内存使用负载较轻的机器上的大多数现代实现非常接近。
为什么可以在O(1(中访问?因为内存访问是通过地址进行的。如果你知道你想访问的地址,那么硬件可以直接访问它,并在一次操作中获取任何地址。
至于分配是O(1(,我不确定总是这样。由操作系统来分配一个新的内存块,而它用来分配内存的算法可能不一定在所有情况下都是O(1(。例如,如果您请求一个大的内存块,但没有足够大的连续块来满足请求,则操作系统可能会执行一些操作,如调出其他数据或重新定位其他进程中的信息,以创建一个足够大的相邻块来满足请求。
不过,如果您想将分配视为"返回可用内存的第一个字节的地址",那么很容易理解为什么这可能是O(1(操作。系统只需要返回最后一个分配字节的地址+1,所以只要它在每次分配后跟踪最后一个被分配的字节是什么,只要你假设有无限的内存空间,那么计算下一个空闲地址总是O(1(。
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- CUDA:统一内存和指针地址的更改
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 使用内存地址访问结构的属性值
- 如何读取特定地址的进程内存?
- 为什么C++总是显示十六进制内存地址,而不仅仅是整数?
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 将布局映射到内存地址
- 为什么同一个变量的内存地址不同?
- LLVM 传递以在特定地址分配内存
- 无法将内存地址转换为值
- 是否可以仅通过将分配的指针地址存储在C++中来分析内存?
- 给定特定内存地址的数组的动态内存分配
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- 我有一个线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x8)错误.我认为这是由于内存管理不好.我可以
- 获取 R 数据帧的内存地址
- 如何配置bazel以运行地址/内存清理器?
- 存储 std::list 元素的地址;内存
- 确定库的地址内存