最適化のすべての種類の礎 - 局所性の原則

コンピュータの基本原則を学び、またはアーキテクチャの多くは、学生を最適化するために行われている程度、地域の原則に非常に精通している必要があります見つけること。ローカライズされたときに有効に取らなければならないにも言及し、チューニングのすべての種類をやっていても非コンピュータ業界が、彼らは一般的に単語の局所性を使用していません。これらは宇宙のエントロピー分布レイアウト、低による局所的なエントロピー、あるため、抽象化してから、あるいはそのより高いレベルの地球は、生命、すべてがローカライズされた製品は、宇宙はどこでも、エントロピー、一部のみ一致している場合ならば混乱。  
  だから何であるローカルこれは、一般的なコンピュータ用語であり、優れた特定のデータ、位置データ、またはアクセス特定の確率にアクセスするときに短い繰り返しプロセッサアクセスの存在を意味する、時間のほとんどは、ローカルデータ_ _アクセスします。地域の原則に基づいて、コンピュータプロセッサは、マルチレベルのキャッシュ近代的なCPU、分岐予測......速く実行しているよりも悪い良い地域の地域の手続きなど、さまざまな最適化を、行うように設計されています。用語は、ローカルコンピュータの設計から来ているが、これRedisのmemcacheのバックエンドへの圧力を軽減するために、CDN配信材料と帯域幅の使用量を減らすために行うように、今日の分散システムでは、インターネット技術はまた、いくつかの地域を見つけることができます......が、
  地域本質とは何ですか?実際、不等確率などでは、この宇宙は、多くのことが均等に分散されていない、確率論の平均分布は、幾何分布の特殊な形で非常にシンプルですが、世界はそれほど単純ではありません。私たちは、長いリリースはガウスリリースを呼ばれるのが聞こえ、だけでなく、正規分布としても知られ、それは通常の状態にある確率は、以下の確率マップからリリースしたが、これは今日言っているわけではありません。
ここに画像を挿入説明
  実際には、多くの場合、ヘッドの現象に強いフォーカスを持っているものがたくさんありますが、ポアソン分布は、確率論を特徴づけるために使用することができ、この地域は、確率研究の形で描かれています。
ここに画像を挿入説明
ここに画像を挿入説明
  上記は、$ E $は自然定数2.71828を表し、ランダムイベントの発生の平均数$ \ラムダ$単位時間(あるいは単位領域)を示す、概略図及びポアソン分布確率式である..、kは事件の数を表します。描か地域$ \ラムダ$表現は、高周波数データの周波数、$ \ラムダ$より小さく、より多くの明白な濃度現象の頭を逃したときに注意を払ってください。

産地の分類

  局部性有两种基本的分类, 时间局部性空间局部性 ,按Wikipedia的资料,可以分为以下五类,其实有些就是时间局部性和空间局部性的特殊情况。

时间局部性(Temporal locality):

  如果某个信息这次被访问,那它有可能在不久的未来被多次访问。时间局部性是空间局部性访问地址一样时的一种特殊情况。这种情况下,可以把常用的数据加cache来优化访存。

空间局部性(Spatial locality):

  如果某个位置的信息被访问,那和它相邻的信息也很有可能被访问到。 这个也很好理解,我们大部分情况下代码都是顺序执行,数据也是顺序访问的。

内存局部性(Memory locality):

访问内存时,大概率会访问连续的块,而不是单一的内存地址,其实就是空间局部性在内存上的体现。目前计算机设计中,都是以块/页为单位管理调度存储,其实就是在利用空间局部性来优化性能。

分支局部性(Branch locality)

  这个又被称为顺序局部性,计算机中大部分指令是顺序执行,顺序执行和非顺序执行的比例大致是5:1,即便有if这种选择分支,其实大多数情况下某个分支都是被大概率选中的,于是就有了CPU的分支预测优化。

等距局部性(Equidistant locality)

  等距局部性是指如果某个位置被访问,那和它相邻等距离的连续地址极有可能会被访问到,它位于空间局部性和分支局部性之间。 举个例子,比如多个相同格式的数据数组,你只取其中每个数据的一部分字段,那么他们可能在内存中地址距离是等距的,这个可以通过简单的线性预测就预测是未来访问的位置。

实际应用

  计算机领域关于局部性非常多的利用,有很多你每天都会用到,但可能并没有察觉,另外一些可能离你会稍微远一些,接下来我们举几个例子来深入了解下局部性的应用。

计算机存储层级结构

タイムオタク
  上图来自极客时间徐文浩的《深入浅出计算机组成原理》,我们以目前常见的普通家用电脑为例 ,分别说下上图各级存储的大小和访问速度,数据来源于https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html
ここに画像を挿入説明
  从最快的L1 Cache到最慢的HDD,其两者的访存时间差距达到了6个数量级,即便是和内存比较,也有几百倍的差距。举个例子,如果CPU在运算是直接从内存中读取指令和数据,执行一条指令0.3ns,然后从内存读下一条指令,等120ns,这样CPU 99%计算时间都会被浪费掉。但就是因为有局部性的存在,每一层都只有少部分数据会被频繁访问,我们可以把这部分数据从底层存储挪到高层存储,可以降低大部分的数据读取时间。
  
  可能有些人好奇,为什么不把L1 缓存做的大点,像内存那么大,直接替代掉内存,不是性能更好吗?虽然是这样,但是L1 Cache单位价格要比内存单位的价格贵好多(大概差200倍),有兴趣可以了解下DRAM和SRAM。
  我们可以通过编写高速缓存友好的代码逻辑来提升我们的代码性能,有两个基本方法 。

  1. 让最常见的情况运行的快,程序大部分的运行实际都花在少了核心函数上,而这些函数把大部分时间都花在少量循环上,把注意力放在这些代码上。
  2. 让每个循环内缓存不命中率最小。比如尽量不要列遍历二维数组。

MemCache

ここに画像を挿入説明
  MemCache在大型网站架构中经常看到。DB一般公司都会用mysql,即便是做了分库分表,数据数据库单机的压力还是非常大的,这时候因为局部性的存在,可能很多数据会被频繁访问,这些数据就可以被cache到像redis这种memcache中,当redis查不到数据,再去查db,并写入redis。
  因为redis的水平扩展能力和简单查询能力要比mysql强多了,查起来也快。所以这种架构设计有几个好处:

  1. 加快了数据查询的平均速度。
  2. 大幅度减少DB的压力。

    CDN

      CDN的全称是Content Delivery Network,即内容分发网络(图片来自百度百科) 。CDN常用于大的素材下发,比如图片和视频,你在淘宝上打开一个图片,这个图片其实会就近从CDN机房拉去数据,而不是到阿里的机房拉数据,可以减少阿里机房的出口带宽占用,也可以减少用户加载素材的等待时间。
    ここに画像を挿入説明
      CDN在互联网中被大规模使用,像视频、直播网站,电商网站,甚至是12306都在使用,这种设计对公司可以节省带宽成本,对用户可以减少素材加载时间,提升用户体验。看到这,有没有发现,CDN的逻辑和Memcache的使用很类似,你可以直接当他是一个互联网版的cache优化。

    Java JIT

  JIT全称是Just-in-time Compiler,中文名为即时编译器,是一种Java运行时的优化。Java的运行方式和C++不太一样,因为为了实现write once, run anywhere的跨平台需求,Java实现了一套字节码机制,所有的平台都可以执行同样的字节码,执行时有该平台的JVM将字节码实时翻译成该平台的机器码再执行。问题在于字节码每次执行都要翻译一次,会很耗时。
  ここに画像を挿入説明
  图片来自郑雨迪Introduction to Graal ,Java 7引入了tiered compilation的概念,综合了C1的高启动性能及C2的高峰值性能。这两个JIT compiler以及interpreter将HotSpot的执行方式划分为五个级别:

  • level 0:interpreter解释执行
  • level 1:C1编译,无profiling
  • level 2:C1编译,仅方法及循环back-edge执行次数的profiling
  • level 3:C1编译,除level 2中的profiling外还包括branch(针对分支跳转字节码)及receiver type(针对成员方法调用或类检测,如checkcast,instnaceof,aastore字节码)的profiling
  • level 4:C2编译

  通常情况下,一个方法先被解释执行(level 0),然后被C1编译(level 3),再然后被得到profile数据的C2编译(level 4)。如果编译对象非常简单,虚拟机认为通过C1编译或通过C2编译并无区别,便会直接由C1编译且不插入profiling代码(level 1)。在C1忙碌的情况下,interpreter会触发profiling,而后方法会直接被C2编译;在C2忙碌的情况下,方法则会先由C1编译并保持较少的profiling(level 2),以获取较高的执行效率(与3级相比高30%)。
  这里将少部分字节码实时编译成机器码的方式,可以提升java的运行效率。可能有人会问,为什么不预先将所有的字节码编译成机器码,执行的时候不是更快更省事吗?首先机器码是和平台强相关的,linux和unix就可能有很大的不同,何况是windows,预编译会让java失去夸平台这种优势。 其次,即时编译可以让jvm拿到更多的运行时数据,根据这些数据可以对字节码做更深层次的优化,这些是C++这种预编译语言做不到的,所以有时候你写出的java代码执行效率会比C++的高。

CopyOnWrite

  CopyOnWrite写时复制,最早应该是源自linux系统,linux中在调用fork() 生成子进程时,子进程应该拥有和父进程一样的指令和数据,可能子进程会修改一些数据,为了避免污染父进程的数据,所以要给子进程单独拷贝一份。出于效率考虑,fork时并不会直接复制,而是等到子进程的各段数据需要写入才会复制一份给子进程,故此得名 写时复制
  在计算机的世界里,读写的分布也是有很大的局部性的,大多数情况下写远大于读, 写时复制 的方式,可以减少大量不必要的复制,提升性能。 另外这种方式也不仅仅是用在linux内核中,java的concurrent包中也提供了CopyOnWriteArrayList CopyOnWriteArraySet。像Spark中的RDD也是用CopyOnWrite来减少不必要的RDD生成。
  

处理

  上面列举了那么多局部性的应用,其实还有很多很多,我只是列举出了几个我所熟知的应用,虽然上面这些例子,我们都利用局部性得到了能效、成本上的提升。但有些时候它也会给我们带来一些不好的体验,更多的时候它其实就是一把双刃剑,我们如何识别局部性,利用它好的一面,避免它坏的一面?

识别

  文章开头也说过,局部性其实就是一种概率的不均等性,所以只要概率不均等就一定存在局部性,因为很多时候这种概率不均太明显了,非常好识别出来,然后我们对大头做相应的优化就行了。但可能有些时候这种概率不均需要做很详细的计算才能发现,最后还得核对成本才能考虑是否值得去做,这种需要具体问题具体分析了。    
  如何识别局部性,很简单,看概率分布曲线,只要不是一条水平的直线,就一定存在局部性。  

利用

  发现局部性之后对我们而言是如何利用好这些局部性,用得好提升性能、节约资源,用不好局部性就会变成阻碍。而且不光是在计算机领域,局部性在非计算机领域也可以利用。
##### 性能优化
  上面列举到的很多应用其实就是通过局部性做一些优化,虽然这些都是别人已经做好的,但是我们也可以参考其设计思路。
  恰巧最近我也在做我们一个java服务的性能优化,利用jstack、jmap这些java自带的分析工具,找出其中最吃cpu的线程,找出最占内存的对象。我发现有个redis数据查询有问题,因为每次需要将一个大字符串解析很多个键值对,中间会产生上千个临时字符串,还需要将字符串parse成long和double。redis数据太多,不可能完全放的内存里,但是这里的key有明显的局部性,大量的查询只会集中在头部的一些key上,我用一个LRU Cache缓存头部数据的解析结果,就可以减少大量的查redis+解析字符串的过程了。
  另外也发现有个代码逻辑,每次请求会被重复执行几千次,耗费大量cpu,这种热点代码,简单几行改动减少了不必要的调用,最终减少了近50%的CPU使用。
  
##### 非计算机领域
  《高能人士的七个习惯》里提到了一种工作方式,将任务划分为重要紧急、不重要但紧急、重要但不紧急、不重要不紧急四种,这种划分方式其实就是按单位时间的重要度排序的,按单位时间的重要度越高收益越大。《The Effective Engineer》里直接用leverage(杠杆率)来衡量每个任务的重要性。这两种方法差不多是类似的,都是优先做高收益率的事情,可以明显提升你的工作效率。
  これは、長い間、大きな利益が、やって価値があったことを、比較的少数のものがあるとして、内のローカル作業利回りの結果です。法__82の__の非常によく知られているルールは、多くの産業では、多くの地域は、適用することができ、また、ありXXXのXXXから80%〜20% 売上高の80%が地域に、作業タスクの20%から来ています私たちの啓示「は常に20%の最も重要に焦点を当てています。」

避けます

  とりわけ、私たちは、地域によってパフォーマンスを向上させる方法について話されていますが、時には私たちは、地元の食材を回避する必要があります。たとえば、大規模なデータ操作で、多くの場合、ローカライズされたデータの分布によって引き起こされるデータ・スキュー、データのホットな問題に遭遇、データは、我々のデータは、多くの場合、非常に長い時間のかかるコンピューティングタスクをリードし、データはいくつかのホットスポットにつながるスキュー単一ノードのパフォーマンスのクラスタ全体のボトルネックが、ほとんどのノードが非常にビジー状態である、これらは私たちが避けるために必要なものです。
  データは一様分布になるように、一般的に、我々は全体のデータを再ハッシュする、あまりにも動揺ホットで提供されたデータがカットされている斜めの道を解決するため、当然のことながら、いくつかのビジネス・ロジックは、あなたが自由にデータを破壊し、あなたが特定の問題を分析する必要があり、この時間を聞かせていないことがあります。ビッグデータの分野で感じ、局所性がもちろん、あなたがそのようなHDFS小さな単一ノードファイルの読み取りホットスポットのような他の手段を通じて解決する必要がある場合は避けることができない、プラスコピーを減らすことによって軽減することができ、避けるようにしてください。何本質的にホットスポットを軽減するためにリソースを増やすために、ローカライズされた回避はありませんが、それはまた、このアプローチに加えて、リソースを取る脱線のRedisの星団への応答をマイクロブログに言われています。
 

参考資料

  1. 地域のウィキペディアの原則
  2. 「コンピュータの構成と設計」デビッド・A.Patterson /ジョン・L.Hennessy
  3. 「素人の言語コンピューター組成原理は」時間徐Wenhaoをオタク
  4. 「深い理解のコンピュータシステムの」ランダルE.Bryant /デヴィッド・O'Hallaronゴングアレクシー/レイYingchun(翻訳)
  5. インタラクティブレイテンシ
  6. グラールの紹介鄭ゆうディ

おすすめ

転載: www.cnblogs.com/xindoo/p/11303906.html