2005年08月19日

 

MIT BBS上说微软电话面试的一道题就是"Who do you think is the best coder, and why?"。我觉得挺有意思的,也来凑个热闹。排名不分先后。

Bill Joy, 前任Sun的首席科学家,当年在Berkeley时主持开发了最早版本的BSD。他还是vicsh的作者。当然,Csh Programming Considered Harmful 是另一个话题乐。据说他想看看自己能不能写个操作系统,就在三天里写了个自己的Unix, 也就是BSD的前身。当然是传说了,但足见他的功力。另一个传说是,1980年初的时候,DARPABBNBerkley Unix里加上BBN开发的TCP/IP代码。但当时还是研究生的B伯伯怒了,拒绝把BBN TCP/IP加入BSD,因为他觉得BBNTCP/IP写得不好。于是B伯伯出手了,端的是一箭封喉,很快就写出了高性能的伯克利版TCP/IP。当时 BBNDARPA签了巨额合同开发TCP/IP Stack,谁知他们的代码还不如一个研究生的好。于是他们开会。只见当时B伯伯穿个T-shirt出现在会议室(当时穿T-shirt不象现在,还是相 当散漫的哈)。只见BBN问:你怎么写出来的?而B伯伯答:简单,你读协议,然后编程就行了。最令偶晕倒的是,B伯伯硕士毕业 后决定到工业界发展,于是就到了当时只有一间办公室的Sun, 然后他就把Sparc设计出 来乐。。。象这种软硬通吃的牛人,想不佩服都不行的说。据Bill Joy的同事说,一般开会的时候B伯伯总是拿一堆杂志漫不经心地读。但往往在关键之处,B伯伯发言,直切要害,提出 漂亮的构想,让同事们彻底崩溃。对了,他还是Java SpecJINI的主要作者之一。


John Carmack
ID SoftwarefounderLead Programmer。上个月和一个搞图形的师兄聊天,他竟然不知道John Carmack, 也让偶大大地晕了一把。不过也许搞研究的和搞实战的多少有些隔吧。想必喜欢第一人称射击游戏的都知道J哥哥。90年代初只要能在PC上搞个小动画都能让人 惊叹一番的时候,J哥哥就推出了石破天惊的Castle Wolfstein, 然后再接再励,doom, doomII, Quake…每次都把3-D技术推到极

限。J哥哥的简历上说自己的专长是"Exhaust 3-D technology",真是牛人之言不我欺的说。做J哥哥这样的人是很幸福的,因为各大图形卡厂家一有了新产品就要向他"进贡" ,不然如果他的游戏不支持哪种卡,哪种卡基本就会夭折乐。当初MSDirect3D也得听取 他的意见,修改了不少API。当然,J哥哥在结婚前十数年如一日地每天编程14小时以上, 也是偶们凡人望尘莫及的。对了,J哥哥高中肆业(),可以说是自学成才。不过呢,谁要用这个例子来为自己学习不好辩护,就大错特错了。那 Leonardo Da Vinci还是自学成才呢(人是私生子,不能上学)。普通人和天才还是有区别的。对了,其实偶们叫"达分奇"是相当不对的,因为Vinci是地名,而Da Vinci就是从Vinci来的人的意思。换句话说,Leonardo Da Vinci就是"Vinci来的Leonardo"的意思。叫别人"Da Vinci"就不知所谓乐。嗯,扯远了,打住。


David Cutler
VMSWindows NT的首席设计师,去微软前号称硅谷最牛的kernel开发员。当初他和他的手下在微软一周内把一个具备基本功能的bootable kernel写出来,然后说:"who can’t write an OS in a week?",也是牛气冲天的说。顺便说一句,D爷爷到NT3.5时,管理1500名开发员,自己还兼做设计和编程,不改coder本色啊。


D
爷爷天生脾气火爆,和人争论时喜欢双手猛击桌子以壮声势。
日常交谈F-word不离口。他面试秘书时必问:"what do you think of the word ‘fuck’?" ,让无数美女刹羽而归。终于有一天,一个同样火爆的女面对这个问题脱口而出:"That’s my favorite word"。于是她被录取乐,为D爷爷工作到NT3.5发布。


Don Knuth
。高爷爷其实用不着偶多说。学编程的不知道他就好像学物理的不知道牛顿,学数学的不知道欧拉,学音乐的不知道莫扎特,学Delphi的不知到Anders Hejlsberg,或者学Linux不知道Linus Torvalds一样,不可原谅啊。 了让文章完整,就再罗唆几句吧。高爷爷本科时就开始给行行色色的公司写各种稀奇古怪的编译器挣外快了。他卖给别人时收一两千美元,那些公司拿了code 加工一下卖出去就是上万上十万。不过也没见高爷爷不爽过,学者本色的说。想想那可是60年代初啊,高爷爷写编译器写多了,顺带就搞出了个 Attribute GrammarLR(k),大大地造福后人啊。至于高爷爷在CalTech的编程比赛(Alan Kay得众多高高手参加)总是第一,写的Tex86年就code freeze,还附带2^n美分奖励等等都是耳熟能详的,偶就不饶舌乐。


便说一下,高老大爷是无可争议的写作高手。他给Concrete Mathematics 写的前言可谓字字铿锵,堪为前言的典范。他的技术文章也是一绝,文风细致,解释精当,而且没有学究气,不失轻快跳脱。记得几年前读Concrete Mathemathics,时不时开怀大笑,让老妈极其郁闷,觉得我nerdy到家,不可救药。其实呢,子非鱼,安知鱼之乐,更不知那完全是高爷爷的功 劳。说到写作高手,不能不提Stephen A. Cook。他的文章当年就被我们的写作老师极力推荐,号称典雅文风的样本。库爷爷一头银发,身材颀长,总是面带谦和的微笑,颇有仙风道骨,正好和他的仙文 相配的说。


高爷爷其实还是开源运动的先驱。虽然他没有象Richard Stallman那样八方奔走,但他捐献了好多作品,都可以在网上看到,比如著名的Mathematical WritingMMIXWareThe Tex Book等,更不用说足以让他流芳百世的Tex乐。


Ken Thompson
C语言前身B语言的作者,Unix的发明人之一(另一个是Dennis M. Riche老大,被尊为DMR)Belle(一个厉害的国际象棋程序)的作者之一, 操作系统Plan 9的主要作者(另一个是大牛人Rob Pike, 前不久被google挖走了)Ken爷爷也算是计算机历史上开天辟地的人物了。1969年还是计算机史前时代,普通人都认为只有大型机才能运行通用的操 作系统,小型机只有高山仰止的份儿。至于用高级语言来写操作系统,更是笑谈。Ken爷爷自然不是池中物,于是他和DMR怒了,在1969年到1970间用 汇编在PDP-7上写出了UNIX的第一个版本。他们并不知道,一场轰轰烈烈的UNIX传奇由此拉开了序幕。Ken爷爷在1971年又把UnixC 写,于是C在随后20年成就了不知多少豪杰的梦想和光荣。


Ken
爷爷还有段佳话: 装了UNIXPDP-11最早被安装在Bell Lab里供大家日常使用。很快大家就发现Ken爷爷总能进入他们的帐户,获得最高权限。Bell Lab里的科学家都心比天高,当然被搞得郁闷无比。于是有高手怒了,跳出来分析了UNIX代码,找到后门,修改代码,然后重新编译了整个UNIX。就在大 家都以为"这个世界清净了"的时候,他们发现Ken爷爷还是轻而易举地拿到他们的帐户权限,百思不解后,只好继续郁闷。谁知道这一郁闷,就郁闷了14年, 直到Ken爷爷道出个中缘由。原来,代码里的确有后门,但后门不在Unix代码里,而在编译Unix代码的C编译器里。每次C编译器编译UNIX的代码, 就自动生成后门代码。而整个Bell Lab的人,都是用Ken爷爷的C编译器。

Rob Pike, AT&T Bell LabMember of Technical Staff ,现在google研究操作系统。罗伯伯是Unix的先驱,是贝尔实验室最早和Ken Thompson以及Dennis M. Ritche开发Unix的猛人,UTF-8的设计人。他还在美国名嘴David Letterman的晚间节目上露了一小脸,一脸憨厚地帮一胖子吹牛搞怪。让偶佩服不已的是,罗伯伯还是1980年奥运会射箭的银牌得主。他还是个颇为厉 害的业余天文学家,设计的珈玛射线望远镜差点被NASA用在航天飞机上。他还是两本经典,The Unix Programming Environment The Practice of Programming 的作者之一。如果初学者想在编程方面精益求精,实在该好好读读这两本书。它们都有中文版的说。罗伯伯还写出了Unix下第一个基于位图的窗口系统,并且是 著名的blit 终端的作者。当然了,罗伯伯还是号称锐意革新的操作系统,Plan9,的主要作者。可惜的是,Plan9并没有引起多少人的注意。罗伯伯一怒之下,写出了 振聋发聩的雄文Systems Software Research is Irrelevant,痛斥当下系统开发的不思进取,固步自封的弊病。虽然这篇文章是罗伯伯含忿出手,颇有偏激之词,但确实道出了系统开发的无奈:开发周 期越来越长,代价越来越大,用户被统一到少数几个系统上,结果越来越多的活动是测量和修补,而真正的革新越来越少。就在罗伯伯郁闷之极的时候, google登门求贤来乐。如果说现在还有一家大众公司在不遗余力地把系统开发推向极致的话,也就是google乐。随便看看google的成果就知道 了。具有超强容错和负载平衡能力的分布式文件系统GFS (现在能够用100,000台廉价PC搭起一个巨型分布系统,并且高效便宜地进行管理的系统也不多哈),大规模机器学习系统(拼写检查,广告匹配,拼音搜 寻。。。哪个都很牛的说),更不用说处理海量并行计算的各式google服务了。RobSystem Software Research is Irrelevant里萧瑟地说现在没有人再关心系统研究的前沿成果了。想不到他错了,应为google关心。google网络了大批功成总是试图吸取系 统研究的最新成果。想必Rob Pikegoogle很幸福。愿他做出更棒的系统。

作者:佚名

小T一边作自己的3D引擎,一边研究half-life2的图形引擎,留下点心得。

整体上half-life2给小T的感觉一是庞大,二就是难读,com方式组织引擎,小T也不敢妄加评价,只是小T觉得整个引擎非常的难读。小T只有借助调试器才勉强对half-life2的图形引擎有个大致的了解,至于怎么编译half-life2,怎么运行,以及怎样调试,小T就不详细的描述了,到网上随便一搜索就能找到一大堆,这里只是简单的看看他的图形系统。

当前的3D环境,想要提高渲染速度,一个最基本的方法就是要减少硬件的渲染状态的切换,今天小T就是讲hl2的渲染状态管理部分的。在hl2里面,渲染状态主要被放在了一个叫ShadowState_t的结构里面,这个结构对应了大多数的硬件渲染状态,渲染系统维护多个ShadowState_t结构,在必要的时候把ShadowState_t的内容真正的设置到硬件上面,从而减少硬件的状态切换。当然实际上却没有这么简单,上面只是个简单的介绍,下面开始详细的解释hl2怎么进行硬件状态管理。

hl2里面渲染状态管理的一个比较重要的类就是CTransitionTable,从名字上面看,这个类描述的是一种转换,他其实就是描述了,渲染过程中硬件渲染状态的转换流程,hl2把硬件状态的管理也放在了这个里面,举个例子来说可能比较清楚。

比如:整个场景里面有2个物品,第一个物品使用一组渲染状态,第二个物品使用另外一组渲染状态,我们先渲染第一个物品,设置成第一个物品的渲染状态,接着渲染第二个物品,设置第二个物品的渲染状态,这个就是正常的操作方式,如果第一个物品和第二个物品的渲染状态有相同的,那么有些设置renderstate的函数就不用调用,我们可以把渲染状态看作是一种状态机,从第一种状态转换到第二种状态,我们要作一些事情,如果我们能建立一张行动表,表里面记录状态转换的时候要执行的动作,那么我们就可以简化这种状态管理模型,这个就是CTransitionTable类完成的工作。

对于场景里面的每个materila(顺便说一句,hl2也是按照material的方式组织渲染动作的),都对应了一种渲染状态,这些渲染状态都被CTransitionTable类记录下来,每一个渲染状态对应一个唯一的id,那么material只用记录他对应的渲染状态id就能完成自己的渲染了。比如我们要渲染一个物品,我们告诉渲染系统我们使用的渲染状态id,渲染系统自动完成渲染状态的设置,自动完成渲染状态切换的最小化任务,然后我们调用一个drawprimitive就ok。实际上的操作也没有这么简单,我们再看看实际一点的东西。

hl2里面的渲染状态操作都被封装到了ShaderRenderState_t类里面
struct ShaderRenderState_t
{
 RenderPassList_t m_Snapshots[4];//代表了一种渲染方式,缓冲4种渲染方式0=默认,1=带color数据,2=带alpha数据,3=color+alpha
int m_Flags;// 标志,
VertexFormat_t m_VertexFormat;// 顶点格式
int m_VertexUsage;
};

struct RenderPassList_t
{
int m_nPassCount; // 渲染pass的数目
StateSnapshot_t m_Snapshot[MAX_RENDER_PASSES]; // 实际是一个short形式,就是渲染状态id
};

解释下RenderPass这个东西,一个material在hl2里面渲染方式分成了4种,每种都对应了一个RenderPassList_t的类,而ShaderRenderState_t把这4种渲染方式都缓存了,嗯,举个例子,比如我现在想要按照默认的方式渲染一种material,我传递一个ShaderRenderState_t的结构给渲染系统,渲染系统根据我要求的渲染方式索引到正确的RenderPassList_t元素,使用里面记录的StateSnapshot_t数组里面的某个正确的id来获取到正确的渲染状态。

我们已经知道了渲染系统的客户端怎样要求渲染系统完成自己的渲染状态设置了,接下来看看渲染系统本身怎样完成这个工作,当渲染系统得到一个渲染状态id以后,就应该要获取到与之对应的渲染状态,并且正确的设置好这个状态,换句话说也就是要完成当前状态到新状态的切换,首先看看渲染系统怎么去找到正确的渲染状态,这就落在了IShaderAPI和CTransitionTable身上了,小T使用的是DX9的ShaderApi,所以这个任务是由CShaderAPIDX8这个类来完成了,在CShaderAPIDX8类里面有一个CTransitionTable类的数据成员m_TransitionTable,每当要获取到一个渲染状态id以后,ShaderApi就告诉m_TransitionTable要使用新的渲染状态了,并且传递新状态的id,到这里先停一下,一直小T都使用渲染状态这几个字在描述,那究竟hl2使用什么样子的数据结构来表示实际的渲染状态呢?ShadowState_t对应的是硬件状态,而还有一个东西对应了vs,ps的状态,他也是要在状态转换的时候进行设置的,渲染状态id对应的其实是SnapshotShaderState_t 结构:

struct SnapshotShaderState_t
{
ShadowShaderState_t m_ShaderState;
ShadowStateId_t m_ShadowStateId;
};

struct ShadowShaderState_t
 {
// The vertex + pixel shader group to use…
VertexShader_t m_VertexShader;
PixelShader_t m_PixelShader;
// The static vertex + pixel shader indices
int m_nStaticVshIndex;
int m_nStaticPshIndex;
};

ShaderApi获得了新的渲染状态id以后,和当前的渲染状态id比较,如果不相同,则获取到ShadowStateId,如果也不相同,那就要设置新的ShadowState了,这个操作下面讲解。然后,ShaderApi保存当前的渲染状态id,保存ShadowStateId,同时设置ShadowShaderState,这些都设置完成了,硬件的渲染状态也就设置完成了,然后的任务就是调用DrawPrimitive等等函数完成绘制的时候了,这个绘制是由各个vs,ps完成的,关于这个部分,小T留到下次讲解。

现在我们来看看shaderapi,怎么设置新的ShadowState,基本的方式就是获得两个状态之间的转换表,执行表里面规定的动作,而实际上也是这样进行的,那现在的重点就落在了转换表上面。

CTransitionTable保存了当前渲染过程中所有可能的ShadowState(关于这些是怎么保存起来的,这些信息是怎么获取到了,下面讲解),然后再这些状态中间拉了一张网,每两个状态之间总有一个弧,同时保存了两个状态进行切换的时候要执行的操作,CTransitionTable的主要数据成员如下:

CUtlVector< ShadowState_t > m_ShadowStateList ; // 全部的ShadowState_t的vector,ShadowState的id作为这个vector的下标
CUtlVector< CUtlVector< TransitionList_t > > m_TransitionTable; // 状态转换表,TransitionList_t就代表了状态转换的操作.

struct TransitionList_t
{
unsigned short m_FirstOperation;
unsigned char m_NumOperations;
unsigned char m_nOpCountInStateBlock;
IDirect3DStateBlock9 *m_pStateBlock;
};

struct TransitionOp_t
{
ApplyStateFunc_t m_Op;
int m_Argument;
};

TransitionOp_t也放到了一个vector里面,而TransitionList_t的第一个和第二个成员能在这个vector里面寻址,从而定位到实际的操作,而TransitionOp_t定义的就是实际的操作,第一个成员是一个函数指针,执行操作就是调用那个函数指针,并且传递两个参数,一个是新的ShadowState_t,一个就是结构里面的另外一个成员。

  总结下,CTransitionTable保存了全部的ShadowState_t,保存全部的TransitionOp,都是使用下表作为索引访问,再全部的ShadowState_t之间建立TransitionList,当要进行状态切换的时候执行状态之间定义的TransitionOp就完成了状态的切换了.那ShaderApi是怎么建立ShadowState_t表格和TransitionOP表格的呢?

  ShadowState_t的表格是在material创建的时候完成创建的,创建了一个新的ShadowState_t了以后就会向转换表里面加入新的节点,并且设置好转换操作,而这动作却是借助Draw动作完成了。

  下面结合源代码看看上面这些功能的具体实现。

  先看看draw的流程,最常用操作就是建立一个DynamicMesh,然后使用一个MeshBuilder修改刚刚建立的DynamicMesh,然后调用mesh的Draw函数,我们就从这里开始。

void CDynamicMeshDX8::Draw( int firstIndex, int numIndices )
  CBaseMeshDX8::DrawMesh(); // 调用自己类的函数,实际上是从父类继承来的
    ShaderAPI()->DrawMesh( this ); // 调用CShaderAPIDX8的函数
      m_pMaterial->DrawMesh( m_pRenderMesh ); // 转调用CMaterial的DrawMesh函数
        ShaderSystem()->DrawElements( m_pShader, m_pShaderParams, &m_ShaderRenderState );//调用CShaderSystem函数
        // 计算当前这次绘制操作的方式:普通?color?alpha?alpha+color?
        int mod = pShader->ComputeModulationFlags( params );
        g_pShaderAPI->SetDefaultState(); // 调用CShaderAPIDX8的函数
        ShaderUtil()->SetDefaultState(); // 实际上回到了CMaterialSystem:SetDefaultState()
        // 一系列的CShaderAPIDX8的函数,这些函数只是比较纪录,并不真正的修改硬件的状态
        // 准备渲染,纪录当前的渲染操作,接下来的CurrentStateSnapshot()函数返回的就是当前渲染的状态id
        PrepForShaderDraw( pShader, params, pRenderState, mod );
        // 调用CShaderAPIDX8的函数,纪录当前要渲染的状态ID
        g_pShaderAPI->BeginPass( CurrentStateSnapshot() );
        // 真正的渲染操作,一般是调用到CBaseShader::DrawElements函数
        pShader->DrawElements( params, mod, 0, g_pShaderAPI );
        // 这里根据第三个参数的有无进行不同的操作,如果0就实际的渲染,否则是要生成ShadowState,
        OnDrawElements( ppParams, pShaderShadow, pShaderAPI );
        // 这个函数调用的地方就不好说了,他是和你当前material使用的shader相关联的,这个函数开始的时候
        // 完成些设置操作以后,调用Draw函数,回到CBaseShader
          CBaseShader::Draw();
          // 如果是设置ShadowState,
          GetShaderSystem()->TakeSnapshot();
          // 否则是渲染,都是调用到CShaderSystem的函数
          GetShaderSystem()->DrawSnapshot();
          // 获取到RenderPass
          RenderPassList_t& snapshotList = m_pRenderState->m_Snapshots[m_nModulation];
          // 渲染这个pass
          g_pShaderAPI->RenderPass();
          // 设置这个渲染状态
          m_TransitionTable.UseSnapshot( m_nCurrentSnapshot );
          // ShadowStateId
          ShadowStateId_t id = m_SnapshotList[snapshotId].m_ShadowStateId;
          if (m_CurrentSnapshotId != snapshotId)
          {
            if ( m_CurrentShadowId != id )
            {
              TransitionList_t& transition = m_TransitionTable[id][m_CurrentShadowId];
              ApplyTransition( transition, id );
              ApplyTransitionList( snapshot, nFirstOp, nOpCount );
              ShadowState_t& shadowState = m_ShadowStateList[snapshot];
              TransitionOp_t* pTransitionOp = &m_TransitionOps[nFirstOp];
              for (int i = 0; i < nOpCount; ++i )
              {
                (*pTransitionOp->m_Op)(shadowState, pTransitionOp->m_Argument);
                ++pTransitionOp;
              }
            }
            m_CurrentSnapshotId = snapshotId;
          }
          // 渲染这个mesh,这个函数就会调用到IDERICET3DDEVICE9::DrawPrimitiveIndex
          m_pRenderMesh->RenderPass();
          DoneWithShaderDraw();

接着说GetShaderSystem()->TakeSnapshot();分支

GetShaderSystem()->TakeSnapshot();
  g_pShaderAPI->TakeSnapshot();
    m_TransitionTable.TakeSnapshot(); // CTransitionTable:TakeSnapshot();
      ShaderShadow()->ComputeAggregateShadowState(); // 计算最后的结果CShaderShadowDX8函数
      shadowStateId = FindShadowState();// 查找,如果不存在就创建
      if(shadowStateId == -1)
      {
        shadowStateId = CreateShadowState();// 创建
        // 创建一个空的连接到以前的所有状态
        for ( i = 0; i < newShaderState; ++i )
        {
          int newElem = m_TransitionTable[i].AddToTail();
          m_TransitionTable[i][newElem].m_FirstOperation = INVALID_TRANSITION_OP;
          m_TransitionTable[i][newElem].m_NumOperations = 0;
          m_TransitionTable[i][newElem].m_nOpCountInStateBlock = 0;
          m_TransitionTable[i][newElem].m_pStateBlock = NULL;
        }
        // 以前有的状态都创建一个空的连接到新的状态
        for ( i = 0; i <= newShaderState; ++i )
        {
          int newElem = m_TransitionTable[newShaderState].AddToTail();
          m_TransitionTable[newShaderState][newElem].m_FirstOperation = INVALID_TRANSITION_OP;
          m_TransitionTable[newShaderState][newElem].m_NumOperations = 0;
          m_TransitionTable[newShaderState][newElem].m_nOpCountInStateBlock = 0;
          m_TransitionTable[newShaderState][newElem].m_pStateBlock = NULL;
        }
      }
      // 新加入的状态,和原来的状态连接到一起
      for (int to = 0; to < shadowStateId; ++to)
      {
        CreateTransitionTableEntry( to, shadowStateId );
      }
      for (int from = 0; from < shadowStateId; ++from)
      {
        CreateTransitionTableEntry( shadowStateId, from );
        // 这个函数就有点复杂了,不再这里列举了,就是根据两个状态的不同设置转换的操作
      }

到这里,小T要罗索的就全部完了,剩下的就要去看源代码了,小T再列几个注意的地方就结束。

  很多的类之间的通讯方式是靠类成员,全局变量完成的,多注意那些准备函数,结束函数,对理解参数的传递有帮组。

  多使用调试器,留意那些指针变量的地址,很多的指针都是指向同一个东西的。


维持秩序的警察也被挤在人群中进退不得。
 在遇到便宜货的时候,美国人也会把“奋勇争先”的精神发挥得淋漓尽致。日前,美国弗吉尼亚州小县的民众就为抢购廉价笔记本电脑疯狂了一把,5500多人从四面八方涌向小小的销售点,由于现场失控,造成踩踏事故,17人受轻伤,但不少人还是“轻伤不下火线”,继续“勇往直前”。


  价格极具吸引力


  据当地媒体8月16日报道,弗吉尼亚州里士满亨利科县的教育系统决定,在16日当天向本县居民出售1000台“苹果iBook”笔记本电脑,虽然是用过4年的二手货,但价格却“低达”50美元,与售价在999美元到1299美元之间的新笔记本相差悬殊,于是整个县的居民都为这个好消息兴奋不已。


  16日清晨天蒙蒙亮,闻讯赶来的男女老幼冲向电脑销售处,有人抱着孩子,有人拖着老伴,还有人甚至从凌晨1点半开始就在这里“蹲点”。到销售快开始的时候,现场已经聚集了约5500人。其中一名女子宁愿尿裤子,也不愿离开队伍放弃购买机会。


  抢购现场太疯狂


  早上7点,销售公司的大门终于打开了,在外等待已久的人们顿时形成了一波一波从外向内推进的人浪。他们大声尖叫,互相推搡。一名小女孩的婴孩车被挤碎,一位老人被推倒在人行道上,甚至有人还想开车冲向人群开道。一名19岁女孩被挤崴了脚,一拐一拐地走在马路上,嘴里说:“这简直是疯了。”维持秩序的警员拿着喇叭喊话也无法盖过鼎沸的人声,而且就连警员本身也被人群挤得动弹不得。


  当天下午1时,二手笔记本销售一空。亨利科县县长施蒂夫·伍德说,在这场混乱的抢购大战中,17人受轻伤,其中4人需要住院治疗。当时,一名男子为了不让别人挤到他前面,竟用随身携带的折叠椅冲着旁人一阵左挥右舞,最终他成功地买到了一台笔记本。一位女顾客在凌晨4点半就带着14岁双胞胎男孩来排队,人群差点把她和孩子们冲散,她心有余悸地说:“我以前从未做过这样的事情,以后再也不会做了。不管孩子想要什么,我都会告诉他们我不会再这样做了。”

2005年08月13日

  英特尔将宣布对传统奔腾架构进行大量改进,主要针对降低发热和提高处理能力。英特尔首席执行官欧德尼将此称为英特尔“下一代架构”。

  英特尔计划在八月底在旧金山举行的“英特尔开发商论坛”上发布新芯片设计的细节,这将是欧德尼五月成为英特尔首席执行官后首次公开演讲。

        这种芯片的台式机芯片代码名为“Conroe”,笔记本电脑芯片代码名为“Merom”,服务器芯片代码名为“Woodcrest”,它们将在2006年年中上市。

  英特尔去年以发热太高为由取消了最快的奔腾4。分析师们认为,移动奔腾可能是英特尔新芯片架构的样板,移动奔腾已经成为英特尔最畅销的芯片,在最新的季度财报中,英特尔表示,移动芯片部门的销售量比去年同期增长了68%,台式机芯片和服务器芯片则都出现了下降。

  一些分析师表示,设计效率更高的处理器与双核处理器方面的努力密切相关,双核处理器被认为是提高计算机运行速度又不增加能耗的一种方法。欧德尼曾表示,双核技术是英特尔未来的重要组成部分,但是将奔腾系列转向能耗更低的架构也能帮助英特尔,例如,追逐消费电子这一英特尔长期追求的市场。

2005年08月11日

88日,Macromedia发布了Studio 8系列套装,包括最新版的DreamweaverFlashFireworks以及ContributeFlashPlayer。其中Flash Professional 8根据移动设备开发特点增加了许多新的功能,如移动设备模拟器,ActionScript Assist等功能。

以前的帐号好久没用了,换个新的。