自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

CPU緩存及偽共享

商務辦公
在計算機系統(tǒng)中,CPU高速緩存是用于減少處理器訪問內存所需平均時間的部件。在金字塔式存儲體系中它位于自頂向下的第二層,僅次于CPU寄存器。其容量遠小于內存,但速度卻可以接近處理器的頻率。

 什么是CPU緩存

在計算機系統(tǒng)中,CPU高速緩存是用于減少處理器訪問內存所需平均時間的部件。在金字塔式存儲體系中它位于自頂向下的第二層,僅次于CPU寄存器。其容量遠小于內存,但速度卻可以接近處理器的頻率。

[[285785]]

當處理器發(fā)出內存訪問請求時,會先查看緩存內是否有請求數據。如果存在(命中),則不經訪問內存直接返回該數據;如果不存在(失效),則要先把內存中的相應數據載入緩存,再將其返回處理器。

 

CPU緩存及偽共享

 

為什么需要CPU緩存

隨著工藝的提升,最近幾十年 CPU 的頻率不斷提升,而受制于制造工藝和成本限制,目前計算機的內存在訪問速度上沒有質的突破。因此,CPU 的處理速度和內存的訪問速度差距越來越大,甚至可以達到上萬倍。這種情況下傳統(tǒng)的 CPU 直連內存的方式顯然就會因為內存訪問的等待,導致計算資源大量閑置,降低 CPU 整體吞吐量。同時又由于內存數據訪問的熱點集中性,在 CPU 和內存之間用較為快速而成本較高(相對于內存)的介質做一層緩存,就顯得性價比極高了。

為什么需要有CPU多級緩存

  1. 各種寄存器,用來存儲本地變量和函數參數,訪問一次需要1cycle,耗時小于1ns;
  2. L1 Cache,一級緩存,本地 core 的緩存,分成 32K 的數據緩存 L1d 和 32k 指令緩存 L1i,訪問 L1 需要3cycles,耗時大約 1ns;
  3. L2 Cache,二級緩存,本地 core 的緩存,被設計為 L1 緩存與共享的 L3 緩存之間的緩沖,大小為 256K,訪問 L2 需要 12cycles,耗時大約 3ns;
  4. L3 Cache,三級緩存,在同插槽的所有 core 共享 L3 緩存,分為多個 2M 的段,訪問 L3 需要 38cycles,耗時大約 12ns;

大致可以得出結論,緩存層級越接近于 CPU core,容量越小,速度越快,當 CPU 執(zhí)行運算的時候,它先去 L1 查找所需的數據,再去 L2,然后是 L3,最后如果這些緩存中都沒有,所需的數據就要去主內存拿。走得越遠,運算耗費的時間就越長。

什么是緩存行

緩存行 (Cache Line) 便是 CPU Cache 中的最小單位,CPU Cache 由若干緩存行組成,一個緩存行的大小通常是 64 字節(jié)(這取決于 CPU),并且它有效地引用主內存中的一塊地址。一個 Java 的 long 類型是 8 字節(jié),因此在一個緩存行中可以存 8 個 long 類型的變量。

 

CPU緩存及偽共享

 

猜一下下面代碼的執(zhí)行時間:

  1. public class ArrayLoop { 
  2.  public static void main(String[] args) { 
  3.  long[][] arr = new long[1024 * 1024][8]; 
  4.  long sum = 0; 
  5.  //橫向遍歷 
  6.  long start = System.currentTimeMillis(); 
  7.  for (int i = 0; i < 1024 *1024; i++) { 
  8.  for (int j = 0; j < 8; j++) { 
  9.  sum += arr[i][j]; 
  10.  } 
  11.  } 
  12.  System.out.println("橫向遍歷耗時:" + (System.currentTimeMillis() - start) + "ms"); 
  13.  //縱向遍歷 
  14.  start = System.currentTimeMillis(); 
  15.  for (int i = 0; i < 8; i++) { 
  16.  for (int j = 0; j < 1024 * 1024; j++) { 
  17.  sum += arr[j][i]; 
  18.  } 
  19.  } 
  20.  System.out.println("縱向遍歷耗時:" + (System.currentTimeMillis() - start) + "ms"); 
  21.  } 

在我電腦上的執(zhí)行時間為:

橫向遍歷耗時:32ms

縱向遍歷耗時:88ms

在程序運行的過程中,緩存每次更新都從主內存中加載連續(xù)的 64 個字節(jié)。因此,如果訪問一個 long 類型的數組時,當數組中的一個值被加載到緩存中時,另外 7 個元素也會被加載到緩存中。

什么是偽共享

 

CPU緩存及偽共享

 

如果多個線程的變量共享了同一個 CacheLine,任意一方的修改操作都會使得整個 CacheLine 失效(因為 CacheLine 是 CPU 緩存的最小單位),也就意味著,頻繁的多線程操作,CPU 緩存將會徹底失效,降級為 CPU core 和主內存的直接交互。

如何避免偽共享

使用了字節(jié)填充技術(空間換時間)解決偽共享;

  1. public final class FalseSharing implements Runnable { 
  2.  public final static int NUM_THREADS = 4; // change 
  3.  public final static long ITERATIONS = 500L * 1000L * 1000L; 
  4.  private final int arrayIndex; 
  5.  private static VolatileLong[] longs = new VolatileLong[NUM_THREADS]; 
  6.  static { 
  7.  for (int i = 0; i < longs.length; i++) { 
  8.  longs[i] = new VolatileLong(); 
  9.  } 
  10.  } 
  11.  public FalseSharing(final int arrayIndex) { 
  12.  this.arrayIndex = arrayIndex; 
  13.  } 
  14.  public static void main(final String[] args) throws Exception { 
  15.  final long start = System.currentTimeMillis(); 
  16.  runTest(); 
  17.  System.out.println("duration = " + (System.currentTimeMillis() - start)); 
  18.  } 
  19.  private static void runTest() throws InterruptedException { 
  20.  Thread[] threads = new Thread[NUM_THREADS]; 
  21.  for (int i = 0; i < threads.length; i++) { 
  22.  threads[i] = new Thread(new FalseSharing(i)); 
  23.  } 
  24.  for (Thread t : threads) { 
  25.  t.start(); 
  26.  } 
  27.  for (Thread t : threads) { 
  28.  t.join(); 
  29.  } 
  30.  } 
  31.  public void run() { 
  32.  long i = ITERATIONS + 1; 
  33.  while (0 != --i) { 
  34.  longs[arrayIndex].value = i; 
  35.  } 
  36.  } 
  37.  public final static class VolatileLong { 
  38.  public volatile long value = 0L; 
  39.  public long p1, p2, p3, p4, p5, p6; // 填充,可以注釋后對比測試 
  40.  } 

Java8 中實現字節(jié)填充

  1. @Retention(RetentionPolicy.RUNTIME) 
  2. @Target({ElementType.FIELD, ElementType.TYPE}) 
  3. public @interface Contended { 
  4.  String value() default ""

注意需要同時開啟 JVM 參數:-XX:-RestrictContended=false

@Contended 注解會增加目標實例大小,要謹慎使用。默認情況下,除了 JDK 內部的類,JVM 會忽略該注解。要應用代碼支持的話,要設置 -XX:-RestrictContended=false,它默認為 true(意味僅限 JDK 內部的類使用)。當然,也有個 –XX: EnableContented 的配置參數,來控制開啟和關閉該注解的功能,默認是 true,如果改為 false,可以減少 Thread 和 ConcurrentHashMap 類的大小。參加《Java性能權威指南》210 頁。

ConcurrentHashMap 中,使用 @sun.misc.Contended 對靜態(tài)內部類 CounterCell 進行修飾。另外還包括并發(fā)容器 Exchanger 也有相同的操作。

  1. /* ---------------- Counter support -------------- */ 
  2. /** 
  3.  * A padded cell for distributing counts. Adapted from LongAdder 
  4.  * and Striped64. See their internal docs for explanation. 
  5.  */ 
  6. @sun.misc.Contended static final class CounterCell { 
  7.  volatile long value; 
  8.  CounterCell(long x) { value = x; } 

Thread 線程類的源碼中,使用 @sun.misc.Contended 對成員變量進行修飾。

  1. // The following three initially uninitialized fields are exclusively 
  2. // managed by class java.util.concurrent.ThreadLocalRandom. These 
  3. // fields are used to build the high-performance PRNGs in the 
  4. // concurrent code, and we can not risk accidental false sharing. 
  5. // Hence, the fields are isolated with @Contended. 
  6. /** The current seed for a ThreadLocalRandom */ 
  7. @sun.misc.Contended("tlr"
  8. long threadLocalRandomSeed; 
  9. /** Probe hash value; nonzero if threadLocalRandomSeed initialized */ 
  10. @sun.misc.Contended("tlr"
  11. int threadLocalRandomProbe; 
  12. /** Secondary seed isolated from public ThreadLocalRandom sequence */ 
  13. @sun.misc.Contended("tlr"
  14. int threadLocalRandomSecondarySeed; 

參考:

https://juejin.im/post/5c471d75e51d45299a08b333

https://juejin.im/post/5cd644886fb9a032136fe6d7

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2022-12-12 08:39:09

CPUCache偽共享

2017-07-13 16:40:16

偽共享緩存行存儲

2023-12-26 10:08:57

緩存偽共享修飾結構體

2019-01-15 14:44:02

CPU Cache L共享存儲器

2023-08-01 08:10:46

內存緩存

2021-11-18 08:55:49

共享CPU內存

2022-01-17 14:24:09

共享字節(jié)面試

2017-08-23 13:21:31

2019-12-10 14:51:00

CPU緩存內存

2021-03-01 11:53:15

面試偽共享CPU

2022-02-02 21:50:25

底層偽共享CPU

2021-09-16 18:29:17

CPU緩存虛擬

2009-04-24 14:46:59

2021-10-29 06:46:42

CPU緩存TLB

2022-08-17 06:25:19

偽共享多線程

2013-06-14 10:12:22

共享并行

2019-04-08 10:09:04

CPU緩存高性能

2025-02-04 10:58:16

2009-06-30 14:08:00

Hibernate緩存

2021-03-29 11:51:07

緩存儲存數據
點贊
收藏

51CTO技術棧公眾號