??xml version="1.0" encoding="utf-8" standalone="yes"?>婷婷五月深深久久精品,久久精品国产一区二区三区不卡,无码任你躁久久久久久久http://www.shnenglu.com/kevinlynx/category/19776.html低调做技术__Ƣ迎UL我的独立博客 <a >codemaro.com</a> 微博 <a >kevinlynx</a>zh-cnTue, 09 Sep 2014 16:53:41 GMTTue, 09 Sep 2014 16:53:41 GMT60理解git常用命o原理http://www.shnenglu.com/kevinlynx/archive/2014/09/09/208257.htmlKevin LynxKevin LynxTue, 09 Sep 2014 13:35:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2014/09/09/208257.htmlhttp://www.shnenglu.com/kevinlynx/comments/208257.htmlhttp://www.shnenglu.com/kevinlynx/archive/2014/09/09/208257.html#Feedback0http://www.shnenglu.com/kevinlynx/comments/commentRss/208257.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/208257.html

git不同于类似SVNq种版本理pȝQ虽然熟悉常用的操作可以满_部分需求,但ؓ了在遇到ȝ时不至于靠蛮力去试Q了解git的原理还是很有必要?/p>

文g

通过git理的文件版本信息全部存攑֜根目?code>.git下,E微看下Q?/p>

$ ls .git
COMMIT_EDITMSG HEAD branches description index logs packed-refs
FETCH_HEAD ORIG_HEAD config hooks info objects refs

git除了提供l我们^时常用的一些命令之外,q有很多底层命oQ可以用于查看以上部分文件表C的东西?/p>

三个区域/三类对象

理解git里的三个区域概念非常重要。git里很多常用的命o都是围绕着q三个区域来做的。它们分别ؓQ?/p>

  • working directoryQ也是你所操作的那些文?/li>
  • historyQ你所提交的所有记录,文g历史内容{等?strong>git是个分布式版本管理系l,在你本地有项目的所有历史提交记录;文g历史记录Q提交日志等{?/strong>
  • stage(index)Q暂存区域,本质上是个文Ӟ也就?code>.git/index

git中还有三cd用对象(实际不止三种Q,理解q三cd象也很重要。分别ؓQ?/p>

  • blobQ用于表CZ个文?/li>
  • treeQ用于表CZ个目录,索引到若q文件或子目?/li>
  • commitQ用于表CZơ提?commit)

所有对象都会以文g的Ş式保存在.git/objects目录Q一个对象一个文件?/p>

接下来把上面所有的内容兌h。做以下操作Q?/p>

$ mkdir test && cd test
$ git init
$ ls -a .git/objects # 没有文g
. .. info pack
$ touch readme # working directory里增加了一个readme文g
$ git add readme # d一个文件到stage区域
$ git ls-files --stage # q个命o可以查看stage区域里的内容Q可以看到有readme
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 readme
$ ls -a .git/objects # 同时.git/objects增加了一个e6的目?
. .. e6 info pack
$ ls -a .git/objects/e6/ # e6目录下增加了一个文?
. .. 9de29bb2d1d6434b8b29ae775ad8c2e48c5391

上面的操作展CZgit中三个区域三个对象的部分兌关系。git中每个对象都以一?0个字W长度的SHA-1哈希gؓ标识Q以q?0个字W的?个字W作为文件夹Q以?8个字Wؓ文g名?/p>

Z以上l箋操作Q?/p>

$ git commit -m 'first commit' # commit会将stage里标识的文g提交到history区域
[master (root-commit) 8bf6969] first commit
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 readme
$ ls -a .git/objects # 增加?个文Ӟ也就?个对?
. .. 8b e6 e8 info pack
$ git ls-files --stage # stage仅表C当前被版本理的文Ӟ所以内容不?
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 readme
# git cat-file 命o可以用于查看.git/objects下的文gQ意卛_用于查看对象
$ git cat-file -t e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 # q个是之前git add readme产生的文件对?blob
blob
# 同样我们来查看git commit -m后新增的两个对象
$ ls .git/objects/8b/
f696927c17526eb8f0c6dae8badb968a001ed0
$ git cat-file -t 8bf696927c17526eb8f0c6dae8badb968a001ed0 # 记得带上8bq个文g夹名Q才一个完整的对象ID。这是一个commit对象
commit
$ ls .git/objects/e8
0ad49ace82167de62e498622d70377d913c79e
$ git cat-file -t e80ad49ace82167de62e498622d70377d913c79e # tree对象
tree

区域和对象如何交互的可以用下图描qͼ

通过git cat-file -p可以查看对象的更多描qͼgit cat-file -t仅获取对象的cd。做以下操作获得更深的认识:

# q个commit对象记录了提交者的信息Q还包括指向的tree对象
$ git cat-file -p 8bf696927c17526eb8f0c6dae8badb968a001ed0
tree e80ad49ace82167de62e498622d70377d913c79e
author Kevin Lynx <kevinlynx@gmail.com> 1410090424 +0800
committer Kevin Lynx <kevinlynx@gmail.com> 1410090424 +0800
first commit
# 查看tree对象可以看出tree指向的blob对象
$ git cat-file -p e80ad49ace82167de62e498622d70377d913c79e
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 readme

即是已l被版本理的文Ӟ发生改动后(正常改动或合qӞ都?code>git add来重新mark它。创建第二次提交q一步认识:

$ echo 'hello git' > readme
$ touch install
$ git ls-files --stage # 不用git addQ暂存区域内Ҏ?
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 readme
# 此时stage里内Ҏ变,提示no changes added to commit
$ git commit
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# install
no changes added to commit (use "git add" and/or "git commit -a")
$ git add readme
$ ls .git/objects/ # git add之后.git/objects下新增文?
8b 8d e6 e8 info pack
$ ls .git/objects/8d/
0e41234f24b6da002d962a26c2495ea16a425f
$ git cat-file -p 8d0e41234f24b6da002d962a26c2495ea16a425f # 查看该新增对?
hello git
# q个时候还可以在提交前撤销git add readme
$ git reset readme # 从history到stage
Unstaged changes after reset:
M readme
$ cat readme
hello git
$ git checkout readme # 从stage到working directory
$ cat readme # 没有内容Q回到第一个版?
$ git add install # d新创建的文g
$ git ls-files --stage # stage中的内容是最新的readme和新d的install
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 install
100644 8d0e41234f24b6da002d962a26c2495ea16a425f 0 readme
$ ls .git/objects/
8b 8d e6 e8 info pack

以上Q发C个有的现象Q新加的install文g的SHA-1哈希值和之前?code>readme相同Q这是因2个文仉是空的,内容相同。l:

$ git commit -m 'second commit'
$ ls .git/objects/ # 提交后新?个对?
45 72 8b 8d e6 e8 info pack
$ ls .git/objects/72/
b94e949c5fca6092cc74c751a7bb35ee71c283
$ git cat-file -p 72b94e949c5fca6092cc74c751a7bb35ee71c283
tree 45cf0bd049d7eea4558b14f33a894db27c7c1130 # 新创建的tree对象
parent 8bf696927c17526eb8f0c6dae8badb968a001ed0 # commit对象有parentQ正是上一ơ提?
author Kevin Lynx <kevinlynx@gmail.com> 1410094456 +0800
committer Kevin Lynx <kevinlynx@gmail.com> 1410094456 +0800
second commit
# 新创建的tree对象指向?个文?
$ git cat-file -p 45cf0bd049d7eea4558b14f33a894db27c7c1130
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 install
100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f readme

需要注意,有时候我们?code>git commit -aQ它会直接将已经加入版本理的文件一h交,从而蟩q了git addq个q程。同git很多操作一P它只是一个快h作?/p>

ȝ

从上面的内容其实已经可以看出git的优势所在,它可以完全不需要服务器完成一个版本控制系l的所有事情。在.git文g中它记录了所有的文g的所有历史提交,记录了每一ơ提交的信息?/p>

git的常用操作中q会涉及到分支、远端仓库等Q空了再写?/p>

参考文?/h2>

Kevin Lynx 2014-09-09 21:35 发表评论
]]>析软g工程开发方法学RUPhttp://www.shnenglu.com/kevinlynx/archive/2013/03/21/198692.htmlKevin LynxKevin LynxThu, 21 Mar 2013 13:41:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2013/03/21/198692.htmlhttp://www.shnenglu.com/kevinlynx/comments/198692.htmlhttp://www.shnenglu.com/kevinlynx/archive/2013/03/21/198692.html#Feedback0http://www.shnenglu.com/kevinlynx/comments/commentRss/198692.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/198692.html

前言

因ؓ之前一直处在游戏开发行业,׃U种原因一直对软g工程中的目理、项目开发方法缺乏体验。虽焉目中也曾倡导~写更多的文档,无论是模块说明文档还是设计文档,但效果一直不好。不甚理想的地方主要体现在文档的规范性欠~、不l一、Q于表面没有实质内宏V文档的~写~Z详尽的方法指|那么所谓的设计文档要么是用来敷衍上U要么就是随着开发h员的水^不一而千差万别?/p>

当我开始目前这个非游戏目Ӟ我也曾想Q前期做好结构设计,制定好关键问题的解决ҎQ那么要完成q个目׃在话下了。但是我很快面临了一个问题:需求不定。回惌n处游戏公司的那些日子Q程序员L抱怨策划需求变更过快过多,在每一ơ策划提Z个需求变更时Q}慎的E序员都会再三让{划保证Q放心,不会变了。而我面的问题则更ؓ严峻。我意识刎ͼ目的需求,p用户也无法一一|列出来。我们需要的是需求调研。但q你将客户的所有需求全部挖掘出来后Q这几乎不可能,因ؓ他们自己也不太清楚自己想要什么)Q当你交付了W一个Y件版本,几乎可以肯定客户会提Z大堆的需求变_我要的不是这个,我要的那个怎么没有Q哦Q我当初以ؓ你说的是另一个意思?/p>

当然Q需求调研这U工作不是让E序员去做的Q那会更悲剧Q无论是对客戯是对E序员而言Q他们都是在对牛弹琴Q。但需求的不确定性也L存在的?/p>

事实上,需求变化本w就是一个很正常的现象。我一向愿意更悲观地处理Y件开发方面的问题Q所谓小心得万q船。基于此Q我军_摆好心态学学Y件开发的Ҏ学?/p>

概要

本文要描q、ȝ了RUP开发方法学的主要内容,l合我自q感受阐述了一些RUP的核心原则。我怿我所理解的内Ҏ肤浅的,对于非代码的表达我更怿其是存在歧义的。所以本文仅当是一U经验参考,不必当真?/p>

RUP据传是用于指导大型甚臌大型目开发的Q我们做的不是这栯模的目。但是我们需要记录下整个目的开发过E,通过q个q程中出的工gM一个h可以看出q个目是如何实现出来的Q其目的在于规避唯有从v量代码中才能熟悉目实现q种问题。这里出C一个概念:工gQ其指的是Y仉目开发过E中M留下记录的事物,例如文档、图、代码等?strong>RUP的一个重要思想Q在于其整个软g开发过E都是可推导?/strong>。例如我们通常说的软g架构Q或一点的模块l构Q都是通过开发过E中前面阶段产出的工件推导得出,?strong>不是凭借程序员的经验拍脑袋惛_来的Q经验不太可靠,q且千差万别Q?strong>推导意味着每个环节变得可靠)。我们借助RUP的这个特性,创徏q些工gQ用以徏立v软g实现的可靠知识库?/p>

RUP概览

以下均摘?lt;Thinking in UML>中对RUP的描qͼ

l一q程归纳和集成了软g开发活动中的最佛_践,它定义了软g开发过E中最重要的阶D和工作Q四个阶D和九个核心工作)Q定义了参与软g开发过E的各种角色和他们的职责Q还定义了Y件生产过E中产生的工Ӟq提供了模板。最后,采用演进式Y件生命周期(q代Q将工作、角色和工g串在一P形成了统一q程?/p>

l一q程是一U追求稳定的软gҎQ它q求开发稳定架构,控制变更

l一q程集成了面向对象方法、UML语言、核心工作流、工件模板和q程指导{知?/p>

单来_RUP作ؓ一UY仉目开发方法学Q?strong>它定义了软g开发的每一个过E,最重要的是它指g在每一个过E需要Z么,q些产出又是怎样得到。它试图规范化整个流E,以规遉K求变_目参与者水q不一{带来的目不可控等问题Q以期一个Y件品稳定地开发出?/strong>。在一个项目开发过E中Q最核心的资源是人,最不可控的亦是人?/p>

RUPq程与实?/h2>

我觉得要快速学习一U知识,需要首先获得这门知识的M框架。另一斚wQ在我们获得更多信息后,我们需要挖掘出q门知识的核心思想。学习RUP我觉得从q两斚w入手是相Ҏ较快速和有效的手Dc?/p>

RUP框架

RUP定义了Y件开发过E的四个阶段Q以?个工作流E?/strong>。一张极为经典的RUP开发过E框架图如下Q?/p>

rup

RUP整个Y件开发过E分为四个阶D:

  • 先启(Inception)?/li>
  • _֌(Elaboration)
  • 构徏(Construction)
  • 产品?Transition)

每一个阶D늚工作分ؓ9个流E:

  • 业务建模
  • 需?/li>
  • 分析设计
  • 实施
  • 部v
  • 配置与变更管?/li>
  • 目理
  • 环境

其中Q前6个流E被l称?#8221;engineering disciplines”Q后3个流E被UCؓ”supporting disciplines”。当Ӟ我们主要x?个流E。那么,q些工作程和开发阶D又有什么关pdQ上图中其实已经阐明了这些关pR?/p>

RUP指导q代开发。在软g开发的q?个阶D中Q每一个阶D会被分q次q代。而每一ơP代则늛了这9个工作流E。随着开发阶D向产品化靠q,自然而然圎ͼ需求的变更、增加自然会减少Q所以从图中可以看出Q开发过E越到后期,其工作流E中关于需求的工作则越。同P在先启阶D,光求相关的工作则占据了该阶D늚主要工作内容?/p>

RUP中的q代要求在每一ơP代中Q都会完整地实施一遍整个工作流E。在软g实施阶段Q甚至会在每一个P代过E完后输Z个可q行的Y件版本。这个版本可能会被交付给客户Q以期进一步地在功能需求上取得与客户一致的意见。这倒是同敏捷开发有点类伹{?/p>

既然制定了工作流E,那每一个工作流E该如何d施呢Q?strong>RUP制定了每个工作流E需要参与的角色Q这些角色需要从事的zdQ以及这些活动生的工g?/strong>

q句话实际上反映了RUP的一个重要信息,摘自wikiQ?/p>

RUP is based on a set of building blocks, or content elements, describing what is to be produced, the necessary skills required and the step-by-step explanation describing how specific development goals are to be achieved. The main building blocks, or content elements, are the following:

  • Roles (who) – A Role defines a set of related skills, competencies and responsibilities.
  • Work Products (what) – A Work Product represents something resulting from a task, including all the documents and models produced while working through the process.
  • Tasks (how) – A Task describes a unit of work assigned to a Role that provides a meaningful result.

RUP建模

在我看来QRUP每个工作程所完成的工作,是一个徏模的q程。所谓徏模,单来说就是将需要描q的事物通过更系l的形式表达出来Q以期获得对该事物更深入的理解?lt;Thinking in UML>中定义徏模概念ؓQ?/p>

建模(modeling)Q是指通过对客观事物徏立一U抽象的Ҏ用以表征事物q获得对事物本n的理解,同时把这U理解概念化Q将q些逻辑概念l织hQ构成一U对所观察的对象的内部l构和工作原理的便于理解的表达?/p>

在这里,建模的过E需要用一些工兗在RUP中徏模用UML来完成。在<Thinking in UML>中讲qCUML的核心模型,包括Q?/p>

  • 业务用例模型
  • 概念用例模型
  • pȝ用例模型
  • 领域模型
  • 分析模型
  • 软g架构和框?/li>
  • 设计模型
  • lg模型
  • 实施模型

可能在大家的普遍认识中,UML无非是几种图,q且_看一眼理解v来也不困难,甚至q能用来ȝcd做下代码l构设计。但UML的作用不仅仅如此?/p>

以上所描述的UML核心模型中,每个模型q不单指的的是一UUML图。每个模型实际上都会包含几种UML图,会包含若q张UML图。这些模型基本上渗透于RUP?个工作流E中Q只不过不同的工作流E用的模型比重不一而已?/p>

例如?#8220;分析设计”工作程中,可能会用到pȝ用例模型、分析模型、Y件架构和框架、设计模型等Q而业务用例模型可能在q个程中根本不会用刎ͼ相反Q业务用例模型则可能?#8220;业务建模”程中被q泛使用?/p>

前已q及在RUP的每个工作流E中QRUP定义了该程需要参与的角色Q以及这些角色需要进行的zdQ例如这里可以看?#8220;分析设计”程中的角色和活动集Q摘?lt;Thinking in UML>Q:

analyse-action

相应的,在该工作程中需要出的工g集ؓQ摘?lt;Thinking in UML>Q:

analyse-ar

既然使用了UML作ؓ建模工具Q所以可以简单地说这些工件主要就是UML图,当然也会有其他文档性质的事物,例如|络协议l构、数据库表等UML无法描述的东西则通过普通文字性文档描q?/p>

RUP最佛_?/h3>

到目前ؓ止我们已l了解到RUP定义了开发过E?phase)Q定义了每个q程包含的若q工作流E,q定义了每个工作程需要哪些角色从事哪些活动来完成哪些工g。除此之外,RUPq提供了6条最佛_는以指DY件开发:

  • q代开?/li>
  • 理需?/li>
  • 使用Zlg的架?/li>
  • 可视建模
  • 持箋的质量验?/li>
  • 控制变更

q些实践在我看来仅仅是一些项目开发的指导原则Q它们渗透到每一个过E,每一个工作流E。在目q程中实践这些原则,用以保目的成功。例如我们用UML建模Q以辑ֈ“可视建模”。我们通过建立需求用例,?#8220;理需?#8221;?/p>

RUP核心思想

g没有文档来专门阐qRUP的核心思想Q但我觉得掌握其核心思想才是学习的要Ҏ在。要理解一UY件开发方法学的核心思想Q其实最好是其与别的方法学做比较。这里先我的一些感惛_阐述?/p>

用例驱动

用例驱动指的是整个Y仉目的推进q程Q是依靠“用例”来完成?lt;Thinking in UML>Q?/p>

在实际的软g目中,一个Y件要实现的功能通过用例来捕P接下来的所有分析、设计、实现、测试都q例来取得Q即以实现用例ؓ目标。在l一q程中用例能够驱动的不仅仅是分析设计?/p>

用例单来说就是描qC一个系l功能。但必须注意的是Q这仅仅是它定义的一部分。用例主要分布在“业务建模”?#8220;需?#8221;?#8220;分析设计”q些工作q程中。在不同的过E中用例的粒度和性质都不一栗例如对于一个借书pȝ而言Q在业务建模阶段Q我们可以获取出一?#8220;借书”用例Q其pȝ边界甚至不是pȝ而可能仅xq个业务本nQ因个阶D还没有考虑到计机如何实现q个借书业务Q;在系l分析阶D,我们可以将“借书”q个用例l化为用户和计算Y件系l的交互Q进一步地Q我们可能会q一步精化这个用例,例如用户通过|页l端“借书”。(q里描述了很多徏模的l节Q可不必qQ本文只l出一个概要性的介绍Q?/p>

我们说用例驱动Y件开发,但它如何驱动的呢Q我在实际的建模q程中,最明显的感受就是用例驱动了整个建模q程?/p>

  • 在需求分析阶D,我以pȝ使用者的角度l制Z一份用例图Q用于表达用者对该系l的需?/li>
  • 然后我绘制序列图Q活动图{)来实现这些用例,也就是阐qC用者具体是如何与系l交互的
  • 从之前的建模q程中我获得对系l功能需求方面的认识
  • Z前面的分析我可以l制出系l用例图Q以明确pȝ的各个功能需?/li>
  • 同样针对用例l制用例实现?/li>
  • 用例本n应该包含更多的文档,因此我编写用例规U用以详l描q各个用?/li>
  • 从用例规U、用例实C我可以抽d一些分析类Q较设计cL高抽象的c)Q包含用例场景中涉及到的实体Q控刉辑
  • l化q些分析c,分析类l织h形成pȝQ我会用界面cd衔接各个控制c?/li>
  • 得到的分析cL模块来划分,从而可以得C个初步的pȝ架构
  • 初步考虑pȝ实现Q我甚至会得C个初步是的系l部|图
  • 回过头不断审视系l用例,以确认我是否实现了所有用例,q可以保证我的分析实C所有需求,我不用枚举所有系l特性是否被我考虑周全Q我仅需在已有用例图中核?/strong>
  • Z模块实现各个用例Q或者基于分析类来实现系l用?/li>
  • 通过重新l制以及核实用例Q可以进一步精化分析类Q分析类在很大程度上会一一对应到设计类Q而设计类则对应到实际的代?/li>
  • 可以q入设计阶段Q设计阶D会考虑到系l的实现l节Q例如用的语言Q用的框架{?/li>

q入设计阶段后,虽然可以q一步徏模,得到会直接映到代码的类图、序列图{,但这L囑֜面需求变更时Q基本上会面临修改,q意味着l护q些文档需要耗费_֊。所以,<Thinking in UML>中主张将_֊攑֜l护分析cL型中Q而通过其他U定实现从分析类到实际代码的转换。我觉得q个也在理?/p>

规范化整个过E?/h3>

我个得RUP的一大特点在于规范化了整个Y件开发过E,每一个步骤需要哪些角色参与,该干什么,怎么d都有指导。加之这些活动的”可推导?#8220;Q这意味着不论参与角色属于什么水qI都可以稳固地推进目q程?/p>

此外Q这U规范化也会l项目留下详l的演化q程。你可以明确地看到整个Y件是如何演化出最l的产品代码Q可以深入地理解目代码中的设计?/p>

ȝ

我只是一个RUP新手Q即便如此,我依然不觉得RUP是Y件开发的万能药。我怿M软g开发方法都是有局限性的。我们在实际使用的时候也只是吸取其精华。不同的开发方法其适用范围也是不一L。正如有人将RUP和XP做比较时_如果你用RUPd一个杂货铺Q在没开张之前你已l破产了Q同样如果你用XPd飞机Q飞机毁了十来次也许才能做出来(from <Thinking in UML> againQ?/p>

参考文?/h2>

Kevin Lynx 2013-03-21 21:41 发表评论
]]>Z么处理排序的数组要比非排序的快?http://www.shnenglu.com/kevinlynx/archive/2012/08/30/188786.htmlKevin LynxKevin LynxThu, 30 Aug 2012 09:43:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2012/08/30/188786.htmlhttp://www.shnenglu.com/kevinlynx/comments/188786.htmlhttp://www.shnenglu.com/kevinlynx/archive/2012/08/30/188786.html#Feedback3http://www.shnenglu.com/kevinlynx/comments/commentRss/188786.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/188786.html

参?a >Why is processing a sorted array faster than an unsorted array?

问题

看以下代码:

#include <algorithm>
#include <ctime>
#include <iostream>

int main()
{
    // generate data
    const unsigned arraySize = 32768;
    int data[arraySize];

    for (unsigned c = 0; c < arraySize; ++c)
        data[c] = std::rand() % 256;


    // !!! with this, the next loop runs faster
    std::sort(data, data + arraySize);


    // test
    clock_t start = clock();
    long long sum = 0;

    for (unsigned i = 0; i < 100000; ++i)
    {
        // primary loop
        for (unsigned c = 0; c < arraySize; ++c)
        {
            if (data[c] >= 128)
                sum += data[c];
        }
    }

    double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;

    std::cout << elapsedTime << std::endl;
    std::cout << "sum = " << sum << std::endl;
}

问题在于,Lstd::sort那一行,以上代码运行更长的旉。在我的机器上未Lstd::sort耗时8.99sQ去掉后耗时24.78s。编译器使用的是gcc4.4.3。事实上Q以上代码跟~译器没有关p,甚至跟语a没有关系。那q是Z么呢Q?/p>

q跟处理q个数组的逻辑有非常大的关pR如以上代码所C,q个循环里有个条件判断。条件判断被~译成二q制代码后,是一个蟩转指令,cMQ?/p>

具体Z么会不同Q这涉及到计机CPU执行指o时的行ؓ?/p>

CPU的流水线指o执行

惌现在有一堆指令等待CPUL行,那么CPU是如何执行的呢?具体的细节可以找一本计机l成原理的书来看。CPU执行一堆指令时Qƈ不是单纯C条一条取出来执行Q而是按照一U流水线的方式,在CPU真正执行一条指令前Q这条指令就像工厂里水U生产的产品一P已经被经q一些处理。简单来_一条指令可能经q这些过E:取指(Fetch)、解?Decode)、执?Execute)、放?Write-back)?/p>

假设现在有指令序列ABCDEFG。当CPU正在执行(execute)指oAӞCPU的其他处理单元(CPU是由若干部g构成的)其实已经预先处理C指oA后面的指令,例如B可能已经被解码,C已经被取指。这是水U执行,q可以保证CPU高效地执行指令?/p>

Branch Prediction

如上所_CPU在执行一堆顺序执行的指oӞ因ؓ对于执行指o的部件来_其基本不需要等待,因ؓ诸如取指、解码这些过E早p做了。但是,当CPU面非顺序执行的指o序列Ӟ例如之前提到的蟩转指令,情况会怎样呢?

取指、解码这些CPU单元q不知道E序程会蟩转,只有当CPU执行到蟩转指令本w时Q才知道该不该蟩转。所以,取指解码q些单元׃l箋取蟩转指令之后的指o。当CPU执行到蟩转指令时Q如果真的发生了跌{Q那么之前的预处理(取指、解码)q做了。这个时候,CPU得从跌{目标处时取指、解码,然后才开始执行,q意味着QCPU停了若干个时钟周期!

q其实是个问题,如果CPU的设计放任这个问题,那么光度很难提升v来。ؓ此,Z发明了一U技术,UCؓbranch predictionQ也是分支预测。分支预的作用Q就是预某个蟩转指令是否会跌{。而CPU根据自q预测到目标地址取指令。这P卛_从一定程度提高运行速度。当Ӟ分支预测在实C有很多方法?/p>

单的预测可以直接使用之前的实际执行结果。例如某个蟩转指令某一ơ生了跌{Q那么下一ơ执行该指oӞCPUq接从跌{目标地址处取指,而不是该跌{指o的下一条指令?/p>

{案

了解了以上信息后Q文章开头提出的问题可以解释了。这个代码中有一个@环,q个循环里有一个条件判断。每一ơCPU执行q个条g判断ӞCPU都可能蟩转到循环开始处的指令,即不执行if后的指o。用分支预技术,当处理已l排序的数组Ӟ在若q次data[c]>=128都不成立Ӟ或第一ơ不成立Ӟ取决于分支预的实现Q,CPU预测q个分支是始l会跌{到@环开始的指oӞq个时候CPU保持有效的执行Q不需要重新等待到新的地址取指Q同P?code>data[c]>=128条g成立若干ơ后QCPU也可以预这个分支是不必跌{的,那么q个时候CPU也可以保持高效执行?/p>

相反Q如果是无序的数l,CPU的分支预在很大E度上都无法预测成功Q基本就?0%的预成功概率,q将消耗大量的旉Q因为CPU很多旉都会{待取指单元重新取指?/p>

本文完。最后感叹下stackoverflow上这个帖子里那个老外回答问题的专业性,我要是楼L感动得涕泪横飞了。感谢每一个传播知识的人?/p>

参考资?/h2>
  1. http://blog.sina.com.cn/s/blog_6c673e570100zfmo.html
  2. http://www.cnblogs.com/dongliqian/archive/2012/04/05/2433847.html
  3. http://en.wikipedia.org/wiki/Branch_predictor


Kevin Lynx 2012-08-30 17:43 发表评论
]]> һŷƬþ| ˾þav| þùƷþ| þþۺϾɫۺ98| ƷŮþþþavˬ| þþƷվ| 뾫Ʒþþþ..| þ96Ʒþþ| þþƷɫ鶹| ۺϾþþƷɫ| ɫۺɫþû| þùֻоƷ| ޾ƷþþþþĻ | һþ㽶߿ۿ | þþƷһ | 99þɫĻ| aëƬþ| ƯޱгĻþ| 99þþƷӰԺѼ| ŷ˾þþƷ| Ʒþ| þ޸ۿ| þþþþþþþþþĻ| ŷͽxxxxѿþþ| þ99Ʒþþþþ| ɫ͵͵͵þ˴ý| ޾Ʒþþþþ| 69Ʒþþþ99| ˹ھƷþþþһ| þþþþϸ| þþƷһ| 99þۺϹƷ| þùƷ-þþƷ| þþƷAV㽶| þþþŮ˾ƷëƬ| ۺϾƷ㽶þ| þøŮ߳MBA| þۺ³³| Ʒþþþþþ˿| ഺþ| þˬһ|