建网站用,wordpress 光点特效,wordpress群聊插件,网页设计与制作代做作者|码农的荒岛求生来源|码农的荒岛求生有同学问了这样一个问题#xff1a;既然CPU内部的寄存器数量有限#xff0c;容量有限#xff0c;那么我们使用的庞大的数据结构是怎样装入寄存器供CPU计算的呢#xff1f;这篇文章就为你讲解一下这个问题。内存与数据真正有用的程序… 作者|码农的荒岛求生来源|码农的荒岛求生有同学问了这样一个问题既然CPU内部的寄存器数量有限容量有限那么我们使用的庞大的数据结构是怎样装入寄存器供CPU计算的呢这篇文章就为你讲解一下这个问题。内存与数据真正有用的程序是离不开数据的比如一个int、一个float等这些都是非常简单的数据。当然也有非常复杂的数据这样的数据通常在内存中以数据结构的形式组织起来比如你创建了一个数组、一个链表、创建了一棵树、一张图就像这样那么很显然这些数据存放在内存中而且这些数据在不同的场景下有不同的大小从数B、数KB到数百GB都有可能与此同时CPU内部的寄存器数量是固定的容量也是极其有限的那么CPU是如何利用有限的资源操作庞大的数据结构呢要回答这一问题我们需要要认识一位农夫因为他不生产数据他只是数据的搬运工这位农夫就是。。搬运数据的机器指令你没有看错这位农夫就是我们之前多次提到的机器指令。机器指令中除了负责逻辑运算、执行流控制、函数调用等指令外还有一类指令这类执行只负责和内存打交道典型的就是精简指令集架构中的Load/Store机器指令即内存读写指令(复杂指令集没有单独的内存读写指令)。原来从宏观上看的话存放在内存中的数据比如一个数组可能会非常庞大但是具体到代码每一个步骤操作的数据又会非常简单就像这样int* huge_arr new int[1 * 1024* 1024 *1024];我们创建了一个长度为1G的数组每个int 4字节则这个数组的大小就是4GB这显然是一个很庞大的数组。对于这样的数据我们通常都会怎么使用呢最常见的情况可能是遍历一边然后对每个字符进行一个简单操作这里以计算数组之和为例long int sum 0;
for (int i 0; i 1 * 1024* 1024 *1024; i) {sum huge_arr[i];
}虽然整个数组多达4GB但具体到每一步我们一次只能操作一个元素就像这里的sum huge_arr[i];这行代码翻译成机器指令可能是这样的我们假设此时i为100load $r0 100($r2)
add $r1 $r1 $r0(注意实际当中编译器不会傻傻的生成100这样的常数这里代码仅用来方便讲解问题)。第一行指令中数组首地址存放在寄存器r2中100($r2)表示数组首地址100这样我们就能得到huge_arr[100]的地址了然后将该地址中的值利用load指令加载到寄存器r0中。第二行就简单多了r1寄存器中保存的是sum的值该行指令执行过后r1中的值就已经加上了huge_arr[100]。现在你应该能看出来了吧虽然我们不能把整个数组加载到寄存器供CPU计算但这其实是没有必要的因为我们一次只能操作数组中的一个元素我们只需要把这一个元素加载到寄存器就足矣了。对于其它复杂的数据结构也是同样的道理无论多么复杂的数据代码对其一次的操作都是很简单很微小的这一微小的操作使用的基本元素都可以通过内存读写指令加载到寄存器修改完后再写回内存。编译器现在你应该知道了为什么CPU内部那么少的寄存器能操作内存中庞大的数据结构实际上由于内存中的数据要远大于CPU寄存器的容量因此编译器必须精心挑选好让那些经常使用的数据放到寄存器中的时间更长一点这样可以减少内存读写次数。在上面的示例中r2寄存器保存的是huge_arr这个数组在内存中的起始地址那么这个数据应该放到寄存器中因为后续遍历到的每一个元素都要用到该地址这项工作就是编译器来完成的。编译器把那些经常使用的数据放到寄存器剩下的放到内存中然后利用内存读写指令在寄存器和内存之间来回搬运数据。总结通过本文不难发现实际上我们没有必要一次性把整个数据全部装到CPU寄存器中而是用到哪些才装载哪些。在最细粒度的操作中依赖的操作数都可以直接加载到内存这通常是由内存读写机器指令来完成的。希望这篇文章对大家理解CPU与寄存器有所帮助。往期推荐做安全操作系统这位技术老兵很认真这个高薪行业正在大量招人如何给女朋友解释什么是“元宇宙”张一鸣购得元宇宙入场券谁将是头号玩家点分享点收藏点点赞点在看