一个常见的编程问题: 遍历同样大小的数组和链表, 哪个比较快? 如果按照大学教科书上的算法分析方法,你会得出结论,这2者一样快, 因为时间复杂度都是 O(n)。 但是在实践中, 这2者却有极大的差异。 通过下面的分析你会发现, 其实数组比链表要快很多。
首先介绍一个概念:memory hierarchy (存储层次结构),电脑中存在多种不同的存储器,如下表
-
CPU寄存器 – immediate access (0-1个CPU时钟周期)
-
CPU L1缓存 – fast access (3个CPU时钟周期)
-
CPU L2 缓存 – slightly slower access (10个CPU时钟周期)
-
内存(RAM) – slow access (100个CPU时钟周期)
-
硬盘(file system)– very slow (10,000,000个CPU时钟周期)
(数据来自 http://www.answers.com/topic/locality-of-reference)
各级别的存储器速度差异非常大,CPU寄存器速度是内存速度的100倍! 这就是为什么CPU产商发明了CPU缓存。 而这个CPU缓存,就是数组和链表的区别的关键所在。
CPU缓存会把一片连续的内存空间读入, 因为数组结构是连续的内存地址,所以数组全部或者部分元素被连续存在CPU缓存里面, 平均读取每个元素的时间只要3个CPU时钟周期。 而链表的节点是分散在堆空间里面的,这时候CPU缓存帮不上忙,只能是去读取内存,平均读取时间需要100个CPU时钟周期。 这样算下来,数组访问的速度比链表快33倍! (这里只是介绍概念,具体的数字因CPU而异)
因此,程序中尽量使用连续的数据结构,这样可以充分发挥CPU缓存的威力。 这种对缓存友好的算法称为 Cache-oblivious algorithm, 有兴趣可以参考相关资料。再举一个简单例子:
对比
for i in 0..n
for j in 0..m
for k in 0..p
C[i][j] = C[i][j] + A[i][k] * B[k][j];
和
for i in 0..n
for k in 0..p
for j in 0..m
C[i][j] = C[i][j] + A[i][k] * B[k][j];
虽然两者执行结果一样,算法复杂度也一样,但是你会发现第二种写法要快很多。
总结一下, 各种存储器的速度差异很大,在编程中绝对有必要考虑这个因素。 比如,内存速度比硬盘快1万倍,所以程序中应该尽量避免频繁的硬盘读写;CPU缓存比内存快几十倍,在程序中尽量多加利用。
>> 原创文章的版权属于作者,转载请注明出处和作者信息(http://blog.csdn.net/WinGeek/), 谢谢。 <<
分享到:
相关推荐
"优化模型程序代码.lg4.zip"这个压缩包文件很可能包含了一个使用特定编程语言(如Lisp, G4或其他未知语言的变种lg4)编写的代码优化模型。下面我们将详细探讨优化模型程序代码的相关知识点。 首先,代码优化是软件...
2. **内存对齐**:优化内存分配,确保数组元素在内存中连续存放,提高CPU缓存效率,降低访问延迟。 3. **并行处理**:如果硬件支持,源码可能利用多核CPU并行处理数组元素,加快加入速度。 4. **避免无效操作**:...
- **缓存优化**:理解数据局部性原理,尽量使数组访问连续,以利用CPU缓存提高效率。 - **分块处理(Block Processing)**:处理大数组时,将数组分割成小块,每次只处理一部分,减少内存带宽需求。 - **动态规划...
在C语言编程中,代码优化是一项至关重要的技能,它能够提升程序的运行效率,减少内存占用,以及提高软件的响应速度。"C_code_optimize.rar"这个压缩包中包含的"C代码优化方案"和"www.pudn.com.txt"文件,显然是为了...
《代码优化:有效使用内存》是一本专注于提升软件性能的关键技术书籍,主要针对应用程序员和系统程序员,旨在帮助他们编写更高效、占用内存更少的代码。这本书不仅对程序员有极大的学习价值,对于硬件领域的专业人士...
- **代码层面优化**:这涉及到算法和数据结构的选择,如选择数组还是链表,以及逻辑结构的简化。 - **内存管理优化**:包括合理使用JVM堆内存空间,减少内存泄漏和垃圾回收(GC)的频率。 - **多线程和并发优化**:...
这是一份专门针对Java优化编程的内部培训资料,旨在帮助中级及以上水平的开发者提升代码性能,实现更高效的应用程序。这份讲义结合了理论与实践,深入探讨了Java语言在实际开发中的优化策略。 **主要知识点** 1. *...
5. **利用缓存优化**:理解CPU缓存的工作原理,尽可能使数据布局符合缓存局部性原则,可以提升数组操作速度。 6. **并行处理**:如果硬件支持,可以考虑使用多线程或并行计算技术,将数组插入任务分割成多个部分...
1. **内存管理**:高效地分配和释放内存,避免内存泄漏和内存碎片,使用合适的数据结构如链表、数组或哈希表等,以及合理利用缓存局部性原理。 2. **循环优化**:避免在循环体内部进行不必要的计算,使用预处理计算...
1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM .........................
1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................
- **缓存优化**:理解CPU缓存的工作原理可以帮助优化数组访问,减少缓存未命中的次数。 9. **ArrayADT的实现** - 你可以找到名为"ArrayADT-master"的压缩包,其中可能包含一个实现ArrayADT的代码库,包括不同的...
本文将深入探讨C语言在提高程序执行效率上的编程技巧,帮助开发者更好地优化代码,提升程序运行速度。 一、理解数据类型与内存管理 1.1 选择合适的数据类型:在C语言中,根据实际需求选择合适的数据类型至关重要。...
- **知识点**: Java是一种广泛使用的面向对象编程语言。 - **选项分析**: - D. 不检查数组下标越界:Java会自动检查数组下标是否越界。 #### 26. 排序算法的选择 - **知识点**: 排序算法是计算机科学中的基础算法...
4. 缓存优化:利用CPU缓存局部性原理,尽可能使相邻元素位于连续的内存区域,以提高访问速度。 数组算法工具是程序设计中的重要组成部分,理解并掌握这些工具可以帮助我们编写出更加高效和优化的代码。在实际开发中...
10. **数据结构与算法**:为了有效地组织和处理CPU信息,源代码可能使用各种数据结构(如链表、数组、哈希表)和算法(如排序、查找)。 通过分析和理解CPU Info的源代码,开发者可以学习到系统编程、硬件接口、...
1. 缓存友好编程:程序员可以使用缓存友好的编程技术,例如使用数组代替链表,使用循环展开等。 2. 数据对齐:程序员可以使用数据对齐技术,例如使用结构体对齐等。 3. 缓存预取:程序员可以使用缓存预取技术,例如...
《代码优化 有效使用内存》一书深入探讨了在编程实践中如何提高代码效率,特别是针对内存使用进行优化的策略和技术。代码优化是软件开发过程中的关键环节,它旨在减少资源消耗,提高程序运行速度,而内存优化则是...
在C编程中,代码优化是提高程序性能的关键步骤。本文将深入探讨11种C代码优化策略,旨在帮助开发者编写出更加高效和精简的代码。 1. **选择合适的算法和数据结构** 选择正确的数据结构和算法对于性能至关重要。...