【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】
  
     以前学习计算机体系结构的时候,也会涉及到cpu缓存、多核和乱序方面的知识,但是真正用代码来表示相关知识的内容,却不是很多。所以,今天打算用三个例子来说明这些内容。缓存的内容比较简单,后面的内容复杂一点,不过没有关系,我们一步一步来说明。这些例子有的网上已经存在了,原来博文的作者已经不是很清楚,不过还是非常感谢他们无私的分享。闲话不多说,我们慢慢来说,
 
 (1)缓存

  #include <stdio.h>#include <malloc.h>#include <windows.h>#define PER_LINE_NUM  10000void test(){int inner, outer, count;char *buffer = malloc(PER_LINE_NUM * PER_LINE_NUM);if(NULL == buffer){return;}count = GetTickCount();for(outer = 0; outer < PER_LINE_NUM; outer++){for(inner = 0; inner < PER_LINE_NUM; inner ++){buffer[outer * PER_LINE_NUM + inner] = outer;}}printf("tick1 = %d\n", GetTickCount() - count);count = GetTickCount();for(outer = 0; outer < PER_LINE_NUM; outer++){for(inner = 0; inner < PER_LINE_NUM; inner ++){buffer[outer + inner * PER_LINE_NUM] = outer;}}printf("tick2 = %d\n", GetTickCount() - count);    free(buffer);}int main(int argc, char* argv[]){test();return 1;}

缓存的示例比较简单一些。我们分别对一个buffer,按照行优先、列优先的顺序分别进行赋值。通过实验,我们发现行优先的数据访问模式在时间的花费上更少。其实这也没有什么奇怪的,cpu对数据的访问是按照缓存、内存的顺序逐步进行访问的。因为进行行访问时,数据有很大一部分是在cache中的,而列访问时,cpu需要不停更新自己的cache,因此时间就这么浪费了,就是这么简单。 
 
 (2)多核缓存同步

 #include <stdio.h>#include <windows.h>struct {int a;char p[64];int b;}data;DWORD WINAPI test1(LPVOID param){int value;int index;SetThreadAffinityMask(GetCurrentThread(), 1);  value = GetTickCount();for(index =0 ; index < 1000000000; index ++){data.a++;}printf("tick1 = %d\n", GetTickCount() - value);return 1;}DWORD WINAPI test2(LPVOID param){int value;int index;SetThreadAffinityMask(GetCurrentThread(), 2);  value = GetTickCount();for(index =0 ; index < 1000000000; index ++){data.b++;}printf("tick2 = %d\n", GetTickCount() - value);return 1;}int main(int argc, char* argv[]){CreateThread(NULL, 0, test1, NULL, 0, NULL);CreateThread(NULL, 0, test2, NULL, 0, NULL);while(1) Sleep(2);return 1;}

这是一个非常好玩的测试用例。我们起了两个线程,分别绑定到不同的cpu上运行。当我们对p[64]进行注释的时候,我们发现cpu需要花费较多的时间,而如果没有注释,我们发现cpu花费的时间要少得多。这就非常奇怪了。一个是对数据a进行处理、一个是对数据b进行处理,两者之间应该没有什么影响才对。关键问题就处在缓存上面。我们知道,一般cache line为64,如果数据的范围在64之内,那么cache需要在不同的cpu之间进行同步处理,而添加p[64]之后则没有这个烦恼了,此时两个cpu的cache肯定是不一样的,所以在更新一个cpu的cache的时候,不需要同步更新另外一个cpu的cache了,时间就节省下来了。
 
  (3)cpu预测

  #include <stdio.h>#include <malloc.h>#include <windows.h>typedef int (*DataCompareFunc)(void*, void*);#define BUFFER_SIZE 10000int simple_int_compare(void* a, void* b){int left = (int) a;int right = (int) b;if(left > right)return 1;else if(left == right)return 0;elsereturn -1;}void quick_sort_impl(void** array, int left, int right, DataCompareFunc cmp){int save_left  = left;int save_right = right;void* x = array[left];while(left < right){while(cmp(array[right], x) >= 0 && left < right) right--;if(left != right){array[left] = array[right];left++;}while(cmp(array[left], x) <= 0 && left < right) left++;if(left != right){array[right] = array[left];right--;}}array[left] = x;if(save_left < left){quick_sort_impl(array, save_left, left-1, cmp);}if(save_right > left){quick_sort_impl(array, left+1, save_right, cmp);}return;}void quick_sort(void** array, size_t nr, DataCompareFunc cmp){if(nr > 1){quick_sort_impl(array, 0, nr - 1, cmp);}}void print(int array[], int size){int index;for(index = 0; index < size; index++){printf("%d\n", array[index]);}}int main(int argc, char* argv[]){int* buffer= malloc(BUFFER_SIZE * sizeof(int));int index, loop, sum, value;if(NULL == buffer){return 1;}value = GetTickCount(), srand(0);for(index = 0; index < BUFFER_SIZE; index++){buffer[index] = rand() & 0xf;}quick_sort((void**)buffer, BUFFER_SIZE, simple_int_compare);sum = 0;for(loop = 0; loop < BUFFER_SIZE; loop++){for(index = 0; index < BUFFER_SIZE; index ++){if(buffer[index] > 5){sum += buffer[index];}}}free(buffer);printf("Elapse = %d\n", GetTickCount() - value);return 1;}

这是我觉得最不可思议的一个范例。我们本意的目的就是把buffer中的数据找出来,可是我们发现如果对数据进行sort处理,反而降低了整个运行时间。所以要说时间节省在什么地方了?那就只有一个答案,那就是cpu乱序执行了。在cpu运行的过程,预测和乱序执行是一直存在的,我们对数据处理的时候常常会默认提前运行一些指令,而如果数据本身就是有序的,那么所有的预测都是ok的,速度本身就可以起来了,所有的判断基本上都是准确的。反之,如果本身数据无序,那么我们的预测其实是无意义的,因为一切的结果其实是随机的,所以即使cpu乱序执行了一些指令,很有可能会失败,所以提前运行的指令完全没有意义,整个运行速度也就自然而然降下来了,不知道我说清楚了没?

随想录(cpu缓存、cache同步和乱序执行)相关推荐

  1. 从Java视角理解CPU缓存(CPU Cache)

    http://coderplay.iteye.com/blog/1485760 众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存 ...

  2. CPU Cache Line:CPU缓存行/缓存块

    <CPU Cache Line伪共享问题的总结和分析> 以下文章来源于小林coding ,作者小林coding Table of Contents CPU Cache 有多快? CPU C ...

  3. 计算机的二级Cache的性能,电脑运行慢,发卡,检查一下CPU二级缓存-Cache是否打开了...

    电脑运行慢,发卡,检查一下CPU二级缓存-Cache是否打开了 (2011-07-31 23:31:59) 标签: 杂谈 转自 http://zhidao.baidu.com/question/138 ...

  4. CPU缓存和内存屏障

    CPU性能优化手段-缓存 为了提高程序运行的性能,现代CPU在很多方面对程序进行了优化. 例如:CPU高速缓存.尽可能地避免处理器访问主内存的时间开销,处理器大多会利用缓存(cache)以提高性能. ...

  5. JVM——CPU缓存架构与Java 内存模型

    导航 一.CPU缓存架构与一致性协议 1.1 CPU缓存架构 1.2 缓存行与伪共享问题 1.3 MESI 缓存一致性协议 1.4 伪共享的解决办法 二.JMM Java 内存模型 2.1 JMM 简 ...

  6. 10 张图打开 CPU 缓存一致性的大门

    前言 直接上,不多 BB 了. 正文 CPU Cache 的数据写入 随着时间的推移,CPU 和内存的访问性能相差越来越大,于是就在 CPU 内部嵌入了 CPU Cache(高速缓存),CPU Cac ...

  7. 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  8. 计算机组成原理 — CPU — 缓存访问

    目录 文章目录 目录 CPU 缓存 CPU Cache 的运行原理 三级缓存(L1.L2.L3) L1 Cache L2 Cache L3 Cache CPU 缓存 CPU Cache(CPU 缓存) ...

  9. CPU缓存与CPU性能的关系

    说到CPU,不得不说的就是CPU缓存,目前CPU的缓存已经成了衡量CPU性能的一个必要指标,那么CPU缓存到底对CPU性能的影响有多大呢? 我们知道,CPU执行指令时,会将执行结果放在一个叫" ...

最新文章

  1. 如何配置三层交换机创建VLAN
  2. 皮一皮:精致的人生,哪怕拔火罐也要搭配衣服出门...
  3. Spring Cache抽象-使用Java类注解的方式整合EhCache
  4. zookeeper 运维
  5. 【ZT】详细设计文档规范
  6. forward_list容器
  7. 解决w3wp.exe内存占用问题[转载]
  8. java toolkit invoker_关于invokeInitFramework 方法未实现的问题
  9. bootstrap 4 pull-right无效
  10. c语言程序计算4阶行列式的值,如何用降阶法求解四阶行列式的计算,请帮我编一个C语言程序。...
  11. 金融数据分析之公司年报会计师事务所信息批量提取
  12. java解析excelpoi_Java解析Excel之POI(一)
  13. 计算机网络调试套什么定额,第一章计算机网络系统设备安装工程定额.docx
  14. HTML5的文档声明
  15. java单链表中temp=temp.next的理解
  16. 富文本TinyMCE
  17. 爬虫学习——初步了解爬虫
  18. nb_samples(采样数)转换
  19. 从零开始Android游戏编程(第二版) 第一版前言
  20. 【有利可图网】配色攻略-红色篇

热门文章

  1. iOS之CATiledLayer的属性简介和使用
  2. 关于函数式编程的思考(1)
  3. CAS 4.1.x 单点登出(退出登录)的原理解析
  4. 由SQL数据库转换Redis的实例
  5. Jedis连接池的使用
  6. 框架会使程序员变笨吗?
  7. 静态库制作-混编(工程是oc为基础)
  8. MVC实战之排球计分(六)—— 使用EF框架,创建Controller,生成数据库。
  9. 通过驱动向Excle中写入数据
  10. 软考信息系统项目管理师_项目进度管理2---软考高级之信息系统项目管理师014