当前位置:首页 » 编程软件 » 多核编程c

多核编程c

发布时间: 2023-05-18 05:15:48

1. 为什么在多核多线程程序中要慎用volatile关键字

a. 避免用通用寄存器对内存读写的优化。编译器常做的一种优化就是:把常用变量的频繁读写弄到通用寄存器中,最后不用的时候再存回内存中。但是如果某个内存地址中的值是由片外决定的(例如另一个线程或是另一个设备可能更改它),那就需要volatile关键字了。(感谢Kenny老师指正)
b.硬件寄存器可能被其他设备改变的情况。例如一个嵌入式板子上的某个寄存器直接与一个测试仪器连在一起,这样在这个寄存器的值随时可能被那个测试仪器更改。在这种情况下如果把该值设为volatile属性的,那么编译器就会每次都直接从内存中去取这个值的最新值,而不是自作聪明的把这个值保留在缓存中而导致读不到最新的那个被其他设备写入的新值。
c. 同一个物理内存地址M有两个不同的内存地址的情况。例如两个程序同时对同一个物理地址进行读写,那么编译器就不能假设这个地址只会有一个程序访问而做缓存优化,所以程序员在这种情况下也需要把它定义为volatile的。

2. 学C语言现在最好用的编程软件

Turbo C就可以的。编辑文本的时候可以用utraledit
至于vc++之类的我是不推荐初学者使用的

3. 想学编程,需要拥有什么样的条件

以下摘自《程序员的十层楼》
自西方文艺复兴以来,中国在自然科学方面落后西方很多,软件领域也不例外。当然现在中国的许多程序员们对此可能有许多不同的意见,有些人认为中国的程序员水平远落后于西方,有些则认为中国的程序员个人能力并不比西方的程序员差,只是整个软件产业落后而已。那么,到底中国的程序员水平比西方程序员水平差,还是中国有许多优秀的程序员达到或超过了西方程序员同等水平呢?要解决这个问题,必须先知道程序员 有多少种技术层级,每个层级需要什么样的技术水平,然后再比较中国和西方在各个技术层级的人数,就可以知道到底有没有差距,差距有多大。
当然,对于如何划分程序员的技术层级,不同公司或不同人会有不同的划分标准,下面的划分仅代表个人的观点,如有不当之处,还请砸板砖予以纠正。
第1层 菜鸟第1层楼属于地板层,迈进这层楼的门槛是很低的。基本上懂计算机的基本操作,了解计算机专业的一些基础知识,掌握一门基本的编程语言如C/C++,或者Java,或者JavaScript,...,均可入门迈进这层。
在这层上,中国有着绝对的优势,除了从计算机专业毕业的众多人数外,还有大量的通信、自动化、数学等相关专业的人士进入这一行,此外还有众多的其他专业转行的人士,人数绝对比西方多出甚多。并且还有一个优势就是我们这层人员的平均智商比西方肯定高。
没有多少人愿意一辈子做菜鸟,因为做"菜鸟"的滋味实在是不咋的,整天被老大们吆喝着去装装机器,搭建一下测试环境,或者对照着别人写好的测试用例 做一些黑盒测试,好一点的可以被安排去写一点测试代码。当然如果运气"好"的话,碰到了国内的一些作坊式的公司,也有机会去写一些正式的代码。
所以,菜鸟们总是在努力学习,希望爬更高的一层楼去。
第2层 大虾从第1层爬到第2层相对容易一些,以C/C++程序员为例,只要熟练掌握C/C++编程语言,掌握C标准库和常用的各种数据结构算法,掌握STL的 基本实现和使用方法,掌握多线程编程基础知识,掌握一种开发环境,再对各种操作系统的API都去使用一下,搞网络编程的当然对socket编程要好好掌握 一下,然后再学习一些面向对象的设计知识和设计模式等,学习一些测试、软件工程和质量控制的基本知识,大部分人经过2~3年的努力,都可以爬到第2层,晋 升为"大虾"。
中国的"大虾"数量和"菜鸟"数量估计不会少多少,所以这层上仍然远领先于西方。
大虾们通常还是有些自知之明,知道自己只能实现一些简单的功能,做不了大的东西,有时候还会遇到一些疑难问题给卡住,所以他们对那些大牛级的人物通 常是非常崇拜的,国外的如Robert C. Martin、Linus Torvalds,国内的如求伯君、王志东等通常是他们崇拜的对象。其中的有些人希望有一天也能达到这些大牛级人物的水平,所以他们继续往楼上爬去。
第3层 牛人由于"大虾"们经常被一些疑难问题给卡住,所以有了"大虾"们只好继续学习,他们需要将原来所学的知识进一步熟练掌握,比如以熟练掌握C++编程语 言为例,除了学一些基础性的C++书籍如《C++ Primer》,《Effective C++》,《Think in C++》,《Exception C++》等之外,更重要的是需要了解C++编译器的原理和实现机制,了解操作系统中的内部机制如内存管理、进程和线程的管理机制,了解处理器的基础知识和 代码优化的方法,此外还需要更深入地学习更多的数据结构与算法,掌握更深入的测试和调试知识以及质量管理和控制方法,对各种设计方法有更好的理解等。
学习上面说的这些知识不是一挥而就的,不看个三五十本书并掌握它是做不到的。以数据结构算法来说,至少要看个5~10本这方面的着作;以软件设计来 说,光懂结构化设计、面向对象设计和一些设计模式是不够的,还要了解软件架构设计、交互设计、面向方面的设计、面向使用的设计、面向数据结构算法的设计、 情感化设计等,否则是很难进到这个楼层的。
当然除了上面说的知识外,大虾们还需要去学习各种经验和技巧。当然这点难不倒他们,现在出版的书籍众多,网络上的技术文章更是不胜数,然后再去各种 专业论坛里泡一泡,把这些书籍和文章中的各种经验、技能、技巧掌握下来,再去学习一些知名的开源项目如Apache或linux操作系统的源代码实现等。 此时对付一般的疑难问题通常都不在话下,菜鸟和大虾们会觉得你很"牛",你也就爬到了第3层,晋升为"牛人"了。
看了上面所讲的要求,可能有些大虾要晕过去了,成为牛人要学这么多东西啊!要求是不是太高了?其实要求一点也不高,这么点东西都掌握不了的话,怎么能让别人觉得你"牛"呢?

需要提一下的是,进入多核时代后,从第2层爬到第3层增加了一道多核编程的门槛。当然要迈过这道门槛并不难,已经有很多前辈高人迈进了这道门槛,只要循着他们的足迹前进就可以了。想迈进这道门槛者不妨去学习一下TBB开源项目的源代码(链接:http://www.threadingbuildingblocks.org/),然后上Intel的博客(http://softwareblogs-zho.intel.com/)和多核论坛(http://forum.csdn.net/Intel/IntelMulti-core/)去看看相关文章,再买上几本相关的书籍学习一下。

在国内, 一旦成为"牛人",通常可以到许多知名的公司里去,运气好者可以挂上一个架构师的头衔,甚至挂上一个"首席架构师"或者"首席xx学家"的头衔也不足为 奇。有不少爬到这层的人就以为到了楼顶了,可以眼睛往天上看了,开始目空一切起来,以为自己什么都可以做了,什么都懂了,经常在网络上乱砸板砖是这个群体 的最好写照。由此也看出,国内的牛人数量仍然众多,远多于西方的牛人数量,在这层上仍然是领先的。
也有不少谦虚的"牛人",知道自己现在还不到半桶水阶段。他们深知爬楼的游戏就像猴子上树一样,往下看是笑脸,往上看是屁股。为了多看笑脸,少看屁股,他们并没有在此停步不前,而是继续寻找到更上一层的楼梯,以便继续往上爬。
第4层 大牛从第3层爬到第4层可不像上面说过的那几层一样容易,要成为大牛的话,你必须要能做牛人们做不了的事情,解决牛人们解决不了问题。比如牛人们通常都 不懂写操作系统,不会写编译器,不懂得TCP/IP协议的底层实现,如果你有能力将其中的任何一个实现得象模象样的话,那么你就从牛人升级为"大牛"了。
当然,由于各个专业领域的差别,这里举操作系统、编译器、TCP/IP协议只是作为例子,并不代表成为"大牛"一定需要掌握这些知识,以时下热门的 多核编程来说,如果你能比牛人们更深入地掌握其中的各种思想原理,能更加自如的运用,并有能力去实现一个象开源项目TBB库一样的东西,也可以成为"大 牛",又或者你能写出一个类似Apache一样的服务器,或者写出一个数据库,都可以成为"大牛"。
要成为"大牛"并不是一件简单的事情,需要付出比牛人们多得多的努力,一般来说,至少要看过200~400本左右的专业书籍并好好掌握它,除此之外,还得经常关注网络和期刊杂志上的各种最新信息。
当"牛人"晋升为"大牛",让"牛人们"发现有比他们更牛的人时,对"牛人"们的心灵的震撼是可想而知的。由于牛人们的数量庞大,并且牛人对大虾和 菜鸟阶层有言传身教的影响,所以大牛们通常能获得非常高的社会知名度,几乎可以用"引无数菜鸟、大虾、牛人竞折腰"来形容,看看前面提过的Linus Torvalds等大牛,应该知道此言不虚。
虽然成为"大牛"的条件看起来似乎很高似的,但是这层楼并不是很难爬的一层,只要通过一定的努力,素质不是很差,还是有许多"牛人"可以爬到这一层的。由此可知,"大牛"这个楼层的人数其实并不像想象的那么少,例如比尔·盖茨之类的人好像也是属于这一层的。
由于"大牛"这层的人数不少,所以也很难统计除到底是中国的"大牛"数量多还是西方的大牛数量多?我估计应该是个旗鼓相当的数量,或者中国的"大牛"们会更多一些。
看到这里,可能会有很多人会以为我在这里说瞎话,Linus Torvalds写出了着名的Linux操作系统,我国并没有人写出过类似的东西啊,我国的"大牛"怎么能和西方的比呢? 不知大家注意到没有,Linus Torvalds只是写出了一个"象模象样"的操作系统雏形,Linux后来真正发展成闻名全球的开源操作系统期间,完全是因为许多支持开源的商业公司如 IBM等,派出了许多比Linus Torvalds更高楼层的幕后英雄在里面把它开发出来的。
可能有些菜鸟认为Linus Torvalds是程序员中的上帝,不妨说个小故事:
Linus,Richard Stallman和Don Knuth(高德纳)一同参加一个会议。
Linus 说:"上帝说我创造了世界上最优秀的操作系统。"
Richard Stallman自然不甘示弱地说:"上帝说我创造了世界上最好用的编译器。"
Don Knuth一脸疑惑的说:"等等,等等,我什么时候说过这些话?"
由此可以看出,Linus Torvalds的技术水平并不像想象中那么高,只是"牛人"和"大虾"觉得"大牛"比他们更牛吧了。在我国,有一些当时还处于"大虾"层的人物,也能写 出介绍如何写操作系统的书,并且书写得非常出色,而且写出了一个有那么一点点象模象样的操作系统来。我想中国的"大牛"们是不会比西方差的,之所以没有人 写出类似的商业产品来,完全是社会环境的原因,并不是技术能力达不到的原因。
"大牛"们之所以成为大牛,主要的原因是因为把"牛人"给盖了下去,并不是他们自己觉得如何牛。也许有很多菜鸟、大虾甚至牛人觉得"大牛"这层已经 到顶了,但大多数"大牛"估计应该是有自知之明的,他们知道自己现在还没有爬到半山腰,也就勉强能算个半桶水的水平,其中有些爬到这层没有累趴下,仍然能 量充沛,并且又有志者,还是会继续往更上一层楼爬的。
看到这里,也许有些菜鸟、大虾、牛人想不明白了,还有比"大牛"们更高的楼层,那会是什么样的楼层?下面就来看看第5层楼的奥妙。
第5层 专家当大牛们真正动手做一个操作系统或者类似的其他软件时,他们就会发现自己的基本功仍然有很多的不足。以内存管理为例,如果直接抄袭Linux或者其 他开源操作系统的内存管理算法,会被人看不起的,如果自动动手实现一个内存管理算法,他会发现现在有关内存管理方法的算法数量众多,自己并没有全部学过和 实践过,不知道到底该用那种内存管理算法。
看到这里,可能有些人已经明白第5层楼的奥妙了,那就是需要做基础研究,当然在计算机里,最重要的就是"计算"二字,程序员要做基础研究,主要的内容就是研究非数值"计算"。
非数值计算可是一个非常庞大的领域,不仅时下热门的"多核计算"与"云计算"属于非数值计算范畴,就是软件需求、设计、测试、调试、评估、质量控 制、软件工程等本质上也属于非数值计算的范畴,甚至芯片硬件设计也同样牵涉到非数值计算。如果你还没有真正领悟"计算"二字的含义,那么你就没有机会进到 这层楼来。
可能有人仍然没有明白为什么比尔·盖茨被划在了大牛层,没有进到这层来。虽然比尔·盖茨大学未毕业,学历不够,但是家有藏书2万余册,进入软件这个 行业比绝大部分人都早,撇开他的商业才能不谈,即使只看他的技术水平,也可以算得上是学富五车,顶上几个普通的计算机软件博士之和是没有问题的,比起 Linus Torvalds之类的"大牛"们应该技高一筹才对,怎么还进不了这层楼呢?
非常遗憾的是,从Windows操作系统的实现来看,其对计算的理解是很肤浅的,如果把Google对计算方面的理解比做大学生,比尔·盖茨只能算做一个初中生,所以比尔·盖茨永远只能做个大牛人,成不了"专家"。
看到这里,也许国内的大牛们要高兴起来了,原来比尔·盖茨也只和我等在同一个层次,只要再升一层就可以超越比尔·盖茨了。不过爬到这层可没有从"牛 人"升为"大牛"那么简单,人家比尔·盖茨都家有2万多册书,让你看个500~1000本以上的专业书籍并掌握好它应该要求不高吧。当然,这并不是主要的 条件,更重要的是,需要到专业的学术站点去学习了,到ACM,IEEE,Elsevier,SpringerLink,SIAM等地方去下载论文应该成为 你的定期功课,使用Google搜索引擎中的学术搜索更是应该成为你的日常必修课。此外,你还得经常关注是否有与你研究相关的开源项目冒出来,例如当听到 有TBB这样针对多核的开源项目时,你应该第一时间到Google里输入"TBB"搜索一下,将其源代码下载下来好好研究一番,这样也许你的一只脚已经快 迈进了这层楼的门槛。
当你象我上面说的那样去做了以后,随着时间的推移,总会有某天,你发现,在很多小的领域里,你已经学不到什么新东西了,所有最新出来的研究成果你几 乎都知道。此时你会发现你比在做"牛人"和"大牛"时的水平不知高出了多少,但是你一点也"牛"不起来,因为你学的知识和思想都是别人提出来的,你自己并 没有多少自己的知识和思想分享给别人,所以你还得继续往楼上爬才行。
我不知道国内的"专家"到底有多少,不过有一点可以肯定的是,如果把那些专门蒙大家的"砖家"也算上的话,我们的砖家比西方的要多得多。
第6层 学者
当"专家"们想继续往上一层楼爬时,他们几乎一眼就可以看到楼梯的入口,不过令他们吃惊的是,楼梯入口处竖了一道高高的门槛,上面写着"创新"二字。不幸的是,大多数人在爬到第5层楼时已经体能消耗过度,无力翻过这道门槛。
有少数体能充足者,可以轻易翻越这道门槛,但是并不意味着体力消耗过度者就无法翻越,因为你只是暂时还没有掌握恢复体能的方法而已,当掌握了恢复体能的方法,将体能恢复后,你就可以轻易地翻越这道门槛了。
怎么才能将体能恢复呢?我们的老祖宗"孔子"早就教导过我们"温故而知新",在英文里,研究的单词是"research",其前缀"re" 和"search"分别是什么意思不用我解释吧。或许有些人觉得"温故而知新"和"research"有些抽象,不好理解,我再给打个简单的比方,比如你 在爬一座高山,爬了半天,中途体力不支,怎么恢复体力呢?自然是休息一下,重新进食一些食物,体力很快就可以得到恢复。
由此可知,对体能消耗过度者,休息+重新进食通常是恢复体能的最佳选择。可惜的是,国内的老板们并不懂得这点,他们的公司里不仅连正常国家规定的休 息时间都不给足,有些公司甚至有员工"过劳死"出现。所以国内能翻越"创新"这道门槛的人是"少之又少",和西方比起来估计是数量级的差别。
再说说重新进食的问题,这个重新进食是有讲究的,需要进食一些基础性易消化的简单食物,不能进食山珍海味级的复杂食物,否则很难快速吸收。以查找为 例,并不是去天天盯着那些复杂的查找结构和算法进行研究,你需要做的是将二分查找、哈希查找、普通二叉树查找等基础性的知识好好地复习几遍。
以哈希查找为例,首先你需要去将各种冲突解决方法如链式结构、二次哈希等编写一遍,再试试不同种类的哈希函数,然后还需要试试在硬盘中如何实现哈希 查找,并考虑数据从硬盘读到内存后,如何组织硬盘中的数据才能快速地在内存中构建出哈希表来,...,这样你可能需要将一个哈希表写上十几个不同的版本, 并比较各个版本的性能、功能方面的区别和适用范围。
总之,对任何一种简单的东西,你需要考虑各种各样的需求,以需求来驱动研究。最后你将各种最基础性的查找结构和算法都了然于胸后,或许某天你再看其他更复杂的查找算法,或者你在散步时,脑袋里灵光一现,突然间就发现了更好的方法,也就从专家晋升为"学者"了。
学者所做的事情,通常都是在前人的基础上,进行一些小的优化和改进,例如别人发明了链式基数排序的方法,你第1个发现使用一定的方法,可以用数组替代链表进行基数排序,性能还能得到进一步提高。
由于学者需要的只是一些小的优化改进,因此中国还是有一定数量的学者。不过和国外的数量比起来,估计少了一个数量级而已。
也许有人会觉得现在中国许多公司申请专利的数量达到甚至超过西方发达国家了,我们的学者数量应该不会比他们少多少。因此,有必要把专利和这里说的创新的区别解释一下。
所谓专利者,只要是以前没有的,新的东西,都可以申请专利;甚至是以前有的东西,你把他用到了一个新的领域的产品里去,也可以申请专利。比如你在房 子里造一个水泥柱子,只要以前没有人就这件事申请专利,那么你就可以申请专利,并且下次你把水泥柱子挪一个位置,又可以申请一个新的专利;或者你在一个柜 子上打上几个孔,下次又把孔的位置改一改,...,均可申请专利。
这层楼里所说的创新,是指学术层面的创新,是基础研究方面的创新,和专利的概念是完全不同的,难度也是完全不同的。你即使申请了一万个象那种打孔一类的专利,加起来也够不到这层楼里的一个创新。
当你爬到第6层楼时,你也许会有一种突破极限的快感,因为你终于把那道高高的写着"创新"二字的门槛给翻过去了,实现了"0"的突破。这时,你也许 有一种"独上高楼,欲望尽天涯路"的感觉,但是很快你会发现看到的都是比较近的路,远处的路根本看不清楚。如果你还有足够的体力的话,你会想爬到更高一层 的楼层去。
第7层 大师
从第6层楼爬到第7层楼,并没有多少捷径可走,主要看你有没有足够的能量。你如果能象Hoare一样设计出一个快速排序的算法;或者象Eugene W. Myers一样设计出了一个用编辑图的最短路径模型来解决diff问题的算法;或者象M.J.D. Powell一样提出了一个能够处理非线性规划问题的SQP方法;或者你发现基于比较的排序算法,它的复杂度下界为O(NLogN);或者你发现用栈可以 将递归的算法变成非递归的;或者你设计出一个红黑树或者AVL树之类的查找结构;或者你设计出一个象C++或Java一样的语言;或者你发明了 UML;...,你就爬到了第7层,晋升为"大师"了。
上面举的这些例子中,其中有些人站的楼层比这层高,这里只是为了形象说明而举例他们的某个成就。从上面列出的一些大师的贡献可以看出,成为大师必须 要有较大的贡献。首先解决问题必须是比较重要的,其次你要比前辈们在某方面有一个较大的提高,或者你解决的是一个全新的以前没有解决过的问题;最重要的 是,主要的思路和方法必须是你自己提供的,不再是在别人的思路基础上进行的优化和改进。
看了上面这些要求,如果能量不够的话,你也许会觉得有些困难,所以不是每个人都能成为"大师"的。中国软件业里能称得上是"大师"的人,用屈指可数来形容,估计是绰绰有余。值得一提得是,国外的"大师"就象我们的"大牛"一样满天飞的多。
我把我猜测本国有可能进到这层楼的大师列一下,以起个抛砖引玉的作用。汉王的"手写识别"技术由于是完全保密的,不知道它里面用了什么思想,原创思 想占的比重有多少,因此不知道该把它划到这层楼还是更高一层楼去。原山东大学王小云教授破解DES和MD5算法时,用到的方法不知道是不是完全原创的,如 果是的话也可进到这层楼来。
陈景润虽然没有彻底解决哥德巴赫猜想,但他在解决问题时所用的方法是创新的,因此也可以进到这层楼来。当然,如果能彻底解决哥德巴赫猜想,那么可以算到更高的楼层去。
求伯君和王志东等大牛们,他们在做WPS和表格处理之类的软件时,不知是否有较大的原创算法在里面,如果有的话就算我错把他们划到了大牛层。由于所 学有限,不知道国内还有那些人能够得上"大师"的级别,或许有少量做研究的教授、院士们,可以达到这个级别,有知道的不妨回个帖子晾一晾。
鉴于"大师"这个称号的光环效应,相信有不少人梦想着成为"大师"。或许你看了前面举的一些大师的例子,你会觉得要成为大师非常困难。不妨说一下,现在有一条通往"大师"之路的捷径打开了,那就是多核计算领域,有大量的处女地等待大家去挖掘。
以前在单核时代开发的各种算法,现在都需要改写成并行的。数据结构与算法、图像处理、数值计算、操作系统、编译器、测试调试等各个领域,都存在大量的机会,可以让你进到这层楼来,甚至有可能让你进到更高一层楼去。
第8层 科学家

科学家向来都是一个神圣的称号,因此我把他放在了“大师”之上。要成为科学家,你的贡献必须超越大师,不妨随便举一些例子。

如果你象Dijkstra一样设计了ALGOL语言,提出了程序设计的三种基本结构:顺序、选择、循环,那么你可以爬到第8层楼来。顺便说一下,即使抛开这个成果,Dijkstra凭他的PV操作和信号量概念的提出,同样可以进到这层楼。

如果你象Don Knuth一样,是数据结构与算法这门学科的重要奠基者,你也可以进到这层楼来。当然,数据结构和算法这门学科不是某个人开创的,是许多大师和科学家集体开创的。

如果你象巴科斯一样发明了Fortran语言,并提出了巴科斯范式,对高级程序语言的发展起了重要作用,你也可以进到这层楼来。

或者你象Ken Thompson、Dennis Ritchie一样发明了Unix操作系统和功能强大、高效、灵活、表达力强的C语言,对操作系统理论和高级编程语言均作出重大贡献,那么你也可以进到这层楼来。

或者你有Frederick P. Brooks一样机会,可以去领导开发IBM的大型计算机System/360和OS/360操作系统,并在失败后反思总结,写出《人月神话》,对软件工程作出里程碑式的贡献,你也可以进到这层来。

或者你提出了面向对象设计的基本思想,或者你设计了互联网的TCP/IP协议,或者你象Steven A.Cook一样奠定NP完全性的理论基础,或者你象Frances Allen一样专注于并行计算来实现编译技术,在编译优化理论和技术取得基础性的成就,…,均可进入这层。

当然,如果你发明了C++语言或者Java语言,你进不到这层来,因为你用到的主要思想都是这层楼中的科学家提出的,你自己并没有没有多少原创思想在里面。

看了上面列出的科学家的成就,你会发现,要成为“科学家”,通常要开创一门分支学科,或者是这个分支学科的奠基者,或者在某个分支学科里作出里程碑式的重大贡献。如果做不到这些的话,那么你能象Andrew C. Yao(姚期智)一样在对计算理论的多个方向如伪随机数生成,密码学与通信复杂度等各个方向上作出重要贡献,成为集大成者,也可以进入这层楼。

成为“科学家”后,如果你有幸象Dijkstra一样,出现在一个非常重视科学的国度。当你去世时,你家乡满城的人都会自动地去为你送葬。不过如果不幸生错地方的话,能不挨“板砖”估计就算万幸了。

从上面随便举的一些例子中,你可能能猜到,西方科学家的数量是非常多的,于是你会想中国应该也有少量的科学家吧?我可以很负责任地告诉你一个不幸的结果,中国本土产生的科学家的数量为0。目前在国内,软件领域的唯一的科学家就是上面提过的姚期智,还是国外请回来的,并不是本土产生的。

可能你不同意我说的本土科学家数量为0的结论,因为你经常看到有许多公司里都有所谓“首席XX科学家”的头衔。我想说的是,这些所谓的“首席XX科学家”都是远远够不到这层楼的级别的,有些人的水平估计也就是一个“牛人”或“大牛”的级别,好一点的最多也就一个“学者”的级别。尤其是那些被称作“首席经X学家”的,基本上可以把称号改为“首席坑大家”。

虽然我国没有人能爬到这层楼上来,但是西方国家仍然有许多人爬到了比这层更高的楼上。如果要问我们比西方落后多少?那么可以简单地回答为:“落后了三层楼”。下面就来看看我们做梦都没有到过的更高一层楼的秘密。

第9层 大科学家

进入这层楼的门槛通常需要一些运气,比如某天有个苹果砸到你头上时,你碰巧发现了万有引力,那么你可以进到这层楼来。当然,万有引力几百年前就被人发现了,如果你现在到处嚷嚷着说你发现了万有引力,恐怕马上会有人打110,然后警察会把你送到不正常人类的聚集地去。因此,这里举万有引力的例子,只是说你要有类似的成就才能进到这层楼来。

牛顿发现万有引力定律开创 了经典物理运动力学这门学科,如果你也能开创一门大的学科,那么你就从科学家晋升为“大科学家”。比如爱因斯坦创建了相对论,从一个小职员变成了大科学 家。当然大科学家可远不止这两人,数学界里比物理学界更是多得多,如欧几里得创建了平面几何,笛卡尔开创解析几何,还有欧拉、高斯、莱布尼茨等数不清的人 物,跟计算相关的大科学家则有图灵等人。

从上面列出的一些大科学家 可以发现,他们的成就不仅是开创了一个大的学科,更重要的是他们的成就上升到了“公理”的层面。发现公理通常是需要一点运气的,如果你的运气不够好的话, 另外还有一个笨办法也可以进到这层楼来,那就是成为集大成者。例如冯·诺伊曼,对数学的所有分支都非常了解,许多领域都有较大的贡献,即使撇开他对计算机 的开创贡献,成为大科学家照样绰绰有余。

当然,程序员们最关心的是 自己有没有机会变成大科学家。既然计算机这门大学科的开创性成果早就被冯·诺伊曼、图灵等人摘走了,那么程序员们是不是没有机会变成大科学家了呢?我们的 古人说得好:“江山代有才人出,各领风骚数百年”,现在在计算机这门学科下面诞生了许多非常重要的大的分支,所以你还是有足够的机会进到这层楼的。

如果你能够彻底解决自然语言理解(机器翻译)这门学科中的核心问题, 或者你在人工智能或者机器视觉(图像识别)方面有突破性的发现,那么你同样可以轻易地晋升为“大科学家”。这样当某天你老了去世时,或许那天国人已经觉醒,你也能享受到如Dijkstra一样的待遇,有满城甚至全国的人去为你送葬。

4. C语言中的MPI编程和多线程有什么区别,MPI编程中针对的是一台电脑多核还是多台电脑谢谢!

MPI(MPI是一个标准,有不同的具体实现,比如MPICH等)是多主机联网协作进行并行计算的工具,当然也可以用于单主机上多核/多CPU的并行计算,不过效率低。它能协调多台主机间的并行计算,因此并行规模上的可伸缩性很强,能在从个人电脑到世界TOP10的超级计算机上使用。缺点是使用进程间通信的方式协调并行计算,这导致并行效率较低、内存开销大、不直观、编程麻烦。OpenMP是针对单主机上多核/多CPU并行计算而设计的工具,换句话说,OpenMP更适合单台计算机共享内存结构上的并行计算。由于使用线程间共享内存的方式协调并行计算,它在多核/多CPU结构上的效率很高、内存开销小、编程语句简洁直观,因此编程容易、编译器实现也容易(现在最新版的C、C++、Fortran编译器基本上都内置OpenMP支持)。不过OpenMP最大的缺点是只能在单台主机上工作,不能用于多台主机间的并行计算!如果要多主机联网使用OpenMP(比如在超级计算机上),那必须有额外的工具帮助,比如MPI+OpenMP混合编程。或者是将多主机虚拟成一个共享内存环境(Intel有这样的平台),但这么做效率还不如混合编程,唯一的好处是编程人员可以不必额外学习MPI编程。

5. python多线程对多核的利用

GIL 与 Python 线程的纠葛
GIL 是什么东西?它对我们的 python 程序会产生什么样的影响?我们先来看一个问题。运行下面这段 python 程序,CPU 占用率是多少?
# 请勿在工作中模仿,危险:)
def dead_loop():
while True:
pass

dead_loop()

答案是什么呢,占用 100% CPU?那是单核!还得是没有超线程的古董 CPU。在我的双核 CPU 上,这个死循环只会吃掉我一个核的工作负荷,也就是只占用 50% CPU。那如何能让它在双核机器上占用 100% 的 CPU 呢?答案很容易想到,用两个线程就行了,线程不正是并发分享 CPU 运算资源的吗。可惜答案虽然对了,但做起来可没那么简单。下面的程序在主线程之外又起了一个死循环的线程
import threading

def dead_loop():
while True:
pass

# 新起一个死循环线程
t = threading.Thread(target=dead_loop)
t.start()

# 主线程也进入死循环
dead_loop()

t.join()

按道理它应该能做到占用两个核的 CPU 资源,可是实际运行情况却是没有什么改变,还是只占了 50% CPU 不到。这又是为什么呢?难道 python 线程不是操作系统的原生线程?打开 system monitor 一探究竟,这个占了 50% 的 python 进程确实是有两个线程在跑。那这两个死循环的线程为何不能占满双核 CPU 资源呢?其实幕后的黑手就是 GIL。
GIL 的迷思:痛并快乐着
GIL 的全称为 Global Interpreter Lock ,意即全局解释器锁。在 Python 语言的主流实现 CPython 中,GIL 是一个货真价实的全局线程锁,在解释器解释执行任何 Python 代码时,都需要先获得这把锁才行,在遇到 I/O 操作时会释放这把锁。如果是纯计算的程序,没有 I/O 操作,解释器会每隔 100 次操作就释放这把锁,让别的线程有机会执行(这个次数可以通过sys.setcheckinterval 来调整)。所以虽然 CPython 的线程库直接封装操作系统的原生线程,但 CPython 进程做为一个整体,同一时间只会有一个获得了 GIL 的线程在跑,其它的线程都处于等待状态等着 GIL 的释放。这也就解释了我们上面的实验结果:虽然有两个死循环的线程,而且有两个物理 CPU 内核,但因为 GIL 的限制,两个线程只是做着分时切换,总的 CPU 占用率还略低于 50%。
看起来 python 很不给力啊。GIL 直接导致 CPython 不能利用物理多核的性能加速运算。那为什么会有这样的设计呢?我猜想应该还是历史遗留问题。多核 CPU 在 1990 年代还属于类科幻,Guido van Rossum 在创造 python 的时候,也想不到他的语言有一天会被用到很可能 1000+ 个核的 CPU 上面,一个全局锁搞定多线程安全在那个时代应该是最简单经济的设计了。简单而又能满足需求,那就是合适的设计(对设计来说,应该只有合适与否,而没有好与不好)。怪只怪硬件的发展实在太快了,摩尔定律给软件业的红利这么快就要到头了。短短 20 年不到,代码工人就不能指望仅仅靠升级 CPU 就能让老软件跑的更快了。在多核时代,编程的免费午餐没有了。如果程序不能用并发挤干每个核的运算性能,那就意谓着会被淘汰。对软件如此,对语言也是一样。那 Python 的对策呢?
Python 的应对很简单,以不变应万变。在最新的 python 3 中依然有 GIL。之所以不去掉,原因嘛,不外以下几点:
欲练神功,挥刀自宫:
CPython 的 GIL 本意是用来保护所有全局的解释器和环境状态变量的。如果去掉 GIL,就需要多个更细粒度的锁对解释器的众多全局状态进行保护。或者采用 Lock-Free 算法。无论哪一种,要做到多线程安全都会比单使用 GIL 一个锁要难的多。而且改动的对象还是有 20 年历史的 CPython 代码树,更不论有这么多第三方的扩展也在依赖 GIL。对 Python 社区来说,这不异于挥刀自宫,重新来过。
就算自宫,也未必成功:
有位牛人曾经做了一个验证用的 CPython,将 GIL 去掉,加入了更多的细粒度锁。但是经过实际的测试,对单线程程序来说,这个版本有很大的性能下降,只有在利用的物理 CPU 超过一定数目后,才会比 GIL 版本的性能好。这也难怪。单线程本来就不需要什么锁。单就锁管理本身来说,锁 GIL 这个粗粒度的锁肯定比管理众多细粒度的锁要快的多。而现在绝大部分的 python 程序都是单线程的。再者,从需求来说,使用 python 绝不是因为看中它的运算性能。就算能利用多核,它的性能也不可能和 C/C++ 比肩。费了大力气把 GIL 拿掉,反而让大部分的程序都变慢了,这不是南辕北辙吗。
难道 Python 这么优秀的语言真的仅仅因为改动困难和意义不大就放弃多核时代了吗?其实,不做改动最最重要的原因还在于:不用自宫,也一样能成功!
其它神功
那除了切掉 GIL 外,果然还有方法让 Python 在多核时代活的滋润?让我们回到本文最初的那个问题:如何能让这个死循环的 Python 脚本在双核机器上占用 100% 的 CPU?其实最简单的答案应该是:运行两个 python 死循环的程序!也就是说,用两个分别占满一个 CPU 内核的 python 进程来做到。确实,多进程也是利用多个 CPU 的好方法。只是进程间内存地址空间独立,互相协同通信要比多线程麻烦很多。有感于此,Python 在 2.6 里新引入了 multiprocessing这个多进程标准库,让多进程的 python 程序编写简化到类似多线程的程度,大大减轻了 GIL 带来的不能利用多核的尴尬。
这还只是一个方法,如果不想用多进程这样重量级的解决方案,还有个更彻底的方案,放弃 Python,改用 C/C++。当然,你也不用做的这么绝,只需要把关键部分用 C/C++ 写成 Python 扩展,其它部分还是用 Python 来写,让 Python 的归 Python,C 的归 C。一般计算密集性的程序都会用 C 代码编写并通过扩展的方式集成到 Python 脚本里(如 NumPy 模块)。在扩展里就完全可以用 C 创建原生线程,而且不用锁 GIL,充分利用 CPU 的计算资源了。不过,写 Python 扩展总是让人觉得很复杂。好在 Python 还有另一种与 C 模块进行互通的机制 : ctypes
利用 ctypes 绕过 GIL
ctypes 与 Python 扩展不同,它可以让 Python 直接调用任意的 C 动态库的导出函数。你所要做的只是用 ctypes 写些 python 代码即可。最酷的是,ctypes 会在调用 C 函数前释放 GIL。所以,我们可以通过 ctypes 和 C 动态库来让 python 充分利用物理内核的计算能力。让我们来实际验证一下,这次我们用 C 写一个死循环函数
extern"C"
{
void DeadLoop()
{
while (true);
}
}

用上面的 C 代码编译生成动态库 libdead_loop.so (Windows 上是 dead_loop.dll)
,接着就要利用 ctypes 来在 python 里 load 这个动态库,分别在主线程和新建线程里调用其中的 DeadLoop
from ctypes import *
from threading import Thread

lib = cdll.LoadLibrary("libdead_loop.so")
t = Thread(target=lib.DeadLoop)
t.start()

lib.DeadLoop()

这回再看看 system monitor,Python 解释器进程有两个线程在跑,而且双核 CPU 全被占满了,ctypes 确实很给力!需要提醒的是,GIL 是被 ctypes 在调用 C 函数前释放的。但是 Python 解释器还是会在执行任意一段 Python 代码时锁 GIL 的。如果你使用 Python 的代码做为 C 函数的 callback,那么只要 Python 的 callback 方法被执行时,GIL 还是会跳出来的。比如下面的例子:
extern"C"
{
typedef void Callback();
void Call(Callback* callback)
{
callback();
}
}

from ctypes import *
from threading import Thread

def dead_loop():
while True:
pass

lib = cdll.LoadLibrary("libcall.so")
Callback = CFUNCTYPE(None)
callback = Callback(dead_loop)

t = Thread(target=lib.Call, args=(callback,))
t.start()

lib.Call(callback)

注意这里与上个例子的不同之处,这次的死循环是发生在 Python 代码里 (DeadLoop 函数) 而 C 代码只是负责去调用这个 callback 而已。运行这个例子,你会发现 CPU 占用率还是只有 50% 不到。GIL 又起作用了。
其实,从上面的例子,我们还能看出 ctypes 的一个应用,那就是用 Python 写自动化测试用例,通过 ctypes 直接调用 C 模块的接口来对这个模块进行黑盒测试,哪怕是有关该模块 C 接口的多线程安全方面的测试,ctypes 也一样能做到。
结语
虽然 CPython 的线程库封装了操作系统的原生线程,但却因为 GIL 的存在导致多线程不能利用多个 CPU 内核的计算能力。好在现在 Python 有了易经筋(multiprocessing), 吸星大法(C 语言扩展机制)和独孤九剑(ctypes),足以应付多核时代的挑战,GIL 切还是不切已经不重要了,不是吗。

6. C++ openmp并行程序在多核linux上如何最大化使用cpu

openmp并行程序在多核linux上最大化使用cpu的方法如下:

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#include<time.h>

intmain()
{
longlongi;
longdoublesum=.0;
longdoublesec=.0;

//Multi-threadcomputestart
clock_tt1=clock();
#pragmaompparallelfor
for(i=0;i<1000000000;i++)
{
sum+=i/100;
}
clock_tt2=clock();

sec=(t2-t1);
//sec=(t2-t1);
printf("Programcosts%.2Lfclocktick. ",sec);
exit(EXIT_SUCCESS);
}

以上代码中,#pragma omp parallel for

这一行的作用即是调用openmp的功能,根据检测到的CPU核心数目,将for (i = 0; i < 1000000000; i++)这个循环执行过程平均分配给每一个CPU核心。

去掉#pragma omp parallel for这行,则和普通的串行代码效果一致。

注意,要使用openmp功能,在编译的时候需要加上-fopenmp编译参数。

以下是两种编译搭配两种代码出现的4种结果,可以很直观地看到效果:

1、代码里含有#pragma omp parallel for,编译参数有-fopenmp

Endys-MacBook-Pro:Desktop endy$ vi test.c

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test -fopenmp

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 50202611.00 clock tick.


2、代码里含有#pragma omp parallel for,编译参数没有-fopenmp

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 4068178.00 clock tick.


3、代码里没有#pragma omp parallel for,编译参数有-fopenmp

Endys-MacBook-Pro:Desktop endy$ vi test.c

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test -fopenmp

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 4090744.00 clock tick.


4、代码里没有#pragma omp parallel for,编译参数没有-fopenmp

Endys-MacBook-Pro:Desktop endy$ vi test.c

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 4170093.00 clock tick.


可以看出,只有在情况1下,openmp生效,其他3种情况下,均为单核运行,2、3、4结果较为接近,而1的运行结果大约相差25%。

值得注意的是,使用多核心的case 1竟然比单核的其他3种case慢了25%,原因是在这种单一的循环运算中,并行分配CPU任务的指令比直接执行下一个循环指令的效率更低。所以并不是用并行运算就一定能够提高运算效率的,要根据实际情况来判断。



热点内容
简单的解压 发布:2025-07-15 17:42:25 浏览:145
lol最强脚本 发布:2025-07-15 17:41:45 浏览:288
安卓手机测量工具在哪里 发布:2025-07-15 17:41:39 浏览:240
易语言灰鸽子源码 发布:2025-07-15 17:37:08 浏览:868
编程代码怎么写 发布:2025-07-15 17:30:45 浏览:120
光遇安卓九游服怎么切换账号 发布:2025-07-15 17:29:07 浏览:916
sqlserverce 发布:2025-07-15 17:20:27 浏览:712
海量数据的存储管理 发布:2025-07-15 17:16:51 浏览:658
安卓手机哪个版本适合玩游戏 发布:2025-07-15 17:12:31 浏览:57
安装flexlinux 发布:2025-07-15 16:35:47 浏览:372