久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

What every programmer should know about memory 笔记

發布時間:2025/4/16 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 What every programmer should know about memory 笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

What every programmer should know about memory, Part 1(筆記)

每個程序員都應該了解的內存知識【第一部分】

2.商用硬件現狀 現在硬件的組成對于pc機而言基本上都是一下的結構: 由2部分組成:南橋,北橋 CPU通過FSB(前端總線)連接到北橋芯片,北橋芯片主要包含內存控制器和其他一些組件,內存控制器決定了內存的類型,SDRAM,DRAM等都需要不同類型的內存控制器。 南橋芯片主要是通過多條不同的總線和設備通信,主要有PCI,SATA,USB等還支持PATA,IEEE 1394,串口和并口。 需要注意一下地方: 1.cpu之間的通信需要通過它與北橋之間的連接總線 2.與RAM的通信需要走北橋芯片 3.RAM只有一個端口 4.CPU和南橋設備通信需要經過北橋 第一個瓶頸:早期RAM的訪問都要經過cpu,影響了整體性能,所以出現了DMA(直接內存訪問),無需CPU干涉但是會導致和CPU爭奪北橋的帶寬。 第二個瓶頸:北橋和RAM之間的總線所以出現了雙通道(可以實現帶寬加倍,內存訪問在兩個通道上交錯分配) 除了并發訪問模式也是有瓶頸的看2.2 比較昂貴的系統上可能會出現: 北橋自身不帶內存控制器,而是連接到外部多個內存控制器上,好處是支持更多的內存,可以同時訪問不同的內存區,降低了延遲,但是對北橋的內部帶寬要求巨大。 使用外部內存控制器并不是唯一的辦法,比較流行的還有一種是把控制器集成到cpu內部,將內存直接連接到CPU 這樣的架構,系統里有幾個cpu就可以有幾個內存庫(memory bank),不需要強大的北橋就可以實現4倍的內存帶寬。但是缺點也是很明顯:1.導致內存不再是統一的資源(NUMA的得名),2.cpu可以正常的訪問本地內存,但是訪問其他內存時需要和其他cpu互通。在討論訪問遠端內存的代價時,我們用「NUMA因子」這個詞。比如說IBM的x445和SGI的Altix系列。CPU被歸入節點,節點內的內存訪問時間是一致的,或者只有很小的NUMA因子。而在節點之間的連接代價很大,而且有巨大的NUMA因子。 2.1 RAM類型 RAM主要分為2中靜態RAM,動態RAM,前者速度快,代價搞,后者速度慢代價低 2.1.1靜態RAM 主要有6個晶體管組成,核心是4個晶體管M1-M4,他們有2個穩定狀態分別代表0和1 2.1.2 動態RAM 動態RAM只有一個晶體管和一個電容 動態RAM優點是簡單,但是缺點是由于讀取狀態時需要對電容器放電,所以這一過程不能無限重復,不得不在某個點上對它重新充電。更糟糕的是,為了容納大量單元(現在一般在單個芯片上容納10的9次方以上的RAM單元),電容器的容量必須很小(0.000000000000001法拉以下)。這樣,完整充電后大約持有幾萬個電子。即使電容器的電阻很大(若干兆歐姆),仍然只需很短的時間就會耗光電荷,稱為「泄漏」。這種泄露就是現在的大部分DRAM芯片每隔64ms就必須進行一次刷新的原因。(附A關于三極管的輸入輸出特性) 2.2 DRAM訪問細節 同步DRAM,顧名思義,是參照一個時間源工作的。由內存控制器提供一個時鐘,時鐘的頻率決定了前端總線(FSB)的速度。以今天的SDRAM為例,每次數據傳輸包含64位,即8字節。所以FSB的傳輸速率應該是有效總線頻率乘于8字節(對于4倍傳輸200MHz總線而言,傳輸速率為6.4GB/s)。聽起來很高,但要知道這只是峰值速率,實際上無法達到的最高速率。我們將會看到,與RAM模塊交流的協議有大量時間是處于非工作狀態,不進行數據傳輸。我們必須對這些非工作時間有所了解,并盡量縮短它們,才能獲得最佳的性能。 2.2.1讀訪問協議 這里忽略了許多細節,我們只關注時鐘頻率、RAS與CAS信號、地址總線和數據總線。首先,內存控制器將行地址放在地址總線上,并降低RAS信號,讀周期開始。所有信號都在時鐘(CLK)的上升沿讀取,因此,只要信號在讀取的時間點上保持穩定,就算不是標準的方波也沒有關系。設置行地址會促使RAM芯片鎖住指定的行。 CAS信號在tRCD(RAS到CAS時延)個時鐘周期后發出。內存控制器將列地址放在地址總線上,降低CAS線。這里我們可以看到,地址的兩個組成部分是怎么通過同一條總線傳輸的。 既然數據的傳輸需要這么多的準備工作,僅僅傳輸一個字顯然是太浪費了。因此,DRAM模塊允許內存控制指定本次傳輸多少數據。可以是2、4或8個字。這樣,就可以一次填滿高速緩存的整條線,而不需要額外的RAS/CAS序列。另外,內存控制器還可以在不重置行選擇的前提下發送新的CAS信號。這樣,讀取或寫入連續的地址就可以變得非常快,因為不需要發送RAS信號,也不需要把行置為非激活狀態(見下文)。 在上圖中,SDRAM的每個周期輸出一個字的數據。這是第一代的SDRAM。而DDR可以在一個周期中輸出兩個字。這種做法可以減少傳輸時間,但無法降低時延。 2.2.2預充電和激活 2.2.1中的圖只是讀取數據的一部分,還有以下部分: 顯示的是兩次CAS信號的時序圖。第一次的數據在CL周期后準備就緒。圖中的例子里,是在SDRAM上,用兩個周期傳輸了兩個字的數據。如果換成DDR的話,則可以傳輸4個字。即使是在一個命令速率為1的DRAM模塊上,也無法立即發出預充電命令,而要等數據傳輸完成。在上圖中,即為兩個周期。剛好與CL相同,但只是巧合而已。預充電信號并沒有專用線,某些實現是用同時降低寫使能(WE)線和RAS線的方式來觸發。 發出預充電信命令后,還需等待tRP(行預充電時間)個周期之后才能使行被選中。在圖2.9中,這個時間(紫色部分)大部分與內存傳輸的時間(淡藍色部分)重合。不錯。但tRP大于傳輸時間,因此下一個RAS信號只能等待一個周期。 數據總線的7個周期中只有2個周期才是真正在用的。再用它乘于FSB速度,結果就是,800MHz總線的理論速率6.4GB/s降到了1.8GB/s 我們會看到預充電指令被數據傳輸時間限制(途中為COL Addr的傳輸)除此之外,SDRAM模塊在RAS信號之后,需要經過一段時間,才能進行預充電(記為tRAS)(minimum active to precharge time(也就是RAS信號之后到充電的最小時間間隔))它的值很大,一般達到tRP的2到3倍。如果在某個RAS信號之后,只有一個CAS信號,而且數據只傳輸很少幾個周期,那么就有問題了。假設在圖2.9中,第一個CAS信號是直接跟在一個RAS信號后免的,而tRAS為8個周期。那么預充電命令還需要被推遲一個周期,因為tRCD、CL和tRP加起來才7個周期。 DDR模塊往往用w-z-y-z-T來表示。例如,2-3-2-8-T1,意思是: w 2 CAS時延(CL)? x 3 RAS-to-CAS時延(t RCD)? y 2 RAS預充電時間(t RP)? z 8 激活到預充電時間(t RAS)? T T1 命令速率 2.2.3重充電 充電對內存是性能最大的影響,根據JEDEC規范,DRAM單元必須保持每64ms刷新一次我們在解讀性能參數時有必要知道,它也是DRAM生命周期的一個部分。如果系統需要讀取某個重要的字,而剛好它所在的行正在刷新,那么處理器將會被延遲很長一段時間。刷新的具體耗時取決于DRAM模塊本身。 2.2.4內存類型 以下是SDR(SDRAME)的操作圖比較簡單 DRAM陣列的頻率和總線的頻率保持相同,但是當所有組件頻率上升時,那么導致耗電量也上升代價很大,所以就出了DDR,在不提高頻率的狀況下提高吞吐量 SDR和DDR1的區別就是DDR1可以在上升沿和下降沿都傳輸數據,實現了雙倍的傳輸。DDR引入了一個緩沖區。緩沖區的每條數據線都持有兩位。它要求內存單元陣列的數據總線包含兩條線。實現的方式很簡單,用同一個列地址同時訪問兩個DRAM單元。對單元陣列的修改也很小。 為了進一步,于是有了DDR2,最明顯的變化是,總線的頻率加倍了。頻率的加倍意味著帶寬的加倍。如果對單元陣列的頻率加倍,顯然是不經濟的,因此DDR2要求I/O緩沖區在每個時鐘周期讀取4位。也就是說,DDR2的變化僅在于使I/O緩沖區運行在更高的速度上。這是可行的,而且耗電也不會顯著增加。DDR2的命名與DDR1相仿,只是將因子2替換成4 陣列頻率總線頻率數據率名稱(速率)名稱
(FSB)
133MHz266MHz4,256MB/sPC2-4200DDR2-533
166MHz333MHz5,312MB/sPC2-5300DDR2-667
200MHz400MHz6,400MB/sPC2-6400DDR2-800
250MHz500MHz8,000MB/sPC2-8000DDR2-1000
266MHz533MHz8,512MB/sPC2-8500DDR2-1066
FSB速度是用有效頻率來標記的,即把上升、下降沿均傳輸數據的因素考慮進去,因此數字被撐大了。所以,擁有266MHz總線的133MHz模塊有著533MHz的FSB“頻率” DDR3變化更多,電壓從1.8下降到了1.5于是耗電也變小了,或者說保持相同的耗電,ddr3可以達到更高的頻率或者,保持同樣的熱能釋放,實現容量翻番 DDR3模塊的單元陣列將運行在內部總線的四分之一速度上,DDR3的I/O緩沖區從DDR2的4位提升到8位 DDR3可能會有一個問題,即在1600Mb/s或更高速率下,每個通道的模塊數可能會限制為1。在早期版本中,這一要求是針對所有頻率的。我們希望這個要求可以提高一些,否則系統容量將會受到嚴重的限制。 我們預計中各DDR3模塊的名稱。JEDEC目前同意了前四種。由于Intel的45nm處理器是1600Mb/s的FSB,1866Mb/s可以用于超頻市場。隨著DDR3的發展,可能會有更多類型加入 陣列頻率總線頻率數據速率名稱(速率)名稱
(FSB)
100MHz400MHz6,400MB/sPC3-6400DDR3-800
133MHz533MHz8,512MB/sPC3-8500DDR3-1066
166MHz667MHz10,667MB/sPC3-10667DDR3-1333
200MHz800MHz12,800MB/sPC3-12800DDR3-1600
233MHz933MHz14,933MB/sPC3-14900DDR3-1866
所有的DDR內存都有一個問題:不斷增加的頻率使得建立并行數據總線變得十分困難。一個DDR2模塊有240根引腳。所有到地址和數據引腳的連線必須被布置得差不多一樣長。更大的問題是,如果多于一個DDR模塊通過菊花鏈連接在同一個總線上,每個模塊所接收到的信號隨著模塊的增加會變得越來越扭曲。 DDR2規范允許每條總線(又稱通道)連接最多兩個模塊,DDR3在高頻率下只允許每個通道連接一個模塊。每條總線多達240根引腳使得單個北橋無法以合理的方式驅動兩個通道。替代方案是增加外部內存控制器,但這會提高成本。 一種解法是,在處理器中加入內存控制器 另外一種是,Intel針對大型服務器方面的解法(至少在未來幾年),是被稱為全緩沖DRAM(FB-DRAM)的技術。FB-DRAM采用與DDR2相同的器件,因此造價低廉。不同之處在于它們與內存控制器的連接方式。FB-DRAM沒有用并行總線,而用了串行總線。串行總線可以達到更高的頻率,串行化的負面影響,甚至可以增加帶寬。使用串行總線后
  • 每個通道可以使用更多的模塊。
  • 每個北橋/內存控制器可以使用更多的通道。
  • 串行總線是全雙工的(兩條線)。
  • FB-DRAM只有69個腳。通過菊花鏈方式連接多個FB-DRAM也很簡單。FB-DRAM規范允許每個通道連接最多8個模塊。在對比下雙通道北橋的連接性,采用FB-DRAM后,北橋可以驅動6個通道,而且腳數更少——6x69對比2x240。每個通道的布線也更為簡單,有助于降低主板的成本。全雙工的并行總線過于昂貴。而換成串行線后,這不再是一個問題,因此串行總線按全雙工來設計的,這也意味著,在某些情況下,僅靠這一特性,總線的理論帶寬已經翻了一倍。還不止于此。由于FB-DRAM控制器可同時連接6個通道,因此可以利用它來增加某些小內存系統的帶寬。對于一個雙通道、4模塊的DDR2系統,我們可以用一個普通FB-DRAM控制器,用4通道來實現相同的容量。串行總線的實際帶寬取決于在FB-DRAM模塊中所使用的DDR2(或DDR3)芯片的類型。
    DDR2FB-DRAM
    24069
    通道26
    每通道DIMM數28
    最大內存16GB192GB
    吞吐量~10GB/s~40GB/s
    ? 2.2.5 結論 通過本節,大家應該了解到訪問DRAM的過程并不是一個快速的過程。至少與處理器的速度相比,或與處理器訪問寄存器及緩存的速度相比,DRAM的訪問不算快。大家還需要記住CPU和內存的頻率是不同的。Intel Core 2處理器運行在2.933GHz,而1.066GHz FSB有11:1的時鐘比率(注: 1.066GHz的總線為四泵總線)。那么,內存總線上延遲一個周期意味著處理器延遲11個周期。絕大多數機器使用的DRAM更慢,因此延遲更大。 前文中讀命令的時序圖表明,DRAM模塊可以支持高速數據傳輸。每個完整行可以被毫無延遲地傳輸。數據總線可以100%被占。對DDR而言,意味著每個周期傳輸2個64位字。對于DDR2-800模塊和雙通道而言,意味著12.8GB/s的速率。 但是,除非是特殊設計,DRAM的訪問并不總是串行的。訪問不連續的內存區意味著需要預充電和RAS信號。于是,各種速度開始慢下來,DRAM模塊急需幫助。預充電的時間越短,數據傳輸所受的懲罰越小。 硬件和軟件的預取(參見第6.3節)可以在時序中制造更多的重疊區,降低延遲。預取還可以轉移內存操作的時間,從而減少爭用。我們常常遇到的問題是,在這一輪中生成的數據需要被存儲,而下一輪的數據需要被讀出來。通過轉移讀取的時間,讀和寫就不需要同時發出了 2.3主存的其他用戶 除了CPU外,系統中還有其它一些組件也可以訪問主存。高性能網卡或大規模存儲控制器是無法承受通過CPU來傳輸數據的,它們一般直接對內存進行讀寫(直接內存訪問,DMA)。在圖2.1中可以看到,它們可以通過南橋和北橋直接訪問內存。另外,其它總線,比如USB等也需要FSB帶寬,即使它們并不使用DMA,但南橋仍要通過FSB連接到北橋。 DMA當然有很大的優點,但也意味著FSB帶寬會有更多的競爭。在有大量DMA流量的情況下,CPU在訪問內存時必然會有更大的延遲。我們可以用一些硬件來解決這個問題。例如,通過圖2.3中的架構,我們可以挑選不受DMA影響的節點,讓它們的內存為我們的計算服務。還可以在每個節點上連接一個南橋,將FSB的負荷均勻地分擔到每個節點上。 附A 三極管 有3個極1.發射極(e),基極(b),集電極(c) 輸入特性:當b輸入一定電壓是,發射端導通 輸出特性:當c,e之間加點壓,電流大小,有基極輸入電流控制c和e之間的電流大小 這樣對動態內存單元中的電容來說每次讀取就是一個放過程,所以讀完之后要重新充電

    Memory part 2: CPU caches

    每個程序員都應該了解的 CPU 高速緩存

    3.1 高速緩存的位置 早期的一些系統就是類似的架構。在這種架構中,CPU核心不再直連到主存。數據的讀取和存儲都經過高速緩存。主存與高速緩存都連到系統總線上,這條總線同時還用于與其它組件通信。我們管這條總線叫“FSB”. 在高速緩存出現后不久,系統變得更加復雜。高速緩存與主存之間的速度差異進一步拉大,直到加入了另一級緩存。新加入的這一級緩存比第一級緩存更大,但是更慢。由于加大一級緩存的做法從經濟上考慮是行不通的,所以有了二級緩存,甚至現在的有些系統擁有三級緩存. L1d是一級數據緩存,L1i是一級指令緩存,等等。請注意,這只是示意圖,真正的數據流并不需要流經上級緩存。CPU的設計者們在設計高速緩存的接口時擁有很大的自由。 我們有多核CPU,每個核心可以有多個“線程”。核心與線程的不同之處在于,核心擁有獨立的硬件資源 3.2 高級的緩存操作 默認情況下,CPU核心所有的數據的讀或寫都存儲在緩存中。當然,也有內存區域不能被緩存的 如果CPU需要訪問某個字(word),先檢索緩存。很顯然,緩存不可能容納主存所有內容(否則還需要主存干嘛)。系統用字的內存地址來對緩存條目進行標記。如果需要讀寫某個地址的字,那么根據標簽來檢索緩存即可(后面會介紹還會使用地址來計算緩存的地址) 標簽是需要額外空間的,用字作為緩存的粒度顯然毫無效率。因為標簽可能也有32位(x86上)。內存模塊在傳輸位于同一行上的多份數據時,由于不需要發送新CAS信號,甚至不需要發送RAS信號,因此可以實現很高的效率。基于以上的原因,緩存條目并不存儲單個字,而是存儲若干連續字組成的“線”。在早期的緩存中,線長是32字節,現在一般是64字節。對于64位寬的內存總線,每條線需要8次傳輸。而DDR對于這種傳輸模式的支持更為高效。 當處理器需要內存中的某塊數據時,整條緩存線被裝入L1d。緩存線的地址通過對內存地址進行掩碼操作生成。對于64字節的緩存線,是將低6位置0。這些被丟棄的位作為線內偏移量。其它的位作為標簽,并用于在緩存內定位。在實踐中,我們將地址分為三個部分。32位地址的情況如下: 如果緩存線長度為2O,那么地址的低O位用作線內偏移量。上面的S位選擇“緩存集”。后面我們會說明使用緩存集的原因。現在只需要明白一共有2S個緩存集就夠了。剩下的32 - S - O = T位組成標簽。它們用來同一個cache set中的各條線 當某條指令修改內存時,仍然要先裝入緩存線,因為任何指令都不可能同時修改整條線。因此需要在寫操作前先把緩存線裝載進來。如果緩存線被寫入,但還沒有寫回主存,那就是所謂的“臟了”。臟了的線一旦寫回主存,臟標記即被清除。為了裝入新數據,基本上總是要先在緩存中清理出位置。L1d將內容逐出L1d,推入L2(線長相同)。當然,L2也需要清理位置。于是L2將內容推入L3,最后L3將它推入主存。這種逐出操作一級比一級昂貴。(所以AMD公司通常使用exclusive caches見附錄1,Intel使用inclusive cache) 在對稱多處理器(SMP)架構的系統中,CPU的高速緩存不能獨立的工作。在任何時候,所有的處理器都應該擁有相同的內存內容。保證這樣的統一的內存視圖被稱為“高速緩存一致性”從一個處理器直接訪問另一個處理器的高速緩存這種模型設計代價將是非常昂貴的,它是一個相當大的瓶頸。而是使用,當另一個處理器要讀取或寫入到高速緩存線上時,處理器會去檢測。? 如果CPU檢測到一個寫訪問,而且該CPU的cache中已經緩存了一個cache line的原始副本,那么這個cache line將被標記為無效的cache line。接下來在引用這個cache line之前,需要重新加載該cache line。 更精確的cache實現需要考慮到其他更多的可能性,比如第二個CPU在讀或者寫他的cache line時,發現該cache line在第一個CPU的cache中被標記為臟數據了,此時我們就需要做進一步的處理。在這種情況下,主存儲器已經失效,第二個CPU需要讀取第一個CPU的cache line。通過測試,我們知道在這種情況下第一個CPU會將自己的cache line數據自動發送給第二個CPU。這種操作是繞過主存儲器的,但是有時候存儲控制器是可以直接將第一個CPU中的cache line數據存儲到主存儲器中。對第一個CPU的cache的寫訪問會導致第二個cpu的cache line的所有拷貝被標記為無效。 對于寫入,cpu不需要等待安全的寫入,只要能模擬這個效果,cpu就可以走捷徑 以下是隨機寫入的圖: 圖中有三個比較明顯的不同階段。很正常,這個處理器有L1d和L2,沒有L3。根據經驗可以推測出,L1d有2**13字節,而L2有2**20字節。因為,如果整個工作集都可以放入L1d,那么只需不到10個周期就可以完成操作。如果工作集超過L1d,處理器不得不從L2獲取數據,于是時間飄升到28個周期左右。如果工作集更大,超過了L2,那么時間進一步暴漲到480個周期以上。這時候,許多操作將不得不從主存中獲取數據。更糟糕的是,如果修改了數據,還需要將這些臟了的緩存線寫回內存。(為什么工作集超過了L1d就會從L2中取數若為讀,當讀入的數據不在L1就要向L2獲取,不在L2就要想L3或者內存獲取,工作集越大,導致L1,L2被填滿。若是寫同理學入到臟數據存放在L1中,時間一長L1填滿依次類推3.3 CPU緩存實現的細節 3.3.1 關聯性 我們可以讓緩存的每條線能存放任何內存地址的數據。這就是所謂的全關聯緩存(fully associative cache)。這種緩存方式,如果處理器要訪問某條線,那么需要所有的cacheline的tag和請求的地址比較。 全關聯:優點,可以放任意地址的數據,不會出現類似直接映射一樣的狀況,如果數據分布不均勻導致被換出,從而導致miss增加 缺點,當cpu給出一個地址訪問某一個緩存線,需要掃描所有的緩存 直接映射:優點,電路簡單,查詢某個元素的速度很快。因為一個元素出現在cache的位子是固定的。 缺點,如果數據分布在同一個set那么,會導致miss大大的提高 組關聯:這個是當前普遍的使用方法。是直接映射和全關聯的折中辦法 L2
    Cache
    SizeAssociativityDirect248CL=32CL=64CL=32CL=64CL=32CL=64CL=32CL=64
    512k27,794,59520,422,52725,222,61118,303,58124,096,51017,356,12123,666,92917,029,334
    1M19,007,31513,903,85416,566,73812,127,17415,537,50011,436,70515,162,89511,233,896
    2M12,230,9628,801,4039,081,8816,491,0117,878,6015,675,1817,391,3895,382,064
    4M7,749,9865,427,8364,736,1873,159,5073,788,1222,418,8983,430,7132,125,103
    8M4,731,9043,209,6932,690,4981,602,9572,207,6551,228,1902,111,0751,155,847
    16M2,620,5871,528,5921,958,2931,089,5801,704,878883,5301,671,541862,324
    表說明:關聯度,cache大小,cacheline大小對miss的影響。從上面數據得出的結論是CL64比CL32miss要少,cache越到miss越少,關聯度越高miss越少 圖是表數據的圖標化更容易看出,問題其中CL大小為32。cache size越大miss越少,關聯越大miss 越少 在其他文獻中提到說增加關聯度和增加緩存有相同的效果,這個當然是不正確的看圖中,4m-8m直接關聯和,2路關聯是有一樣的提升,但是當緩存越來越大就不好說了。測試程序的workset只有5.6M,使用8MB之后自然無法體現優勢。但是當workset越來越大,小緩存的關聯性就體現出了巨大的優勢。 隨著多核cpu的出現,相對來說cache的大小就被平分,因此關聯性就顯得比較重要。但是已經到了16路關聯,如果再加顯然比較困難,所以就有廠家開始考慮使用3級緩存。 3.3.2 Cache的性能測試 用于測試程序的數據可以模擬一個任意大小的工作集:包括讀、寫訪問,隨機、連續訪問。在圖3.4中我們可以看到,程序為工作集創建了一個與其大小和元素類型相同的數組: struct l { struct l *n; long int pad[NPAD]; }; 2**N 字節的工作集包含2**N/sizeof(struct l)個元素。顯然sizeof(struct l) 的值取決于NPAD的大小。在32位系統上,NPAD=7意味著數組的每個元素的大小為32字節,在64位系統上,NPAD=7意味著數組的每個元素的大小為64字節。(關于如何CHECK,我還不知道) 單線程順序訪問 最簡單的情況就是遍歷鏈表中順序存儲的節點。無論是從前向后處理,還是從后向前,對于處理器來說沒有什么區別。下面的測試中,我們需要得到處理鏈表中一個元素所需要的時間,以CPU時鐘周期最為計時單元。圖顯示了測試結構。除非有特殊說明, 所有的測試都是在Pentium 4 64-bit 平臺上進行的,因此結構體l中NPAD=0,大小為8字節。 ?? ? ?? ? ?? ? ?順序讀訪問, NPAD=0 ?? ? ?? ? ?? ? ?? ? ?? ? ?? ? ?順序讀多個字節 一開始的兩個測試數據收到了噪音的污染。由于它們的工作負荷太小,無法過濾掉系統內其它進程對它們的影響。我們可以認為它們都是4個周期以內的。這樣一來,整個圖可以劃分為比較明顯的三個部分:
    • 工作集小于2**14字節的。
    • 工作集從2**15字節到2**20字節的。
    • 工作集大于2**21字節的。
    這樣的結果很容易解釋——是因為處理器有16KB的L1d和1MB的L2。 L1d的部分跟我們預想的差不多,在一臺P4上耗時為4個周期左右。但L2的結果則出乎意料。大家可能覺得需要14個周期以上,但實際只用了9個周期。這要歸功于處理器先進的處理邏輯,當它使用連續的內存區時,會 預先讀取下一條緩存線的數據。這樣一來,當真正使用下一條線的時候,其實已經早已讀完一半了,于是真正的等待耗時會比L2的訪問時間少很多。 在工作集超過L2的大小之后,預取的效果更明顯了。前面我們說過,主存的訪問需要耗時200個周期以上。但在預取的幫助下,實際耗時保持在9個周期左右。200 vs 9,效果非常不錯。 在L2階段,三條新加的線基本重合,而且耗時比老的那條線高很多,大約在28個周期左右,差不多就是L2的訪問時間。這表明,從L2到L1d的預取并沒有生效。這是因為,對于最下面的線(NPAD=0),由于結構小,8次循環后才需要訪問一條新緩存線,而上面三條線對應的結構比較大,拿相對最小的NPAD=7來說,光是一次循環就需要訪問一條新線,更不用說更大的NPAD=15和31了。而預取邏輯是無法在每個周期裝載新線的,因此每次循環都需要從L2讀取,我們看到的就是從L2讀取的時延。 (有一點想不通作者這里說是28個周期是L2的訪問時間,但是上面為什么說是14個周期,有一種不靠譜的感覺。元素大小太大導致預取效果很差,但是順序的訪問方式很容易被預取,為什么不沒有呢,作者的觀點是預取邏輯是無法在每個周期裝載新線的所以導致預取無效) 另一個導致慢下來的原因是TLB緩存的未命中。TLB是存儲虛實地址映射的緩存。為了保持快速,TLB只有很小的容量。如果有大量頁被反復訪問,超出了TLB緩存容量,就會導致反復地進行地址翻譯,這會耗費大量時間。TLB查找的代價分攤到所有元素上,如果元素越大,那么元素的數量越少,每個元素承擔的那一份就越多。 為了觀察TLB的性能,我們可以進行另兩項測試。第一項:我們還是順序存儲列表中的元素,使NPAD=7,讓每個元素占滿整個cache line,第二項:我們將列表的每個元素存儲在一個單獨的頁上,忽略每個頁沒有使用的部分以用來計算工作集的大小。結果表明,第一項測試中,每次列表的迭代都需要一個新的cache line,而且每64個元素就需要一個新的頁。第二項測試中,每次迭代都會訪問一個cache,都需要加載一個新頁。 圖 3.12: TLB 對順序讀的影響 基于可用RAM空間的有限性,測試設置容量空間大小為2的24次方字節,這就需要1GB的容量將對象放置在分頁上。NPAD等于7的曲線。我們看到不同的步長顯示了高速緩存L1d和L2的大小。第二條曲線看上去完全不同,其最重要的特點是當工作容量到達2的13次方字節時開始大幅度增長。這就是TLB緩存溢出的時候。我們能計算出一個64字節大小的元素的TLB緩存有64個輸入。成本不會受頁面錯誤影響,因為程序鎖定了存儲器以防止內存被換出。可以看出,計算物理地址并把它存儲在TLB中所花費的周期數量級是非常高的。從中可以清楚的得到:TLB緩存效率降低的一個重要因素是大型NPAD值的減緩。由于物理地址必須在緩存行能被L2或主存讀取之前計算出來,地址轉換這個不利因素就增加了內存訪問時間。這一點部分解釋了為什么NPAD等于31時每個列表元素的總花費比理論上的RAM訪問時間要高。 ? ? ? ? ??圖3.13 NPAD等于1時的順序讀和寫 所有情況下元素寬度都為16個字節。第一條曲線“Follow”是熟悉的鏈表走線在這里作為基線。第二條曲線,標記為“Inc”,僅僅在當前元素進入下一個前給其增加thepad[0]成員。第三條曲線,標記為"Addnext0", 取出下一個元素的thepad[0]鏈表元素并把它添加為當前鏈表元素的thepad[0]成員。 在沒運行時,大家可能會以為"Addnext0"更慢,因為它要做的事情更多——在沒進到下個元素之前就需要裝載它的值。但實際的運行結果令人驚訝——在某些小工作集下,"Addnext0"比"Inc"更快。這是為什么呢?原因在于,系統一般會對下一個元素進行強制性預取。當程序前進到下個元素時這個元素其實早已被預取在L1d里。但是,"Addnext0"比"Inc"更快離開L2,這是因為它需要從主存裝載更多的數據。而在工作集達到2 21字節時,"Addnext0"的耗時達到了28個周期,是同期"Follow"14周期的兩倍。這個兩倍也很好解釋。"Addnext0"和"Inc"涉及對內存的修改,因此L2的逐出操作不能簡單地把數據一扔了事,而必須將它們寫入內存。因此FSB的可用帶寬變成了一半,傳輸等量數據的耗時也就變成了原來的兩倍。 ? ? ?? ? ?圖3.14: 更大L2/L3緩存的優勢 決定順序式緩存處理性能的另一個重要因素是緩存容量。雖然這一點比較明顯,但還是值得一說。圖中展示了128字節長元素的測試結果(64位機,NPAD=15)。這次我們比較三臺不同計算機的曲線,兩臺P4,一臺Core 2。兩臺P4的區別是緩存容量不同,一臺是32k的L1d和1M的L2,一臺是16K的L1d、512k的L2和2M的L3。Core 2那臺則是32k的L1d和4M的L2。 圖中最有趣的地方,并不是Core 2如何大勝兩臺P4,而是工作集開始增長到連末級緩存也放不下、需要主存熱情參與之后的部分。與我們預計的相似,最末級緩存越大,曲線停留在L2訪問耗時區的時間越長。在2**20字節的工作集時,第二臺P4(更老一些)比第一臺P4要快上一倍,這要完全歸功于更大的末級緩存。而Core 2拜它巨大的4M L2所賜,表現更為卓越。 單線程隨機訪問模式的測量 圖3.15: 順序讀取vs隨機讀取,NPAD=0 如果換成隨機訪問或者不可預測的訪問,情況就大不相同了。圖3.15比較了順序讀取與隨機讀取的耗時情況。 換成隨機之后,處理器無法再有效地預取數據,只有少數情況下靠運氣剛好碰到先后訪問的兩個元素挨在一起的情形。 圖3.15中有兩個需要關注的地方。 首先,在大的工作集下需要非常多的周期。這臺機器訪問主存的時間大約為200-300個周期,但圖中的耗時甚至超過了450個周期。我們前面已經觀察到過類似現象(對比圖3.11)。這說明,處理器的自動預取在這里起到了反效果。 其次,代表隨機訪問的曲線在各個階段不像順序訪問那樣保持平坦,而是不斷攀升。為了解釋這個問題,我們測量了程序在不同工作集下對L2的訪問情況。結果如圖3.16和表3.2。 ? ? ?? ? ?圖3.16: L2d未命中率 Set
    SizeSequentialRandomL2 HitL2 Miss#IterRatio Miss/HitL2 Accesses Per IterL2 HitL2 Miss#IterRatio Miss/HitL2 Accesses Per Iter
    22088,63684316,3840.94%5.530,46247211,02413.42%34.4
    22188,1051,5848,1921.77%10.921,81715,15151240.98%72.2
    22288,1061,6004,0961.78%21.922,25822,28525650.03%174.0
    22388,1041,6142,0481.80%43.827,52126,27412848.84%420.3
    22488,1141,6551,0241.84%87.733,16629,1156446.75%973.1
    22588,1121,7305121.93%175.539,85832,3603244.81%2,256.8
    22688,1121,9062562.12%351.648,53938,1511644.01%5,418.1
    22788,1142,2441282.48%705.962,42352,049845.47%14,309.0
    22888,1202,939643.23%1,422.881,90687,167451.56%42,268.3
    22988,1374,318324.67%2,889.2119,079163,398257.84%141,238.5
    表3.2: 順序訪問與隨機訪問時L2命中與未命中的情況,NPAD=0 從圖中可以看出,當工作集大小超過L2時,未命中率(L2未命中次數/L2訪問次數)開始上升。整條曲線的走向與圖3.15有些相似: 先急速爬升,隨后緩緩下滑,最后再度爬升。它與耗時圖有緊密的關聯。L2未命中率會一直爬升到100%為止。只要工作集足夠大(并且內存也足夠大),就可以將緩存線位于L2內或處于裝載過程中的可能性降到非常低。 (工作集越大,隨機訪問,命中率就會越小) 圖3.17: 頁意義上(Page-Wise)的隨機化,NPAD=7 而換成隨機訪問后,單位耗時的增長超過了工作集的增長,根源是TLB未命中率的上升。圖3.17描繪的是NPAD=7時隨機訪問的耗時情況。這一次,我們修改了隨機訪問的方式。正常情況下是把整個列表作為一個塊進行隨機(以∞表示),而其它11條線則是在小一些的塊里進行隨機。例如,標簽為'60'的線表示以60頁(245760字節)為單位進行隨機。先遍歷完這個塊里的所有元素,再訪問另一個塊。這樣一來,可以保證任意時刻使用的TLB條目數都是有限的。(也就是上圖的性能差距主要來自于TLB的未命中率) NPAD=7對應于64字節,正好等于緩存線的長度。由于元素順序隨機,硬件預取不可能有任何效果,特別是在元素較多的情況下。這意味著,分塊隨機時的L2未命中率與整個列表隨機時的未命中率沒有本質的差別。隨著塊的增大,曲線逐漸逼近整個列表隨機對應的曲線。這說明,在這個測試里,性能受到TLB命中率的影響很大,如果我們能提高TLB命中率,就能大幅度地提升性能(在后面的一個例子里,性能提升了38%之多)。(作者在這里突出當元素長度>=cache line 長度的時候并且元素是隨機訪問硬件預取失效,為什么?我根據作者提供的結構體加上vtune,當結構體大小剛好為64B的時候并沒有發現L1的miss3.3.3 寫入時的行為 為了保持cache和內存的一致性,當cache被修改后,我們要刷新到主存中(flush),可以通過2種方式實現:1.write through(寫透),2.write back(寫回) 寫透是當修改cache會立刻寫入到主存, 缺點:速度慢,占用FSB總線 優點:實現簡單 寫回是當修改cache后不是馬上寫入到主存,而是打上已弄臟(dirty)的標記。當以后某個時間點緩存線被丟棄時,這個已弄臟標記會通知處理器把數據寫回到主存中,而不是簡單地扔掉。 優點:速度快 缺點:當有多個處理器(或核心、超線程)訪問同一塊內存時,必須確保它們在任何時候看到的都是相同的內容。如果緩存線在其中一個處理器上弄臟了(修改了,但還沒寫回主存),而第二個處理器剛好要讀取同一個內存地址,那么這個讀操作不能去讀主存,而需要讀第一個處理器的緩存線。 3.3.4 多處理器支持 直接提供從一個處理器到另一處理器的高速訪問,這是完全不切實際的。從一開始,連接速度根本就不夠快。實際的選擇是,在其需要的情況下,轉移到其他處理器 現在的問題是,當該高速緩存線轉移的時候會發生什么?這個問題回答起來相當容易:當一個處理器需要在另一個處理器的高速緩存中讀或者寫的臟的高速緩存線的時候。但怎樣處理器怎樣確定在另一個處理器的緩存中的高速緩存線是臟的?假設它僅僅是因為一個高速緩存線被另一個處理器加載將是次優的(最好的)。通常情況下,大多數的內存訪問是只讀的訪問和產生高速緩存線,并不臟。在高速緩存線上處理器頻繁的操作(當然,否則為什么我們有這樣的文件呢?),也就意味著每一次寫訪問后,都要廣播關于高速緩存線的改變將變得不切實際。 人們開發除了MESI緩存一致性協議(MESI=Modified, Exclusive, Shared, Invalid,變更的、獨占的、共享的、無效的)。協議的名稱來自協議中緩存線可以進入的四種狀態:
    • 變更的: 本地處理器修改了緩存線。同時暗示,它是所有緩存中唯一的拷貝。
    • 獨占的: 緩存線沒有被修改,而且沒有被裝入其它處理器緩存。
    • 共享的: 緩存線沒有被修改,但可能已被裝入其它處理器緩存。
    • 無效的: 緩存線無效,即,未被使用。
    MESI協議開發了很多年,最初的版本比較簡單,但是效率也比較差。現在的版本通過以上4個狀態可以有效地實現寫回式緩存,同時支持不同處理器對只讀數據的并發訪問。 (寫回如何被實現,通過監聽其處理器的狀態) 在協議中,通過處理器監聽其它處理器的活動,不需太多努力即可實現狀態變更。處理器將操作發布在外部引腳上,使外部可以了解到處理過程。 一開始,所有緩存線都是空的,緩存為無效(Invalid)狀態。當有數據裝進緩存供寫入時,緩存變為變更(Modified)狀態。如果有數據裝進緩存供讀取,那么新狀態取決于其它處理器是否已經狀態了同一條緩存線。如果是,那么新狀態變成共享(Shared)狀態,否則變成獨占(Exclusive)狀態。 如果本地處理器對某條Modified緩存線進行讀寫,那么直接使用緩存內容,狀態保持不變。如果另一個處理器希望讀它,那么第一個處理器將內容發給第二個處理器,然后可以將緩存狀態置為Shared。而發給第二個處理器的數據由內存控制器接收,并放入內存中。如果這一步沒有發生,就不能將這條線置為Shared。如果第二個處理器希望的是寫,那么第一個處理器將內容發給它后,將緩存置為Invalid。這就是臭名昭著的"請求所有權(Request For Ownership,RFO)"操作。在末級緩存執行RFO操作的代價比較高。如果是寫通式緩存,還要加上將內容寫入上一層緩存或主存的時間,進一步提升了代價。 對于Shared緩存線,本地處理器的讀取操作并不需要修改狀態,而且可以直接從緩存滿足。而本地處理器的寫入操作則需要將狀態置為Modified,而且需要將緩存線在其它處理器的所有拷貝置為Invalid。因此,這個寫入操作需要通過RFO消息發通知其它處理器。如果第二個處理器請求讀取,無事發生。因為主存已經包含了當前數據,而且狀態已經為Shared。如果第二個處理器需要寫入,則將緩存線置為Invalid。不需要總線操作。 Exclusive狀態與Shared狀態很像,只有一個不同之處: 在Exclusive狀態時,本地寫入操作不需要在總線上聲明,因為本地的緩存是系統中唯一的拷貝。這是一個巨大的優勢,所以處理器會盡量將緩存線保留在Exclusive狀態,而不是Shared狀態。只有在信息不可用時,才退而求其次選擇shared。放棄Exclusive不會引起任何功能缺失,但會導致性能下降,因為E→M要遠遠快于S→M。 從以上的說明中應該已經可以看出,在多處理器環境下,哪一步的代價比較大了。填充緩存的代價當然還是很高,但我們還需要留意RFO消息。一旦涉及RFO,操作就快不起來了。 RFO在兩種情況下是必需的:
    • 線程從一個處理器遷移到另一個處理器,需要將所有緩存線移到新處理器。
    • 某條緩存線確實需要被兩個處理器使用。{對于同一處理器的兩個核心,也有同樣的情況,只是代價稍低。RFO消息可能會被發送多次。}
    緩存一致性協議的消息必須發給系統中所有處理器。只有當協議確定已經給過所有處理器響應機會之后,才能進行狀態躍遷。也就是說,協議的速度取決于最長響應時間。 對同步來說,有限的帶寬嚴重地制約著并發度。程序需要更加謹慎的設計,將不同處理器訪問同一塊內存的機會降到最低。 多線程測量 ? ? ?? ? ?圖3.19: 順序讀操作,多線程 圖3.19展示了順序讀訪問時的性能,元素為128字節長(64位計算機,NPAD=15)。對于單線程的曲線,我們預計是與圖3.11相似,只不過是換了一臺機器,所以實際的數字會有些小差別。 更重要的部分當然是多線程的環節。由于是只讀,不會去修改內存,不會嘗試同步。但即使不需要RFO,而且所有緩存線都可共享,性能仍然分別下降了18%(雙線程)和34%(四線程)。由于不需要在處理器之間傳輸緩存,因此這里的性能下降完全由以下兩個瓶頸之一或同時引起: 一是從處理器到內存控制器的共享總線,二是從內存控制器到內存模塊的共享總線。 ? ? ?? ? ?圖3.20: 順序遞增,多線程 我們用對數刻度來展示L1d范圍的結果。可以發現,當超過一個線程后,L1d就無力了。單線程時,僅當工作集超過L1d時訪問時間才會超過20個周期,而多線程時,即使在很小的工作集情況下,訪問時間也達到了那個水平。 ? ? ?? ? ?圖3.21: 隨機的Addnextlast,多線程 最后,在圖3.21中,我們展示了隨機訪問的Addnextlast測試的結果。這里主要是為了讓大家感受一下這些巨大到爆的數字。極端情況下,甚至用了1500個周期才處理完一個元素。如果加入更多線程,真是不可想象哪。 ? ? ?圖3.22: 通過并行化實現的加速因子 圖3.22中的曲線展示了加速因子,即多線程相對于單線程所能獲取的性能加成值。測量值的精確度有限,因此我們需要忽略比較小的那些數字。可以看到,在L2與L3范圍內,多線程基本可以做到線性加速,雙線程和四線程分別達到了2和4的加速因子。但是,一旦工作集的大小超出L3,曲線就崩塌了,雙線程和四線程降到了基本相同的數值(參見表3.3中第4列)。也是部分由于這個原因,我們很少看到4CPU以上的主板共享同一個內存控制器。如果需要配置更多處理器,我們只能選擇其它的實現方式(參見第5節)。 特例: 超線程 它真正的優勢在于,CPU可以在當前運行的超線程發生延遲時,調度另一個線程。這種延遲一般由內存訪問引起。 如果兩個線程運行在一個超線程核心上,那么只有當兩個線程合起來的運行時間少于單線程運行時間時,效率才會比較高 程序的執行時間可以通過一個只有一級緩存的簡單模型來進行估算(參見[htimpact]): T??exe??= N[(1-F??mem?)T??proc??+ F??mem?(G??hit?T??cache??+ (1-G??hit?)T??miss?)] 各變量的含義如下:
    N=指令數
    Fmem=N中訪問內存的比例
    Ghit=命中緩存的比例
    Tproc=每條指令所用的周期數
    Tcache=緩存命中所用的周期數
    Tmiss=緩沖未命中所用的周期數
    Texe=程序的執行時間
    (也就是說在命中的時間+非命中的時間) 圖?3.23: 最小緩存命中率-加速 紅色區域為單線程的命中率,綠色為雙線程,比如 如果單線程命中率不低于60%,那么雙線程就不能低于10%。綠色區域是我們要達到的目標, 因此,超線程只在某些情況下才比較有用。單線程代碼的緩存命中率必須低到一定程度,從而使緩存容量變小時新的命中率仍能滿足要求。只有在這種情況下,超線程才是有意義的。在實踐中,采用超線程能否獲得更快的結果,取決于處理器能否有效地將每個進程的等待時間與其它進程的執行時間重疊在一起。并行化也需要一定的開銷,需要加到總的運行時間里,這個開銷往往是不能忽略的。 3.3.5 其它細節 我們已經介紹了地址的組成,即標簽、集合索引和偏移三個部分。那么,實際會用到什么樣的地址呢?目前,處理器一般都向進程提供虛擬地址空間,意味著我們有兩種不同的地址: 虛擬地址和物理地址。 虛擬地址有個問題——并不唯一。隨著時間的變化,虛擬地址可以變化,指向不同的物理地址。 處理器指令用的虛擬地址,而且需要在內存管理單元(MMU)的協助下將它們翻譯成物理地址。這并不是一個很小的操作。在執行指令的管線(pipeline)中,物理地址只能在很后面的階段才能得到。這意味著,緩存邏輯需要在很短的時間里判斷地址是否已被緩存過。而如果可以使用虛擬地址,緩存查找操作就可以更早地發生,一旦命中,就可以馬上使用內存的內容。結果就是,使用虛擬內存后,可以讓管線把更多內存訪問的開銷隱藏起來。 處理器的設計人員們現在使用虛擬地址來標記第一級緩存。 對于更大的緩存,包括L2和L3等,則需要以物理地址作為標簽。因為這些緩存的時延比較大,虛擬到物理地址的映射可以在允許的時間里完成,而且由于主存時延的存在,重新填充這些緩存會消耗比較長的時間,刷新的代價比較昂貴。(刷新就是寫入到內存) 一般來說,我們并不需要了解這些緩存處理地址的細節。我們不能更改它們,而那些可能影響性能的因素,要么是應該避免的,要么是伴隨更高代價的。填滿緩存是不好的行為,緩存線都落入同一個集合,也會讓緩存早早地出問題。(和關聯性相關)對于后一個問題,可以通過cache address中使用虛擬地址來避免(如何避免,依靠系統?),但作為一個用戶級程序,是不可能避免緩存物理地址的。我們唯一可以做的,是盡最大努力不要在同一個進程里用多個虛擬地址映射同一個物理地址(避免同一個數據在cache中有多個記錄)。 3.4 指令緩存 其實,不光處理器使用的數據被緩存,它們執行的指令也是被緩存的。只不過,指令緩存的問題相對來說要少得多,因為:
    • 執行的代碼量取決于代碼大小。而代碼大小通常取決于問題復雜度。問題復雜度則是固定的。
    • 程序的數據處理邏輯是程序員設計的,而程序的指令卻是編譯器生成的。編譯器的作者知道如何生成優良的代碼。
    • 程序的流向比數據訪問模式更容易預測。現如今的CPU很擅長模式檢測,對預取很有利。
    • 代碼永遠都有良好的時間局部性和空間局部性。
    有一些準則是需要程序員們遵守的,但大都是關于如何使用工具的,我們會在第6節介紹它們。而在這里我們只介紹一下指令緩存的技術細節。 隨著CPU的核心頻率大幅上升,緩存與核心的速度差越拉越大,CPU的處理開始管線化。也就是說,指令的執行分成若干階段。首先,對指令進行解碼,隨后,準備參數,最后,執行它。這樣的管線可以很長(例如,Intel的Netburst架構超過了20個階段)。在管線很長的情況下,一旦發生延誤(即指令流中斷),需要很長時間才能恢復速度。管線延誤發生在這樣的情況下: 下一條指令未能正確預測,或者裝載下一條指令耗時過長(例如,需要從內存讀取時)。 3.4.1 自修改的代碼 3.5 緩存未命中的因素 我們已經看過內存訪問沒有命中緩存時,那陡然猛漲的高昂代價。但是有時候,這種情況又是無法避免的,因此我們需要對真正的代價有所認識,并學習如何緩解這種局面。 3.5.1 緩存與內存帶寬? 圖3.24: P4的帶寬 當工作集能夠完全放入L1d時,處理器的每個周期可以讀取完整的16字節數據,即每個周期執行一條裝載指令(moveaps指令,每次移動16字節的數據)。測試程序并不對數據進行任何處理,只是測試讀取指令本身。當工作集增大,無法再完全放入L1d時,性能開始急劇下降,跌至每周期6字節。在218工作集處出現的臺階是由于DTLB緩存耗盡,因此需要對每個新頁施加額外處理。由于這里的讀取是按順序的,預取機制可以完美地工作,而FSB能以5.3字節/周期的速度傳輸內容。但預取的數據并不進入L1d(放不進L1D放去了哪里?)。當然,真實世界的程序永遠無法達到以上的數字,但我們可以將它們看作一系列實際上的極限值 更令人驚訝的是寫操作和復制操作的性能。即使是在很小的工作集下,寫操作也始終無法達到4字節/周期的速度。這意味著,Intel為Netburst處理器的L1d選擇了寫通(write-through)模式,所以寫入性能受到L2速度的限制。同時,這也意味著,復制測試的性能不會比寫入測試差太多(復制測試是將某塊內存的數據拷貝到另一塊不重疊的內存區),因為讀操作很快,可以與寫操作實現部分重疊。最值得關注的地方是,兩個操作在工作集無法完全放入L2后出現了嚴重的性能滑坡,降到了0.5字節/周期!比讀操作慢了10倍!(慢在哪里?)顯然,如果要提高程序性能,優化這兩個操作更為重要 圖3.25采用了與圖3.24相同的刻度,以方便比較兩者的差異。圖3.25中的曲線抖動更多,是由于采用雙線程的緣故。結果正如我們預期,由于超線程共享著幾乎所有資源(僅除寄存器外),所以每個超線程只能得到一半的緩存和帶寬。所以,即使每個線程都要花上許多時間等待內存,從而把執行時間讓給另一個線程,也是無濟于事——因為另一個線程也同樣需要等待。這里恰恰展示了使用超線程時可能出現的最壞情況。 寫/復制操作的性能與P4相比,也有很大差異。處理器沒有采用寫通策略,寫入的數據留在L1d中,只在必要時才逐出。這使得寫操作的速度可以逼近16字節/周期。一旦工作集超過L1d,性能即飛速下降。由于Core 2讀操作的性能非常好,所以兩者的差值顯得特別大。當工作集超過L2時,兩者的差值甚至超過20倍!但這并不表示Core 2的性能不好,相反,Core 2永遠都比Netburst強。 圖3.27: Core 2運行雙線程時的帶寬表現 在圖3.27中,啟動雙線程,各自運行在Core 2的一個核心上。它們訪問相同的內存,但不需要完美同步。從結果上看,讀操作的性能與單線程并無區別,只是多了一些多線程情況下常見的抖動。 當工作集小于L1d時,寫操作與復制操作的性能很差,就好像數據需要從內存讀取一樣。兩個線程彼此競爭著同一個內存位置,于是不得不頻頻發送RFO消息。問題的根源在于,雖然兩個核心共享著L2,但無法以L2的速度處理RFO請求。 當工作集小于L1d時,寫操作與復制操作的性能很差,就好像數據需要從內存讀取一樣。兩個線程彼此競爭著同一個內存位置,于是不得不頻頻發送RFO消息。問題的根源在于,雖然兩個核心共享著L2,但無法以L2的速度處理RFO請求。而當工作集超過L1d后,性能出現了迅猛提升。這是因為,由于L1d容量不足,于是將被修改的條目刷新到共享的L2。由于L1d的未命中可以由L2滿足,只有那些尚未刷新的數據才需要RFO,所以出現了這樣的現象。這也是這些工作集情況下速度下降一半的原因。 圖3.28展示了AMD家族10h Opteron處理器的性能。這顆處理器有64kB的L1d、512kB的L2和2MB的L3,其中L3緩存由所有核心所共享。 圖3.28: AMD家族10h Opteron的帶寬表現 大家首先應該會注意到,在L1d緩存足夠的情況下,這個處理器每個周期能處理兩條指令。讀操作的性能超過了32字節/周期,寫操作也達到了18.7字節/周期。但是,不久,讀操作的曲線就急速下降,跌到2.3字節/周期,非常差。處理器在這個測試中并沒有預取數據,或者說,沒有有效地預取數據。 另一方面,寫操作的曲線隨幾級緩存的容量而流轉。在L1d階段達到最高性能,隨后在L2階段下降到6字節/周期,在L3階段進一步下降到2.8字節/周期,最后,在工作集超過L3后,降到0.5字節/周期。它在L1d階段超過了Core 2,在L2階段基本相當(Core 2的L2更大一些),在L3及主存階段比Core 2慢。 圖3.29: AMD Fam 10h在雙線程時的帶寬表現 讀操作的性能沒有受到很大的影響。每個線程的L1d和L2表現與單線程下相仿,L3的預取也依然表現不佳。兩個線程并沒有過渡爭搶L3。問題比較大的是寫操作的性能。兩個線程共享的所有數據都需要經過L3,而這種共享看起來卻效率很差。即使是在L3足夠容納整個工作集的情況下,所需要的開銷仍然遠高于L3的訪問時間。再來看圖3.27,可以發現,在一定的工作集范圍內,Core 2處理器能以共享的L2緩存的速度進行處理。而Opteron處理器只能在很小的一個范圍內實現相似的性能,而且,它僅僅只能達到L3的速度,無法與Core 2的L2相比。 3.5.2 關鍵字加載 事實上,內存控制器可以按不同順序去請求緩存線中的字。當處理器告訴它,程序需要緩存中具體某個字,即「關鍵字(critical word)」時,內存控制器就會先請求這個字。一旦請求的字抵達,雖然緩存線的剩余部分還在傳輸中,緩存的狀態還沒有達成一致,但程序已經可以繼續運行。這種技術叫做關鍵字優先及較早重啟(Critical Word First & Early Restart)。 圖3.30: 關鍵字位于緩存線尾時的表現 圖3.30展示了下一個測試的結果,圖中表示的是關鍵字分別在線首和線尾時的性能對比情況。元素大小為64字節,等于緩存線的長度。圖中的噪聲比較多,但仍然可以看出,當工作集超過L2后,關鍵字處于線尾情況下的性能要比線首情況下低0.7%左右。 3.5.3 緩存設定 關于各種處理器模型的優點,已經在它們各自的宣傳手冊里寫得夠多了。在每個核心的工作集互不重疊的情況下,獨立的L2擁有一定的優勢,單線程的程序可以表現優良。考慮到目前實際環境中仍然存在大量類似的情況,這種方法的表現并不會太差。不過,不管怎樣,我們總會遇到工作集重疊的情況。如果每個緩存都保存著某些通用運行庫的常用部分,那么很顯然是一種浪費。 如果像Intel的雙核處理器那樣,共享除L1外的所有緩存,則會有一個很大的優點。如果兩個核心的工作集重疊的部分較多,那么綜合起來的可用緩存容量會變大,從而允許容納更大的工作集而不導致性能的下降。如果兩者的工作集并不重疊,那么則是由Intel的高級智能緩存管理(Advanced Smart Cache management)發揮功用,防止其中一個核心壟斷整個緩存。 圖3.31: 兩個進程的帶寬表現 這次,測試程序兩個進程,第一個進程不斷用SSE指令讀/寫2MB的內存數據塊,選擇2MB,是因為它正好是Core 2處理器L2緩存的一半,第二個進程則是讀/寫大小變化的內存區域,我們把這兩個進程分別固定在處理器的兩個核心上。圖中顯示的是每個周期讀/寫的字節數,共有4條曲線,分別表示不同的讀寫搭配情況。例如,標記為讀/寫(read/write)的曲線代表的是后臺進程進行寫操作(固定2MB工作集),而被測量進程進行讀操作(工作集從小到大)。 圖中最有趣的是2**20到2**23之間的部分。如果兩個核心的L2是完全獨立的,那么所有4種情況下的性能下降均應發生在221到222之間,也就是L2緩存耗盡的時候。但從圖上來看,實際情況并不是這樣,特別是背景進程進行寫操作時尤為明顯。當工作集達到1MB(220)時,性能即出現惡化,兩個進程并沒有共享內存,因此并不會產生RFO消息。所以,完全是緩存逐出操作引起的問題。目前這種智能的緩存處理機制有一個問題,每個核心能實際用到的緩存更接近1MB,而不是理論上的2MB。 3.5.4 FSB的影響 FSB在性能中扮演了核心角色。緩存數據的存取速度受制于內存通道的速度。 圖3.32: FSB速度的影響 圖上的數字表明,當工作集大到對FSB造成壓力的程度時,高速FSB確實會帶來巨大的優勢。在我們的測試中,性能的提升達到了18.5%,接近理論上的極限。而當工作集比較小,可以完全納入緩存時,FSB的作用并不大。 附錄1 exclusive caches:就是所有的緩存中只保留一份緩存線。 好處:能存更多的數據。壞處:當L1 miss,L2 hit后,L2要把數據交換到L1上,這個操作比copy的花費要大 inclusive caches:上一級緩存有的必須在本緩存中出現一份備份 好處:當刪除一個緩存線的時候只需要掃描L2的緩存線就可以了,不需要再去掃描L1的緩存線 如果在二級緩存很大,并且cache數據比tag還要大,tags的空間就可以被節省下來,在L2中保留跟多的L1數據 壞處:如果當L2的關聯性比L1差,L1的關聯性會被L2影響(不清楚狀況) 當L2的緩存線要被換出,L1的也需要被換出,可能會再次L1的miss率上升

    ?

    Memory part 3: Virtual Memory

    4 虛擬內存 4.1 簡單的地址轉化 MMU會把地址映射到基于頁的方式,想cache line的地址虛擬地址也被分為幾個部分,使用這些部分用來構建最后的物理地址 圖中前版部分指向了一個頁表,頁表中包含了物理內存頁的地址,然后再通過offset計算出頁內的偏移。這就就是一個物理地址了 頁表的被保存在內存中,OS分配一個連續的物理內存并且把基地址存入寄存器中。虛擬地址前部分被作為頁表的index 4.2多級頁表 一般頁大小是4KB,那么也就是2**12還有2**20,如果每個項為4B,那么就需要4MB大小的頁表,很不靠譜。所以分為了多級增加了頁表的緊湊性,并且頁保證了多個程序下對性能的影響不會太大。 4級頁表,是最復雜的4個頁表被分在不同的4個寄存器上,Level1是局部物理地址加上安全選項 和上面的類似,唯一不同的是多級頁表是分為多次,最后查詢到物理地址。每個進程都有自己的頁表,所以為了性能和可擴展性盡量保持較小的頁表。把虛擬地址放在一起,這樣可以減少頁表空間。小的程序只會使用頁表的很少的部分。 在現實中,因為安全性的關系可執行程序的多個部分被隨機分散到各處。若是性能比安全重要,也可以關閉隨機。 4.3 優化頁表訪問 頁表是維護在內存中的,但是需要4次訪問內存還是很慢的,訪問cache,4次訪問也是很慢的。每個絕對地址的計算都需要大量的訪問頁表4頁表級別的至少要12個cpu周期,并且可能會導致L1miss,導致管線斷裂。 所以并不緩存頁表,而是緩存計算后的物理地址。因為offset并不參與緩存。放翻譯結果的叫做TLB,很快但是也很小,現代的CPU都有提供多級的TLB,并使用LRU算法,當前,TLB引入了組相連,所以并不是最老的就會被代替了。 Tag是虛擬地址的一部分用來訪問TLB,如果找到再加上offset就是物理地址了。在某些情況下二級的TLB中沒有找到,就必須通過頁表計算,這個將是代價非常高的操作。在預取操作的時候為TLB預取是不行的,(硬件預取)只能通過指令預取才有TLB預取。 4.3.1 TLB注意事項 TLB是內核全局資源所有的線程,進程都運行在同一個TLB上,CPU不能盲目的重用,因為存的是虛擬地址會出現重復的情況。 所以有一下2個方法: 1.當頁表被修改后刷新TLB數據 2.用一個標記來識別TLB中的頁表 第一個是不行的頁表會在上下文切換的時候被天,刷新會把可能可以繼續使用的也刷新掉了 有些cpu結構優化了,把某個區間內的刷新掉,所以代價不是很高 最優的方法是新增一個唯一識別符。但是有個問題是TLB能給的標記有限,有些標示必須能夠重用,當TLB出現刷新的時候,所有的重用都要被刷新掉。 使用標記的好處是如果當前使用的被調出,下次再被調度的時候TLB任然可以使用,出了這個還有另外2個好處: 1.內核或者VMM使用通常只需要很短的時間。沒有tag會執行2次刷新,如果有tag地址就會被保留,因為內核和vmm并不經常修改tlb,所以上次保存的任然可以使用 2.若一個進程的2個線程進行切換,那么就沒有必要刷新。 4.3.2 TLB的性能影響 首先就是頁的大小,頁越大減少了轉化過程,減少了在TLB的容量 但是大的頁在物理內存上必須連續,這樣會造成內存浪費。 在x86-64中2MB的頁,是有多個小的頁組成,這些小的頁在物理上市連續的。當系統運行了一段時間后,發現要分配2MB的連續內存空間變得十分困難 在linux中會在系統啟動時使用hugetlbfs文件系統預先保留,如果要增加就必須重啟系統。大的頁可以提升性能,在資源豐富,但是安裝麻煩也不是很大的問題。比如數據庫系統。 增加最小虛擬頁的大小也是有問題,內存映射操作驗證這些頁的大小,不能讓更小的出現,若大小超過了可執行文件或者DSO的考慮范圍,就無法加載。 第二個影響就是頁表級別減少,因為需要參與映射的位數減少,減少了TLB中的使用空間,也減少了需要移動的數據。只是對對齊的需求比較大。TLB少了性能自然變好。 4.4 虛擬化的影響 VMM只是個軟件,并不實現硬件的控制。在早期,內存和處理器之外的硬件都控制在DOM0中。現在Dom0和其他的Dom一樣,在內存的控制上沒有什么區別。 為了實現虛擬化,Dom0,DomU的內核直接訪問物理內存是被限制的。而是使用頁表結構來控制Dom0,DomU上的內存使用。 不管是軟件虛擬還是硬件虛擬,用戶域中的為每個進程創建的頁表和硬件虛擬,軟件虛擬是類似的。當用戶OS修改了這些頁表,VMM就會被調用,根據修改的信息,來修改VMM中的影子頁表(本來應該是硬件處理),每次修改都需要調用VMM顯然是一個代價很高的操作。 為了減少這個代價,intel 引入了EPT,AMD引入了NPT,2個功能一樣,就是為VMM生產虛擬的物理地址,當使用內存的時候,cpu參與把這些地址進一步翻譯為物理地址,這樣就可以再非虛擬話的速度來運行,更多的vmm中關于內存控制的項被刪除,減少了vmm的內存使用,vmm只需要為每個Dom保留一份頁表即可。 為了更高效的使用TLB,就加入了ASID在初始化處理器的時候生產用于TLB的擴展,來避免TLB的刷新,intel引入了VPID(虛擬處理器的id)來避免TLB的刷新。 基于VMM的虛擬機,多有2層內存控制,vmm和os需要實現一模一樣的功能 基于KVM的虛擬機就解決了這個問題,KVM虛擬機并不是和VMM一樣運行在VMM上的,而是直接運行的內核的上面,使用內核的內存管理,虛擬化被KVM VMM進程控制。盡管還是有個2個內存控制,但是工作都是在內核中實現的,不需要再VMM再實現一遍。 虛擬化的內存訪問肯定比非虛擬話代價高,而且越去解決問題,可能代價會更高,cpu視圖解決這個問題,但是只能減弱,并不能徹底解決

    Memory part 4: NUMA support

    5. NUMA的支持 NUMA因為的特色的體系設計,所以需要OS和應用程序做特別的支持 5.1 NUMA硬件 NUMA最大的特點是CPU直接連接內存,這樣讓cpu訪問本地的內存代價就很低,但是訪問遠程的代價就變高。 NUMA主要解決,大內存,多CPU環境下,解決,多個CPU同時訪問內存,導致內存總線熱點,或者某個內存模塊熱點,從而降低吞吐量 AMD公司提出了一個Hypertransport的傳輸技術,讓CPU通過這個傳輸技術訪問內存,而不是直接訪問內存。 圖5.1 立方體 這些節點的拓撲圖就是立方體,限制了節點的大小2**C,C是節點的互連接口個數。對于2**n個cpu立方體擁有最小的直徑(任意2點的距離) 缺點就是不能支持大量的CPU。 接下來就是給cpu分組,實現它們之間的內存共享問題,所有這樣的系統都需要特殊的硬件,2臺這樣的機器可以通過共享內存,實現和工作在一臺機器上一樣。互連在NUMA中是一個很重要的因素,所以系統和應用程序必須考慮到這一點 5.2 OS對NUMA的支持 為了讓NUMA盡量使用本地的內存,這里有個特殊的例子只會在NUMA體系結構中出現。DSO的文本段在內存中,但是所有cpu都要使用,這就以為這基本上都要使用遠程訪問。最理想的狀態是對所有需要訪問的做一個鏡像,但是很難實現。 為了避免類似的情況,應該防止經常切換到其他節點運行,從一個cpu切換到另外一個就以為這cache內容的丟失,如果要遷移,OS會選擇一個任務的選擇一個,但是在NUMA結構體系下,選擇是有一些限制的,新的處理器內存的訪問代價一定要比老的低,如果沒有可用的處理器符合這個條件,os就沒得選擇只能切換到一個代價較高的。 在這個狀況下有2種方向,1.只是臨時的切換,2.遷移并且把內存也遷移走(頁遷移代價太高,需要做大量的復制工作,進程也必須停止,等待數據頁遷移完畢,應該避免這種情況的發送) 我們不應該假設應用程序都使用相同大小的內存,一些程序使用大量內存,一些使用小量的,如果都是用本地,遲早本地內存會被耗盡。 為了解決這個問題,有個方法就是讓內存條帶化,但是缺點就是因為遷移,導致內存訪問的開銷變大。 5.3 相關信息 內核發布了一些關于處理器cache的信息(通過sysfs) /sys/devices/system/cpu/cpu*/cache 這里包含了資料叫做index*,列出了CPU進程的一些信息。
    ?typelevelshared_cpu_map
    cpu0index0Data100000001
    index1Instruction100000001
    index2Unified200000003
    cpu1index0Data100000002
    index1Instruction100000002
    index2Unified200000003
    cpu2index0Data100000004
    index1Instruction100000004
    index2Unified20000000c
    cpu3index0Data100000008
    index1Instruction100000008
    index2Unified20000000c
    表5.1 sysfs中雙核cpu cache信息 每個內核都有L1i,L1D,L2。L1不和其他cpu共享。cpu0和cpu1共享L2,cpu2和cpu3共享L2 以下是4路雙核cpu的cache信息

    ?

    ?typelevelshared_cpu_map
    cpu0index0Data100000001
    index1Instruction100000001
    index2Unified200000001
    cpu1index0Data100000002
    index1Instruction100000002
    index2Unified200000002
    cpu2index0Data100000004
    index1Instruction100000004
    index2Unified200000004
    cpu3index0Data100000008
    index1Instruction100000008
    index2Unified200000008
    cpu4index0Data100000010
    index1Instruction100000010
    index2Unified200000010
    cpu5index0Data100000020
    index1Instruction100000020
    index2Unified200000020
    cpu6index0Data100000040
    index1Instruction100000040
    index2Unified200000040
    cpu7index0Data100000080
    index1Instruction100000080
    index2Unified200000080
    圖5.2 Opteron CPU cache信息 和圖5.1類似,但是看表就會發現L2不和任何cpu共享 /sys/devices/system/cpu/cpu*/topology顯示了sysfs關于CPU拓撲信息
    ?physical_
    package_idcore_idcore_
    siblingsthread_
    siblings
    cpu0000000000300000001
    cpu110000000300000002
    cpu2100000000c00000004
    cpu310000000c00000008
    cpu4200000003000000010
    cpu510000003000000020
    cpu630000000c000000040
    cpu71000000c000000080
    圖5.3 Opteron CPU拓撲信息 因為thread_sinlings都是設置了一個bit,所以沒有超線程,是一個4個cpu每個cpu有2個內核。 /sys/devices/system/node這個目錄下包含了系統中NUMA的信息,表5.4顯示了總要的信息
    ?cpumapdistance
    node00000000310 20 20 20
    node10000000c20 10 20 20
    node20000003020 20 10 20
    node3000000c020 20 20 10
    圖5.4 sysfs Opteron 節點信息 上圖顯示了,cpu只有4個,有4個節點,distance表示了,他們訪問內存的花費(這個是不正確的,cpu中至少有一個是連接到南橋的,所以花費可能不止20.) 5.4 遠程訪問開銷 圖5.3 多個節點的讀寫性能 讀性能優于寫,這個可以預料,2個1hop性能有一點小差別,這個不是關鍵,關鍵是2hop性能大概比0hop低了30%到49%,寫的性能2-hop比0-hop少了32%,比1-hop少了17%,下一代AMD處理器hypertransport將是4個,對于4路的cpu,間距就是1。但是8路的cpu還是有相同的問題,因為立方體中8節點的間距還是3. 最后一部分信息是來自PID文件的 00400000 default file=/bin/cat mapped=3 N3=3 00504000 default file=/bin/cat anon=1 dirty=1 mapped=2 N3=2 00506000 default heap anon=3 dirty=3 active=0 N3=3 38a9000000 default file=/lib64/ld-2.4.so mapped=22 mapmax=47 N1=22 38a9119000 default file=/lib64/ld-2.4.so anon=1 dirty=1 N3=1 38a911a000 default file=/lib64/ld-2.4.so anon=1 dirty=1 N3=1 38a9200000 default file=/lib64/libc-2.4.so mapped=53 mapmax=52 N1=51 N2=2 38a933f000 default file=/lib64/libc-2.4.so 38a943f000 default file=/lib64/libc-2.4.so anon=1 dirty=1 mapped=3 mapmax=32 N1=2 N3=1 38a9443000 default file=/lib64/libc-2.4.so anon=1 dirty=1 N3=1 38a9444000 default anon=4 dirty=4 active=0 N3=4 2b2bbcdce000 default anon=1 dirty=1 N3=1 2b2bbcde4000 default anon=2 dirty=2 N3=2 2b2bbcde6000 default file=/usr/lib/locale/locale-archive mapped=11 mapmax=8 N0=11 7fffedcc7000 default stack anon=2 dirty=2 N3=2 N0-N3表示了不同的節點,后面表示在各個節點開辟的內存頁數 從圖5.3中,我們發現讀性能下降了9%-30%,如果L2失效,要用遠程的內存,那么將會增加9%-30%的開銷。 圖5.4遠程內存的操作 這里讀取性能降低了20%,但是前面圖5.3中是9%,差距怎么大,想是使用老的cpu(這些圖來自AMD的amdccnuma文檔,只有AMD知道怎么回事兒了)(我特意去查了amdccnuma并沒有以上2個圖) 寫和復制操作也是20%,當工作集超過cache時,讀寫操作就不比本地的慢了,主要原因是訪問主存的開銷(不明白,感覺沒有講清楚

    Memory part 5: What programmers can do

    6 程序員應該做什么 6.1 繞過Cache line 對于并不是馬上要使用的數據,先讀取在修改并不利于性能,因為這樣會讓cache效果變低。比如矩陣寫入最后一個的時候第一個常常因為不太使用被犧牲掉了。 所以有了非臨時寫入,直接把數據寫入到內存。因為處理器會使用write-combining,使得寫入開銷并不是很大。 #include <emmintrin.h> void setbytes(char *p, int c) {__m128i i = _mm_set_epi8(c, c, c, c,c, c, c, c,c, c, c, c,c, c, c, c);_mm_stream_si128((__m128i *)&p[0], i);_mm_stream_si128((__m128i *)&p[16], i);_mm_stream_si128((__m128i *)&p[32], i);_mm_stream_si128((__m128i *)&p[48], i); } 因為寫入綁定寫入只在最后一條指令發送,直接寫入不但避免了先讀后修改,也避免了污染cache 下面測試矩陣訪問的2中方式:行訪問,列訪問 主要的區別是行訪問是順序的,但是列訪問時隨機的。 圖 6-1矩陣訪問模式

    Inner Loop Increment?RowColumn
    Normal0.048s0.127s
    Non-Temporal0.048s0.160s
    直接寫入內存和手動寫入幾乎一樣快,主要原因是使用了write-combining,還有就是寫入并不在乎順序,這樣處理器就可以直接寫回,盡可能的使用帶寬。 列訪問方式,并沒有write-combining,內存單元必須一個一個寫入,因為是隨機的。當在內存芯片上寫入新行也需要選擇這一行,有相關的延遲。 在讀入方面還沒有非零食訪問的預取,需要通過指令顯示預取,intel實現了NTA load,實現一個buffer load,每個buffer大小為一個cache line。 現在cpu對非cache數據,順序訪問訪問做了很好的優化,也可以通過cache,對內存的隨機訪問降低開銷。 6.2 Cache Access 6.2.1 優化L1D訪問 通過demo的修改,來提高L1D的訪問,demo實現以下功能: 代碼: for (i = 0; i < N; ++i)for (j = 0; j < N; ++j)for (k = 0; k < N; ++k)res[i][j] += mul1[i][k] * mul2[k][j]; 從代碼中看到mul2的訪問方式是列的方式,基本上都是隨機的,那么我們可以先轉化以下再計算: double tmp[N][N];for (i = 0; i < N; ++i)for (j = 0; j < N; ++j)tmp[i][j] = mul2[j][i];for (i = 0; i < N; ++i)for (j = 0; j < N; ++j)for (k = 0; k < N; ++k)res[i][j] += mul1[i][k] * tmp[j][k]; 測試結果: ? ? ??? ? ??? ? ??? ? ??Original? ? ? ? ?TransposedCyclesRelative
    16,765,297,8703,922,373,010
    100%23.4%
    轉化后,性能高了76.6%,主要是非順序訪問引起。 為了和cache line對齊,可以再對代碼修改: #define SM (CLS / sizeof (double))for (i = 0; i < N; i += SM)for (j = 0; j < N; j += SM)for (k = 0; k < N; k += SM)for (i2 = 0, rres = &res[i][j],rmul1 = &mul1[i][k]; i2 < SM;++i2, rres += N, rmul1 += N)for (k2 = 0, rmul2 = &mul2[k][j];k2 < SM; ++k2, rmul2 += N)for (j2 = 0; j2 < SM; ++j2)rres[j2] += rmul1[k2] * rmul2[j2]; 性能如下:
    ?OriginalTransposedSub-MatrixVectorizedCyclesRelative
    16,765,297,8703,922,373,0102,895,041,4801,588,711,750
    100%23.4%17.3%9.47%
    和轉化比性能有了6.1%的提升,最后一個是向量結果 代碼如下: #include <stdlib.h> #include <stdio.h> #include <emmintrin.h> #define N 1000 double res[N][N] __attribute__ ((aligned (64))); double mul1[N][N] __attribute__ ((aligned (64))); double mul2[N][N] __attribute__ ((aligned (64))); #define SM (CLS / sizeof (double))
    int main (void) {// ... Initialize mul1 and mul2
    int i, i2, j, j2, k, k2;double *restrict rres;double *restrict rmul1;double *restrict rmul2;for (i = 0; i < N; i += SM)for (j = 0; j < N; j += SM)for (k = 0; k < N; k += SM)for (i2 = 0, rres = &res[i][j], rmul1 = &mul1[i][k]; i2 < SM;++i2, rres += N, rmul1 += N){_mm_prefetch (&rmul1[8], _MM_HINT_NTA);for (k2 = 0, rmul2 = &mul2[k][j]; k2 < SM; ++k2, rmul2 += N){__m128d m1d = _mm_load_sd (&rmul1[k2]);m1d = _mm_unpacklo_pd (m1d, m1d);for (j2 = 0; j2 < SM; j2 += 2){__m128d m2 = _mm_load_pd (&rmul2[j2]);__m128d r2 = _mm_load_pd (&rres[j2]);_mm_store_pd (&rres[j2],_mm_add_pd (_mm_mul_pd (m2, m1d), r2));}}}
    // ... use res matrix
    return 0; } 對于寫入大量數據,但是同時使用到很少數據的情況是很常見的如圖就是這種情況: 順序訪問和隨機的訪問在L2緩存之前都很容易理解,但是超過L2之后,回到了10%不是因為開銷變小,是因為內存訪問開銷太大,已經不成比例了(有點沒法理解,為什么會不成比例)。 軟件pahole可以從代碼級分析這個結構體可能會用幾個cacheline struct foo {int a;long fill[7];int b; }; 在編譯的時候需要帶上調試信息才行,我是在linux 下使用。 struct foo {int a; /* 0 4 *//* XXX 4 bytes hole, try to pack */long int fill[7]; /* 8 56 *//* --- cacheline 1 boundary (64 bytes) --- */int b; /* 64 4 */ }; /* size: 72, cachelines: 2 *//* sum members: 64, holes: 1, sum holes: 4 *//* padding: 4 *//* last cacheline: 8 bytes */ 上面的信息清晰,這個結構體需要2個cache line,大小為72字節,成員大小64字節,空的字節:4個,有1個空洞 元素b也是4個字節,作者這里說因為int 4個字節要和long 對齊所以被浪費了有個4字節是為了和fill對齊。但是我自己在測試的時候沒有發現這種情況,在虛擬機上測試的。 使用pahole可以輕易的對元素重排,并且可以確認,那些元素在一個cache line上。結構體中的元素順序很重要,所以開發人員需要遵守以下2個規則: 1.把可能是關鍵字的放到結構體的頭部 2.若沒有特定的順序,就以結構體元素的順序訪問元素 對于小的結構體可以隨意的排列結構體順序,但是對于大的結構體需要有一些規則 如果本身不是對齊的結構體,那么重新排序沒有什么太大的價值,對于結構化的類型,結構體中最大的元素決定了結構體的對齊。即使結構體小于cache line,但是對齊后可能就比cache line 大。有2個方法確保結構體設置的時候對齊。 1.顯示的對齊請求,動態的malloc分配,通常要那些和對齊匹配的通常是標準的類型(如long,double)。也可以使用posix_memalign做更高級別的對齊。若是編譯器分配的,變量可以使用變量屬性struct strtype variable??__attribute((aligned(64)));這樣這個變量以64為字節對齊 使用posix_memalign會導致碎片產生,并可能讓內存浪費。使用變量屬性對齊不能使用在數組中,除非數組元素都是對齊的。 2.對于類型的對齊可以使用類型屬性 struct strtype {...members...} __attribute((aligned(64))); 這樣設置之后所有編譯器分配的對象都是對齊的,包括數組,但是用malloc分配的不是對齊的,還是posix_memalign對齊,可以使用gcc的alignof傳入用于第二個參數。 x86,x86-64處理器支持對非對齊訪問但是比較慢,對于RISC來說對齊并不是什么新鮮事,RISC指令本身都是對齊的,有些結構體系支持非對齊的訪問,但是速度總是比對齊的慢。 如圖是對齊訪問和非對齊訪問的對比,有意思的地方是當work set超過2mb的時候開始下滑,是因為,內存訪問變多,并且內存訪問的時間占的比重大。 關于對齊必須認真對待,竟然支持非對齊訪問,但是性能也不能可能比對齊好。 對齊也是有副作用的,如使用了自動變量對齊,那么就需要在所有用到的地方都要對齊,但是編譯器無法控制調用和堆棧,所以有2個解決方法。 1.代碼和堆棧對齊,有必要的話就填充空白.2.所有的調用都要對齊。 對于調用對齊,如果被調用要求對齊,但是調用者不對其的話就會出錯。 對于和堆棧對齊,堆棧幀沒必要是對齊大小的整數倍,所以要填充空白,編譯器是知道堆棧幀大小的,所以可以處理。 當要對VLA(通過變量決定數組長度),或者alloca的變量對齊,大小只能在運行的時候知道,所以對他們做對齊可能會照成代碼變慢,因為生產了其他代碼。 gcc提供了一個選項可以更靈活的設置stack的對齊, -mpreferred-stack-boundary =N,這個N表示對齊為2的N次。 在編譯x86程序的時候設置這個參數為2,可以減少stack的使用并提高代碼執行速度。 對于86-64,調用ABI,浮點類型,是通過SSE寄存器和SSE指令需要16個字節對齊。 對齊只是優化性能的一個方面 對于比較大的workset,重新整理數據結構是很有必要的。不是把所有的元素都放在一個結構體中,而是更具常用程度,進程組織。 若數據集中在同一個cache set中會導致conflict misses。 圖中:x表示list中2個元素的距離,y表示list總長度,z表示運行時間 當list的所有元素都在一個cache set的時候,元素個數高于關聯度時,訪問就要從L2中讀取增加了讀取時間,這就是圖中顯示的特點。(能猜測數據時均勻的分布在L1每個cache set中,能力有限未能重現conflict miss)。非對齊的訪問或增加cache line 的conflict miss。 總結:對于data cache訪問主要的優化方式是1.順序訪問(提高預取性能)2.對齊(和cache line,減少cache讀取次數) 3.減少結構體對cache的占用(也是為了減少cache讀取) 4.減少conflict miss ? 6.2.2 優化L1指令cache訪問 因為通過編譯器處理,所以程序員并不能直接的控制代碼,線性讓處理器可以高效獲取指令,但是如果有jump會打破這個線性,因為:1.jump是動態的,2.如果出現miss就會花費很長的時間恢復(因為pipeline)。 主要問題還是在分支預測上的成功率,分支預測在運行到這個指令之前會先把指令取來,如果預測錯誤,就會花費比較大的時間。 1.減少代碼大小,注意loop unrolling 和inlining的代碼量。 內聯對代碼分支預測有好處,但是如果內聯代碼過大,或者被對此調用反而會增加code的大小。 2.盡量線性執行,讓pipleline不會出現斷的情況 碰到跳轉,要不太執行的塊移動到外面,在gcc 中可以使用, #define unlikely(expr) __builtin_expect(!!(expr), 0) #define likely(expr) __builtin_expect(!!(expr), 1) 并且在編譯的時候使用 -freorder-blocks對代碼進行重排,還有另一選項 -freorder-blocks-and-partition 但是有使用限制,其不能和exception handling 一起使用 inter core2對于小的順序引入了一個基數LSD(loop stream detector),如果循環指令不超過18個,這個LSD,需要4個decoder,最多4個跳轉指令,執行64次以上, 那么??就會被鎖定在指令隊列中,下次運行就會變得很快。 3.如果有意義就使用代碼對齊 對齊的意義在于能夠形成順序的指令流,對齊可以讓預取更加有效。也就意味著讓decode更加有效。若出現miss,那么pipeline就會斷開。 從以下幾點對齊代碼比較有效:1.函數的開始,2.基本代碼塊的開始,3.循環的開始。 在第一點和第二點的優化中,編譯器往往通過插入nop指令,來對齊,所以有一些開銷。 對于第三點,有點不同的是,在循環之前往往是其他的順序的代碼,如果,其他代碼和循環之間有空隙,那么必須使用nop或者跳轉到循環的開始,若循環有不常執行, 那么nop和jump就會很浪費,比非對齊的開銷還要多。 -falign-functions = N,對函數的對齊,對齊2的N次 -falign-jumps = N ,對跳轉的對齊 -falign-loops = N對循環的對齊 ? 6.2.3 優化L2的cache訪問 L1的優化和L2差不多,但是L2的特點是:1.如果miss了,代價很高,因為可能要訪問內存了。2.L2cache通常是內核共享或者超線程共享的。 由于l2cache 差異較大,并且,并不是都引用于數據的。所以需要一個動態的計算每個線程或者內核的最低安全限制, cache結構在Linux下可在 /sys/devices/system/cpu/cpu*/cache。 ? 6.2.4 優化TLB使用 要有話TLB,1.減少內存使用,2.減少查找代價,減少被分配的頁表的個數。 ASLR會導致頁表過多,因為ASLR會讓stack,DSO,heap隨機在執行的是否分配。為了性能可以把ASLR關掉,但是少了安全性。 還有一種方法是mmap的MAP_FIXED選項來分配內存地址,但是十分危險,只有在開發指導最后一級頁表的邊界,并能夠選擇合適地址的前提下使用。 6.3預取 6.3.1 硬件預取 只有2次以上的miss才會除非預取,單個的miss觸發預取會照成性能問題,隨機的內存訪問預取會對fsb照成沒必要的浪費。 L2或更高的預取可以和其他內核或者超線程共享,prefetch不能越過一個頁 因為硬件預取不懂語義,可能引起page fault或者fetch一個并不需要的頁。 在不需要的時候引起prefetch 需要調整程序結構才能解決 在指令中插入未定義指令是一種解決方法,體系結構提供全部或者部分關閉prefetch 6.3.2 軟件預取 硬件預取的好處是:不需要軟件處理,缺點:預取不能超過1頁。而軟件預取需要源代碼配合。 #include <xmmintrin.h> enum _mm_hint {_MM_HINT_T0 = 3,_MM_HINT_T1 = 2,_MM_HINT_T2 = 1,_MM_HINT_NTA = 0 }; void _mm_prefetch(void *p, enum _mm_hint h); 以上的命令會把指針的內容預取到cache中。如果沒有可用空間了,那么會犧牲掉其他數據,沒不要的預取應該要避免,不然反而會增加帶寬的消耗。 _MM_HINT_T0,_MM_HINT_T1,_MM_HINT_T2,_MM_HINT_NTA,分別預取到L1,L2,L3,?_MM_HINT_NTA的NTA是non-temporal access的縮寫,告訴處理器盡量避免訪問這個數據,因為只是短時間使用,所以處理器如果是包含性的就不讀取到低級的cache中,如果從L1d中犧牲,不需要推到L2中,而是直接寫入內存。要小心使用,如果work set太大,犧牲了很多cache line,這些cache line 由要從內存中加載,有些得不償失了。 圖中使用NPAD=31 每個元素大小為128,只有8%的提升,很不明顯。加入預取代碼效果不是很明顯,可以使用性能計數器,在需要的位子上面加預取。 -fprefetch-loop-arrays是GCC提供的編譯選項 其將為優化數組循環插入prefetch指令,對于小的循環就沒有好處,要小心使用 6.3.3 特殊類型的預取:推測(speculation) 主要的用處是在其他不相關的代碼中映入預取,來hide延遲 6.3.4 幫助thread 把預取放在代碼中會讓邏輯變得很復雜,可以使用其他處理器來做幫助thread,幫忙預取數據。難度是不能太慢,也不能太快,增加L1i的有效性。 1.使用超線程,可以預取到l2,升至l1 2.使用dumber線程,只做簡單的讀取和預取操作 上圖看到性能有提升。 可以通過libNUMA中的函數,來知道cache的共享信息 #include <libNUMA.h> ssize_t NUMA_cpu_level_mask(size_t destsize,cpu_set_t *dest,size_t srcsize,const cpu_set_t*src,unsigned int level); cpu_set_t self;NUMA_cpu_self_current_mask(sizeof(self),&self);cpu_set_t hts;NUMA_cpu_level_mask(sizeof(hts), &hts,sizeof(self), &self, 1);CPU_XOR(&hts, &hts, &self); self 是當前的內核,hts是可以被用來做help線程的內核。 ? 6.3.5直接cache訪問 現代的硬件可以直接寫入到內存,但是對于馬上要使用的數據,就會出現miss,所以intel有了一個技術,可以直接報包的數據寫入到cache中。使用DCA(direct cache access)來標記這個包,寫在包頭中,如圖: 左右沒有使用DCA標記,右圖有DCA標記, DCA標記如果fsb識別那么就直接傳入到L1cache中了。這個功能需要所有硬件都有相關功能才能使用。

    Memory part 6: More things programmers can do

    6.4多線程優化 關于多線程的優化,主要從以下3方面展開 1.并發 2.原子性 3.帶寬 ? 6.4.1 并發優化 通常cache的優化是那數據盡量放在一起,減少代碼footprint,能夠最大化的把內存放到cache中,但是多線程往往訪問相似的數據,這樣會導致,如果一個線程對一個內存進行修改請求,cache line 必須是 獨占(E)狀態,這就意味著要做RFO。就算所有的線程使用獨立的內存,并且是獨立的還是可能會出現這種狀況。 上圖測試在4個P4處理器上進行,在第9.3中有這個測試的demo,代碼主要是做對一個內存做5000W次的自增,藍色的值表示,線程在分開的cache上自增,紅色的表示在同一個cache上自增。 當線程寫入一個cache是,所有的其他cache都會被延遲,并且cache是獨立的。造成紅色部分比藍色部分高的原因。 上圖是intel core2 QX6700 上的測試,4核有2個獨立的L2,并沒有出現這個問題,原因就是cache是共享的。 簡單的解決問題的方法:把變量放到線程各自的cache line中,線程變量。 1.把讀寫的變量和只讀的變量發開存放。也可以用來解決讀多寫少的變量。 2.會被同時使用的變量放到一個結構體上,用結構體來保證,變量在比較近的。 3.把被不同線程讀寫的變量寫入到他們自己的cache line中。 int foo = 1; int baz = 3;struct {struct al1 {int bar;int xyzzy;};char pad[CLSIZE - sizeof(struct al1)];} rwstruct __attribute__((aligned(CLSIZE))) ={ { .bar = 2, .xyzzy = 4 } }; 4.把被多線程使用,但是使用都是獨立的變量放入各自線程中,如: int foo = 1; __thread int bar = 2;int baz = 3; __thread int xyzzy = 4; 6.4.2 原子優化 作者只介紹了原子操作的相關操作,并說盡量減少原子操作。 6.4.3 帶寬沖突 每個處理器都有與內存連接的帶寬,由于體系結構的不同,多個處理器可能共享一個總線或者北橋。那么就可能會出現帶寬的爭用問題。 1.買速度快的服務器,如果重寫程序比較昂貴的情況下 2.優化程序避免miss,調度器并不清楚workload,只能收集到cache miss,很多情況下并沒有什么幫助 3.盡量讓cache存儲變得更有效,讓處理器處理一塊數據。 cache使用效率低下 cache 使用效率高 調度器不知道workload,所以需要開發人員自己設置調度。 進程調度: ? ?? #define _GNU_SOURCE #include <sched.h>int sched_setaffinity(pid_t pid, size_t size, const cpu_set_t *cpuset); int sched_getaffinity(pid_t pid, size_t size, cpu_set_t *cpuset); 線程的調度: #define _GNU_SOURCE #include <pthread.h>int pthread_setaffinity_np(pthread_t th, size_t size,const cpu_set_t *cpuset); int pthread_getaffinity_np(pthread_t th, size_t size, cpu_set_t *cpuset); int pthread_attr_setaffinity_np(pthread_attr_t *at,size_t size, const cpu_set_t *cpuset); int pthread_attr_getaffinity_np(pthread_attr_t *at, size_t size, cpu_set_t *cpuset); 6.5 NUMA編程 NUMA的特點是:cpu內訪內存時,節點訪問代價高,非跨節點代價低。 2個線程在同一個內核中使用相同的cache協作比使用獨立的cache要快。 6.5.1 內存策略 對于numa來說內存的訪問,尤為重要,所有出了個內存策略也就是內存分配策略,具體說就是在哪里分配內存。 linux 內核支持的策略種類: 1.MPOL_BIND:在給定的node中分配,如果不行則失敗 2.MPOL_PREFERRED:首選在給定的節點分配,失敗考慮其他節點 3.MPOL_INTERLEAVE:通過虛擬地址區域,決定在哪個節點上分配 4.MPOL_DUFAULT:在default區域上分配 以上的遞歸的方法定義策略只是對了一半,其實,內存策略的有個一個框圖: 若地址落在VMA上那么,使用VMA策略,若在共享上,那么使用ShMem Policy,如果,這個地址沒有指定策略,那么使用task policy,如果定義了task policy那么就task policy處理,如果沒有就system default policy處理。 6.5.2 指定策略 #include <numaif.h>long set_mempolicy(int mode, unsigned long *nodemask, unsigned long maxnode); 通過以上方法來設置task policy 6.5.3 交換和策略 交換后,內存中的節點信息就會消失,對于一個多處理器共享的頁來說隨著時間的推移,相關性就會被改變, 6.5.4 VMA Policy 通過函數來裝載 VMA Policy #include <numaif.h>long mbind(void *start, unsigned long len,int mode,unsigned long *nodemask,unsigned long maxnode,unsigned flags); VMA區域是 start,start+len mode 就是前面提到的4個策略 flag參數: MPOL_MF_STRICT:如果mbind中的地址不在nodemask中,就報錯 MPOL_MF_MOVE:如果有地址不在這個node上,試圖移動。 MPOL_MF_MOVEALL:會移動所有,不單單是這個進程用到的頁表,這個參數會影響其他進程的訪問 對于一個已經保留了地址,但是沒有分配的地址空間,可以使用mbind但是不帶參數。 6.5.5 查詢節點信息 獲取numa策略 #include <numaif.h> long get_mempolicy(int *policy,const unsigned long *nmask,unsigned long maxnode,void *addr, int flags); 通過虛擬地址查詢節點信息 #include <libNUMA.h>int NUMA_mem_get_node_idx(void *addr); int NUMA_mem_get_node_mask(void *addr,size_t size,size_t __destsize,memnode_set_t *dest); 查詢cpu對應的節點 #include <libNUMA.h>int NUMA_cpu_to_memnode(size_t cpusetsize,const cpu_set_t *cpuset,size_t memnodesize,memnode_set_t *memnodeset); #include <libNUMA.h>int NUMA_memnode_to_cpu(size_t memnodesize,const memnode_set_t *memnodeset,size_t cpusetsize,cpu_set_t *cpuset); 6.5.6 cpu和節點設置 使用cpuset來限制用戶或者程序對cpu和內存的使用。 6.5.7 顯示優化NUMA 當內地內存和affinity規則,如果所有的線程要訪問同一個地址,那么訪問本地內存,和affinity是沒有效果的。 對于只讀的內存可以直接使用復制,把數據復制到要用的節點。 但是對于可讀寫的就比較麻煩,如果計算不依賴于上次的結果,可以把各個節點的計算累計到各個node上,然后再寫入內存。 如果訪問內存是固定的,遷移到本地node中,如果訪問很高,但是非本地訪問減少,那么就是有用的。但是要注意,頁遷移還是有不小的開銷的。 6.5.8?利用所有帶寬 在圖5.4中,訪問遠程和本地并沒有明顯的差距,這個是因為,把寫入不再使用的數據,通過內存附加,寫入到了其他節點上去了,因為帶寬連接DRAM和cpu之間的內部連接是一樣的,所以,看不出來性能的差距。 利用所有的帶寬是很多方面的:一個就是確定cache是無效的,因為需要通過遠程來放置,另外一個是遠程內存是否需要帶寬


    ? ? 本文轉自 Fanr_Zh 博客園博客,原文鏈接:http://www.cnblogs.com/Amaranthus/p/3180036.html,如需轉載請自行聯系原作者

    總結

    以上是生活随笔為你收集整理的What every programmer should know about memory 笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    网友自拍区视频精品 | 欧洲精品码一区二区三区免费看 | 国产午夜手机精彩视频 | 无码乱肉视频免费大全合集 | 欧美人与禽猛交狂配 | 人妻尝试又大又粗久久 | 乱人伦人妻中文字幕无码 | 天天综合网天天综合色 | 麻豆av传媒蜜桃天美传媒 | 亚洲精品中文字幕乱码 | 青青草原综合久久大伊人精品 | 国产精品亚洲综合色区韩国 | 天天爽夜夜爽夜夜爽 | 午夜无码人妻av大片色欲 | 55夜色66夜色国产精品视频 | 国产在热线精品视频 | 国产精品福利视频导航 | 高清国产亚洲精品自在久久 | 人妻插b视频一区二区三区 | 欧美阿v高清资源不卡在线播放 | 97久久国产亚洲精品超碰热 | 日韩少妇内射免费播放 | 国产成人无码av一区二区 | 国产高清av在线播放 | 2019午夜福利不卡片在线 | 亚洲 另类 在线 欧美 制服 | 亚洲精品国偷拍自产在线麻豆 | 乌克兰少妇xxxx做受 | 欧美成人午夜精品久久久 | 国产人妻大战黑人第1集 | 欧美自拍另类欧美综合图片区 | 欧美黑人性暴力猛交喷水 | 全球成人中文在线 | 中文毛片无遮挡高清免费 | 夫妻免费无码v看片 | 久久亚洲a片com人成 | 成人欧美一区二区三区黑人免费 | 麻豆国产人妻欲求不满谁演的 | 国产内射爽爽大片视频社区在线 | 国产欧美精品一区二区三区 | 国产一区二区三区日韩精品 | 午夜精品久久久久久久 | 亚洲精品中文字幕乱码 | 精品一区二区三区波多野结衣 | 国产无遮挡又黄又爽又色 | 久久精品人妻少妇一区二区三区 | 好爽又高潮了毛片免费下载 | 乱人伦人妻中文字幕无码 | 九九久久精品国产免费看小说 | 人妻有码中文字幕在线 | 无码乱肉视频免费大全合集 | 色五月丁香五月综合五月 | 成 人影片 免费观看 | 欧洲vodafone精品性 | 无码av免费一区二区三区试看 | 日本精品人妻无码77777 天堂一区人妻无码 | 日韩精品无码一本二本三本色 | 国产后入清纯学生妹 | 国产成人综合美国十次 | 久久天天躁狠狠躁夜夜免费观看 | yw尤物av无码国产在线观看 | 三级4级全黄60分钟 | 成熟女人特级毛片www免费 | 综合网日日天干夜夜久久 | 久久久成人毛片无码 | 装睡被陌生人摸出水好爽 | 成 人影片 免费观看 | 久久精品中文闷骚内射 | 一本久久伊人热热精品中文字幕 | 丰满少妇人妻久久久久久 | 亚洲欧美日韩成人高清在线一区 | 午夜时刻免费入口 | 在线 国产 欧美 亚洲 天堂 | 午夜精品一区二区三区的区别 | 欧美国产亚洲日韩在线二区 | 99久久无码一区人妻 | 国产av人人夜夜澡人人爽麻豆 | 成人女人看片免费视频放人 | 一区二区传媒有限公司 | 免费无码午夜福利片69 | 7777奇米四色成人眼影 | 日本精品人妻无码免费大全 | 精品国偷自产在线 | 亚拍精品一区二区三区探花 | 鲁大师影院在线观看 | 日本一区二区三区免费播放 | 青青草原综合久久大伊人精品 | 少妇无码一区二区二三区 | 日日碰狠狠躁久久躁蜜桃 | 国产欧美熟妇另类久久久 | 欧洲熟妇色 欧美 | 欧美阿v高清资源不卡在线播放 | 成人无码视频在线观看网站 | 中文字幕无码视频专区 | 国产亚洲精品久久久闺蜜 | 久青草影院在线观看国产 | 老太婆性杂交欧美肥老太 | 性欧美疯狂xxxxbbbb | 久久国产自偷自偷免费一区调 | 国产又爽又猛又粗的视频a片 | 午夜福利试看120秒体验区 | 欧美成人免费全部网站 | 国产高潮视频在线观看 | 国产熟女一区二区三区四区五区 | 麻豆av传媒蜜桃天美传媒 | 欧美精品一区二区精品久久 | 欧美 日韩 人妻 高清 中文 | 亚洲狠狠色丁香婷婷综合 | 成年美女黄网站色大免费视频 | 天天摸天天碰天天添 | 伊人久久大香线焦av综合影院 | 中文亚洲成a人片在线观看 | 少妇被黑人到高潮喷出白浆 | 国产成人无码专区 | 亚洲狠狠婷婷综合久久 | 小sao货水好多真紧h无码视频 | 久久久久免费看成人影片 | 88国产精品欧美一区二区三区 | 中文毛片无遮挡高清免费 | 久久精品人妻少妇一区二区三区 | 丰满岳乱妇在线观看中字无码 | 福利一区二区三区视频在线观看 | 一区二区三区高清视频一 | 国产后入清纯学生妹 | 国产精品免费大片 | 亚洲成av人影院在线观看 | 亚洲天堂2017无码中文 | 全黄性性激高免费视频 | 国产精品无套呻吟在线 | 亚洲精品午夜国产va久久成人 | 白嫩日本少妇做爰 | 国产97人人超碰caoprom | 亚洲日韩av片在线观看 | 亚洲理论电影在线观看 | 在线精品亚洲一区二区 | 欧美肥老太牲交大战 | 亚欧洲精品在线视频免费观看 | 午夜精品久久久内射近拍高清 | 无码人妻丰满熟妇区毛片18 | 自拍偷自拍亚洲精品10p | 一本色道久久综合亚洲精品不卡 | 国产在热线精品视频 | 日日天干夜夜狠狠爱 | 日韩av无码中文无码电影 | 国产乱人无码伦av在线a | 中文亚洲成a人片在线观看 | 麻豆av传媒蜜桃天美传媒 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 久久精品中文字幕一区 | 国产xxx69麻豆国语对白 | 国产色xx群视频射精 | 久久99国产综合精品 | 黄网在线观看免费网站 | 国产午夜手机精彩视频 | 日日躁夜夜躁狠狠躁 | 亚洲欧洲日本无在线码 | 国产无遮挡吃胸膜奶免费看 | 国产后入清纯学生妹 | 又大又黄又粗又爽的免费视频 | 亚洲中文无码av永久不收费 | 亚洲日韩av一区二区三区四区 | 精品国产一区二区三区四区 | 国产激情精品一区二区三区 | 女高中生第一次破苞av | 亚洲中文无码av永久不收费 | 国产卡一卡二卡三 | 水蜜桃亚洲一二三四在线 | 欧美成人午夜精品久久久 | 1000部啪啪未满十八勿入下载 | 久久久久久久人妻无码中文字幕爆 | 久久这里只有精品视频9 | 亚洲精品一区二区三区四区五区 | 色综合久久久无码中文字幕 | 又大又紧又粉嫩18p少妇 | 欧美人妻一区二区三区 | 亚洲色偷偷男人的天堂 | 成在人线av无码免费 | 国内精品人妻无码久久久影院 | 爱做久久久久久 | 人妻少妇精品无码专区二区 | 九九久久精品国产免费看小说 | 樱花草在线社区www | 无套内射视频囯产 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产特级毛片aaaaaaa高清 | 99精品视频在线观看免费 | 日本高清一区免费中文视频 | 亚洲成a人片在线观看日本 | 久久99国产综合精品 | 蜜桃视频插满18在线观看 | 国产无套粉嫩白浆在线 | 久久精品99久久香蕉国产色戒 | 亚洲成av人片在线观看无码不卡 | 国产明星裸体无码xxxx视频 | 色诱久久久久综合网ywww | 欧美zoozzooz性欧美 | 丝袜美腿亚洲一区二区 | 日韩少妇白浆无码系列 | 天干天干啦夜天干天2017 | 国产三级久久久精品麻豆三级 | 久久久久亚洲精品男人的天堂 | 少妇邻居内射在线 | 国产三级精品三级男人的天堂 | 一本色道久久综合亚洲精品不卡 | 久激情内射婷内射蜜桃人妖 | 午夜福利试看120秒体验区 | 亚洲无人区午夜福利码高清完整版 | 天堂无码人妻精品一区二区三区 | 九九热爱视频精品 | 在线观看欧美一区二区三区 | 亚洲成av人片在线观看无码不卡 | 亚洲人亚洲人成电影网站色 | 亚洲欧洲无卡二区视頻 | 成人av无码一区二区三区 | 粗大的内捧猛烈进出视频 | 亚洲高清偷拍一区二区三区 | 亚洲а∨天堂久久精品2021 | 无码免费一区二区三区 | 精品一二三区久久aaa片 | aⅴ亚洲 日韩 色 图网站 播放 | 欧美国产日韩久久mv | 精品久久综合1区2区3区激情 | 国产精品久久国产精品99 | 精品无码国产自产拍在线观看蜜 | 久久五月精品中文字幕 | 撕开奶罩揉吮奶头视频 | 天天av天天av天天透 | 国产特级毛片aaaaaa高潮流水 | 国产精品永久免费视频 | 超碰97人人射妻 | 无码乱肉视频免费大全合集 | 久久久久se色偷偷亚洲精品av | 中文字幕无码乱人伦 | 日韩人妻无码中文字幕视频 | 1000部啪啪未满十八勿入下载 | 国产日产欧产精品精品app | 国产美女精品一区二区三区 | 国产av一区二区三区最新精品 | 欧美日韩人成综合在线播放 | 国产成人无码av一区二区 | 免费人成在线观看网站 | 国产亚洲人成a在线v网站 | 日韩人妻无码一区二区三区久久99 | 欧美自拍另类欧美综合图片区 | 成人精品天堂一区二区三区 | 波多野结衣av在线观看 | 国产偷国产偷精品高清尤物 | 人妻人人添人妻人人爱 | 熟女少妇人妻中文字幕 | 亚洲中文字幕va福利 | 欧美日韩在线亚洲综合国产人 | 午夜精品久久久内射近拍高清 | 狠狠色噜噜狠狠狠7777奇米 | 妺妺窝人体色www婷婷 | 国产真实乱对白精彩久久 | 中文字幕乱码人妻二区三区 | 无码国模国产在线观看 | 99久久精品无码一区二区毛片 | 欧美阿v高清资源不卡在线播放 | 久久国产精品萌白酱免费 | 亚洲国产精华液网站w | 国产69精品久久久久app下载 | 久久久精品成人免费观看 | 欧美成人高清在线播放 | 国产人成高清在线视频99最全资源 | 亚洲国产精品无码一区二区三区 | 国产亚洲欧美日韩亚洲中文色 | 亚洲精品成人福利网站 | 亚洲精品一区三区三区在线观看 | 99riav国产精品视频 | 99精品国产综合久久久久五月天 | 欧洲精品码一区二区三区免费看 | 中文字幕亚洲情99在线 | 久久99久久99精品中文字幕 | 大胆欧美熟妇xx | 婷婷综合久久中文字幕蜜桃三电影 | 国产高清不卡无码视频 | 一本加勒比波多野结衣 | 小泽玛莉亚一区二区视频在线 | 日本精品人妻无码免费大全 | 精品日本一区二区三区在线观看 | 无遮挡啪啪摇乳动态图 | 久久久久久av无码免费看大片 | 亚洲国产精品成人久久蜜臀 | 娇妻被黑人粗大高潮白浆 | 国产高清av在线播放 | 99精品国产综合久久久久五月天 | 精品无码成人片一区二区98 | 久久成人a毛片免费观看网站 | 久久久久成人精品免费播放动漫 | 天天摸天天透天天添 | 好爽又高潮了毛片免费下载 | 高清国产亚洲精品自在久久 | 国产深夜福利视频在线 | 在线播放免费人成毛片乱码 | 精品国产福利一区二区 | 亚洲高清偷拍一区二区三区 | 亚洲中文字幕无码中文字在线 | 成人性做爰aaa片免费看不忠 | 少妇性荡欲午夜性开放视频剧场 | 久久天天躁夜夜躁狠狠 | 亚洲乱亚洲乱妇50p | 亚洲成a人片在线观看无码3d | 国产精品无码成人午夜电影 | 国内精品久久久久久中文字幕 | 国内精品久久毛片一区二区 | 日本护士xxxxhd少妇 | 中文无码成人免费视频在线观看 | 国产成人精品优优av | 成人无码影片精品久久久 | 亚洲热妇无码av在线播放 | 亚洲人成网站免费播放 | 永久黄网站色视频免费直播 | 久久久久av无码免费网 | 嫩b人妻精品一区二区三区 | 国精产品一品二品国精品69xx | 国产一精品一av一免费 | 初尝人妻少妇中文字幕 | 国产精品va在线播放 | 日本乱人伦片中文三区 | 一本无码人妻在中文字幕免费 | 男女性色大片免费网站 | 国产色视频一区二区三区 | 久久zyz资源站无码中文动漫 | 国产午夜福利100集发布 | 国精品人妻无码一区二区三区蜜柚 | 荫蒂添的好舒服视频囗交 | 国内老熟妇对白xxxxhd | 97久久超碰中文字幕 | 日韩av无码中文无码电影 | 国精产品一品二品国精品69xx | 桃花色综合影院 | 亚洲熟妇色xxxxx欧美老妇y | 国内精品九九久久久精品 | 最近的中文字幕在线看视频 | 精品无人国产偷自产在线 | 波多野结衣高清一区二区三区 | 国产精品亚洲一区二区三区喷水 | 精品 日韩 国产 欧美 视频 | 亚洲熟悉妇女xxx妇女av | 色欲久久久天天天综合网精品 | 婷婷综合久久中文字幕蜜桃三电影 | 国产成人综合色在线观看网站 | 中国大陆精品视频xxxx | 欧美35页视频在线观看 | 麻豆国产丝袜白领秘书在线观看 | 色婷婷av一区二区三区之红樱桃 | 狂野欧美性猛交免费视频 | 久久午夜夜伦鲁鲁片无码免费 | 性欧美大战久久久久久久 | 亚洲人成人无码网www国产 | 男人扒开女人内裤强吻桶进去 | 精品aⅴ一区二区三区 | 天堂亚洲免费视频 | 老司机亚洲精品影院 | 亚洲精品国产精品乱码不卡 | 国产精品对白交换视频 | www国产亚洲精品久久久日本 | 成人精品视频一区二区三区尤物 | 日日碰狠狠躁久久躁蜜桃 | 国产精品无码久久av | 97精品人妻一区二区三区香蕉 | 波多野结衣av一区二区全免费观看 | 色综合久久88色综合天天 | 亚洲码国产精品高潮在线 | 国产人妖乱国产精品人妖 | 国产va免费精品观看 | 亚洲欧美色中文字幕在线 | 黑人巨大精品欧美一区二区 | 丰满少妇人妻久久久久久 | 精品国产福利一区二区 | 樱花草在线社区www | 小sao货水好多真紧h无码视频 | 国产亚洲人成在线播放 | 亚洲区欧美区综合区自拍区 | 成年美女黄网站色大免费视频 | 午夜精品久久久内射近拍高清 | 2020久久香蕉国产线看观看 | 午夜肉伦伦影院 | 无码人妻精品一区二区三区不卡 | 国产精品人人妻人人爽 | 日韩精品无码一区二区中文字幕 | 午夜时刻免费入口 | 国产农村妇女高潮大叫 | 亚洲小说春色综合另类 | 国精品人妻无码一区二区三区蜜柚 | 少妇性荡欲午夜性开放视频剧场 | 亚洲成av人影院在线观看 | 精品久久久久久人妻无码中文字幕 | 国产suv精品一区二区五 | 亚洲精品午夜国产va久久成人 | 久久天天躁狠狠躁夜夜免费观看 | 55夜色66夜色国产精品视频 | 一本一道久久综合久久 | 好屌草这里只有精品 | 99久久久国产精品无码免费 | 日韩 欧美 动漫 国产 制服 | 野狼第一精品社区 | 国产精品第一国产精品 | 婷婷综合久久中文字幕蜜桃三电影 | 大胆欧美熟妇xx | 国产精品99爱免费视频 | 亚洲色大成网站www | 国产美女极度色诱视频www | 亚洲一区二区三区 | 天堂亚洲免费视频 | 精品国精品国产自在久国产87 | 亚洲成a人一区二区三区 | 国产色视频一区二区三区 | 成人片黄网站色大片免费观看 | 内射老妇bbwx0c0ck | 少妇被黑人到高潮喷出白浆 | 亚洲无人区午夜福利码高清完整版 | 精品一二三区久久aaa片 | 老太婆性杂交欧美肥老太 | 亚洲熟妇色xxxxx欧美老妇 | 国产肉丝袜在线观看 | 妺妺窝人体色www在线小说 | 一本精品99久久精品77 | 丰满少妇高潮惨叫视频 | 日日噜噜噜噜夜夜爽亚洲精品 | 真人与拘做受免费视频 | 久久久久99精品国产片 | 成人亚洲精品久久久久软件 | 一本久道久久综合狠狠爱 | 好爽又高潮了毛片免费下载 | 久久久久亚洲精品中文字幕 | 少妇高潮喷潮久久久影院 | 亚洲乱码日产精品bd | 久久熟妇人妻午夜寂寞影院 | 国产熟妇另类久久久久 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 午夜嘿嘿嘿影院 | 成熟人妻av无码专区 | 国产精品美女久久久 | 久久亚洲中文字幕无码 | 久久99精品国产麻豆蜜芽 | 亚洲区小说区激情区图片区 | 久久午夜无码鲁丝片 | 人妻插b视频一区二区三区 | 最近中文2019字幕第二页 | 国内精品九九久久久精品 | 88国产精品欧美一区二区三区 | 99久久人妻精品免费一区 | 久久亚洲中文字幕精品一区 | 亚洲综合无码久久精品综合 | 玩弄少妇高潮ⅹxxxyw | 风流少妇按摩来高潮 | 精品水蜜桃久久久久久久 | 亚洲精品一区二区三区婷婷月 | 色综合视频一区二区三区 | a在线观看免费网站大全 | 奇米影视7777久久精品人人爽 | 成人影院yy111111在线观看 | 无码任你躁久久久久久久 | 1000部啪啪未满十八勿入下载 | av人摸人人人澡人人超碰下载 | 国产免费无码一区二区视频 | 成人亚洲精品久久久久 | 鲁大师影院在线观看 | 久久久久久久人妻无码中文字幕爆 | 国产性生大片免费观看性 | 国产女主播喷水视频在线观看 | 99精品国产综合久久久久五月天 | 日日橹狠狠爱欧美视频 | 欧美肥老太牲交大战 | 国产猛烈高潮尖叫视频免费 | 波多野结衣aⅴ在线 | 国产精品成人av在线观看 | 丝袜足控一区二区三区 | 日韩精品无码一本二本三本色 | 国产精华av午夜在线观看 | 国内综合精品午夜久久资源 | 国产乱人偷精品人妻a片 | 欧美日韩亚洲国产精品 | 国产黑色丝袜在线播放 | 久久无码专区国产精品s | 亚洲一区二区三区偷拍女厕 | 午夜成人1000部免费视频 | 久久亚洲中文字幕精品一区 | 欧美熟妇另类久久久久久多毛 | 亚洲国产综合无码一区 | 亚洲综合色区中文字幕 | 日日摸日日碰夜夜爽av | 超碰97人人做人人爱少妇 | 性生交片免费无码看人 | 亚洲成av人片天堂网无码】 | 狠狠躁日日躁夜夜躁2020 | 亚洲国产日韩a在线播放 | 水蜜桃亚洲一二三四在线 | 男女性色大片免费网站 | 欧美老妇交乱视频在线观看 | 欧美国产亚洲日韩在线二区 | 国产一区二区三区影院 | 国产人妻大战黑人第1集 | 欧美性黑人极品hd | 欧美老妇与禽交 | 国产成人亚洲综合无码 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 欧美兽交xxxx×视频 | 色 综合 欧美 亚洲 国产 | 丁香啪啪综合成人亚洲 | 日本大乳高潮视频在线观看 | 小鲜肉自慰网站xnxx | 日日躁夜夜躁狠狠躁 | 丰满人妻翻云覆雨呻吟视频 | 人妻与老人中文字幕 | 一本久道高清无码视频 | 精品无码一区二区三区爱欲 | 2019午夜福利不卡片在线 | 国产精品人人爽人人做我的可爱 | 亚洲日韩av一区二区三区四区 | 国产极品视觉盛宴 | 国产欧美精品一区二区三区 | 女高中生第一次破苞av | 久久国产自偷自偷免费一区调 | 大肉大捧一进一出好爽视频 | 成人无码视频免费播放 | 亚洲日韩av片在线观看 | 国产片av国语在线观看 | 成人影院yy111111在线观看 | 九九综合va免费看 | 国产亚洲精品久久久ai换 | 夜夜高潮次次欢爽av女 | 自拍偷自拍亚洲精品10p | 熟女少妇人妻中文字幕 | 在线播放亚洲第一字幕 | 色婷婷久久一区二区三区麻豆 | 成人欧美一区二区三区 | 最近免费中文字幕中文高清百度 | 窝窝午夜理论片影院 | 亚洲一区二区三区在线观看网站 | 久久精品国产一区二区三区 | 人人澡人人妻人人爽人人蜜桃 | 亚洲精品一区二区三区四区五区 | 粗大的内捧猛烈进出视频 | 国产在线无码精品电影网 | 婷婷综合久久中文字幕蜜桃三电影 | 国产亚洲tv在线观看 | 午夜性刺激在线视频免费 | 好爽又高潮了毛片免费下载 | 国产精品人人爽人人做我的可爱 | 国产av无码专区亚洲awww | 高潮毛片无遮挡高清免费 | 久久久精品456亚洲影院 | 色一情一乱一伦一区二区三欧美 | 人妻熟女一区 | 永久黄网站色视频免费直播 | 牲欲强的熟妇农村老妇女视频 | 乱人伦人妻中文字幕无码 | 国产av一区二区三区最新精品 | 亚洲一区二区三区含羞草 | 日本在线高清不卡免费播放 | 女人色极品影院 | 亚洲精品一区二区三区四区五区 | 99精品国产综合久久久久五月天 | 日本精品人妻无码77777 天堂一区人妻无码 | 最新版天堂资源中文官网 | 大乳丰满人妻中文字幕日本 | 国产精品毛片一区二区 | 国产精品亚洲五月天高清 | 乱码av麻豆丝袜熟女系列 | 国产亚洲日韩欧美另类第八页 | 中文精品久久久久人妻不卡 | 日日躁夜夜躁狠狠躁 | 中文字幕中文有码在线 | 国内精品人妻无码久久久影院 | 给我免费的视频在线观看 | 久久久久av无码免费网 | 国产一区二区三区精品视频 | 国产精品.xx视频.xxtv | 亚洲欧美精品aaaaaa片 | 在线亚洲高清揄拍自拍一品区 | 亚洲爆乳大丰满无码专区 | 波多野结衣aⅴ在线 | 国产精品99久久精品爆乳 | 老子影院午夜精品无码 | 亚洲国产一区二区三区在线观看 | 国产亚洲精品久久久闺蜜 | 丰满护士巨好爽好大乳 | 无码国产色欲xxxxx视频 | 欧美性猛交xxxx富婆 | 国产精品人人妻人人爽 | a国产一区二区免费入口 | 亚洲精品美女久久久久久久 | 国产亚洲日韩欧美另类第八页 | 久久久www成人免费毛片 | www国产亚洲精品久久网站 | 伊人久久大香线蕉午夜 | 最近免费中文字幕中文高清百度 | 成人一在线视频日韩国产 | 日产国产精品亚洲系列 | 99视频精品全部免费免费观看 | 国产va免费精品观看 | 午夜精品一区二区三区的区别 | 国产香蕉97碰碰久久人人 | 奇米影视7777久久精品 | 最新国产乱人伦偷精品免费网站 | 国产成人无码午夜视频在线观看 | 天天拍夜夜添久久精品 | 在线精品国产一区二区三区 | 丰满少妇高潮惨叫视频 | 波多野结衣 黑人 | 奇米影视7777久久精品人人爽 | 国产真人无遮挡作爱免费视频 | 精品偷自拍另类在线观看 | 欧美性色19p | 无码任你躁久久久久久久 | 一本久久a久久精品亚洲 | 又紧又大又爽精品一区二区 | 亚洲aⅴ无码成人网站国产app | 99久久婷婷国产综合精品青草免费 | 我要看www免费看插插视频 | 99久久婷婷国产综合精品青草免费 | 国产精品第一国产精品 | 波多野结衣一区二区三区av免费 | 激情综合激情五月俺也去 | 美女极度色诱视频国产 | 无遮挡国产高潮视频免费观看 | 十八禁视频网站在线观看 | 久久zyz资源站无码中文动漫 | 精品国产一区二区三区四区 | 4hu四虎永久在线观看 | 丰满人妻精品国产99aⅴ | 日本一卡2卡3卡四卡精品网站 | 日韩精品a片一区二区三区妖精 | 18精品久久久无码午夜福利 | 国产超碰人人爽人人做人人添 | 国产成人无码区免费内射一片色欲 | 国产精品第一国产精品 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 成熟妇人a片免费看网站 | 色综合视频一区二区三区 | 性欧美牲交xxxxx视频 | 国产香蕉尹人综合在线观看 | 久久亚洲日韩精品一区二区三区 | 狠狠cao日日穞夜夜穞av | 国产综合在线观看 | 国产精品久久久av久久久 | a在线观看免费网站大全 | 亚洲精品欧美二区三区中文字幕 | 国产香蕉尹人视频在线 | 色综合久久久久综合一本到桃花网 | 欧美喷潮久久久xxxxx | 午夜精品久久久久久久久 | 99精品视频在线观看免费 | 国产亚洲美女精品久久久2020 | 国产午夜福利亚洲第一 | 成人毛片一区二区 | 国产乱子伦视频在线播放 | 极品嫩模高潮叫床 | 日韩人妻少妇一区二区三区 | 亚欧洲精品在线视频免费观看 | √天堂中文官网8在线 | 131美女爱做视频 | 美女毛片一区二区三区四区 | 欧美激情综合亚洲一二区 | 国产九九九九九九九a片 | 男女作爱免费网站 | 呦交小u女精品视频 | 国产另类ts人妖一区二区 | 国产性生交xxxxx无码 | 久久99精品久久久久久 | 精品亚洲韩国一区二区三区 | 成人一区二区免费视频 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 中文字幕无码av波多野吉衣 | 欧美亚洲国产一区二区三区 | 天堂无码人妻精品一区二区三区 | 丁香啪啪综合成人亚洲 | 最新国产乱人伦偷精品免费网站 | 无人区乱码一区二区三区 | 亚洲一区二区三区偷拍女厕 | 亚洲中文字幕乱码av波多ji | 纯爱无遮挡h肉动漫在线播放 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产精品久久久av久久久 | 亚洲一区二区观看播放 | 极品嫩模高潮叫床 | 大色综合色综合网站 | 亚拍精品一区二区三区探花 | 久久婷婷五月综合色国产香蕉 | 亚洲自偷自偷在线制服 | 国产综合久久久久鬼色 | 亚洲自偷自拍另类第1页 | 亚洲の无码国产の无码步美 | 亚洲精品鲁一鲁一区二区三区 | 欧美刺激性大交 | 国产成人精品三级麻豆 | 国精产品一品二品国精品69xx | 亚洲熟妇色xxxxx欧美老妇 | 日本一本二本三区免费 | 国产人妻精品一区二区三区不卡 | 中文字幕日韩精品一区二区三区 | 欧美一区二区三区视频在线观看 | 色欲综合久久中文字幕网 | 国产农村乱对白刺激视频 | 亚洲七七久久桃花影院 | 国产精品高潮呻吟av久久 | 九九久久精品国产免费看小说 | 亚洲一区二区三区含羞草 | 97夜夜澡人人爽人人喊中国片 | 18精品久久久无码午夜福利 | 国产一区二区三区日韩精品 | 国产后入清纯学生妹 | 国产精品无码成人午夜电影 | 久久久久久国产精品无码下载 | 99精品久久毛片a片 | 国产乱人伦av在线无码 | 人妻aⅴ无码一区二区三区 | 天天av天天av天天透 | 久久国产劲爆∧v内射 | 国产精品沙发午睡系列 | 亚洲精品鲁一鲁一区二区三区 | 夜夜影院未满十八勿进 | 5858s亚洲色大成网站www | 美女黄网站人色视频免费国产 | 无码人妻丰满熟妇区五十路百度 | 久久久中文久久久无码 | 精品国产一区av天美传媒 | 97夜夜澡人人双人人人喊 | 人人妻人人藻人人爽欧美一区 | 国产成人精品久久亚洲高清不卡 | 台湾无码一区二区 | 国产精品无码一区二区三区不卡 | 日本饥渴人妻欲求不满 | 熟女俱乐部五十路六十路av | 国产精品久久久久无码av色戒 | 久久亚洲中文字幕无码 | 久久久成人毛片无码 | 性色欲网站人妻丰满中文久久不卡 | 亚洲自偷精品视频自拍 | 无遮挡啪啪摇乳动态图 | 欧美激情内射喷水高潮 | 影音先锋中文字幕无码 | 亚洲精品一区二区三区四区五区 | 人人妻人人澡人人爽欧美一区 | 久久无码中文字幕免费影院蜜桃 | 久久视频在线观看精品 | 中文字幕日产无线码一区 | 亚洲综合色区中文字幕 | 岛国片人妻三上悠亚 | 日韩精品乱码av一区二区 | 中文无码成人免费视频在线观看 | 国内揄拍国内精品少妇国语 | 中文字幕人成乱码熟女app | 久久99精品国产.久久久久 | 麻豆果冻传媒2021精品传媒一区下载 | 欧美日韩一区二区三区自拍 | 伊人久久大香线蕉亚洲 | 国产suv精品一区二区五 | 1000部啪啪未满十八勿入下载 | 日欧一片内射va在线影院 | 国产精品二区一区二区aⅴ污介绍 | 午夜丰满少妇性开放视频 | 国产莉萝无码av在线播放 | 午夜理论片yy44880影院 | 高潮喷水的毛片 | 丰满人妻被黑人猛烈进入 | 网友自拍区视频精品 | 国模大胆一区二区三区 | 特黄特色大片免费播放器图片 | 久久久久久a亚洲欧洲av冫 | 性欧美大战久久久久久久 | 国产午夜视频在线观看 | 国产亚洲人成a在线v网站 | 亚洲第一网站男人都懂 | 国产农村妇女高潮大叫 | 久久 国产 尿 小便 嘘嘘 | 国产午夜亚洲精品不卡下载 | 一本大道久久东京热无码av | 国产欧美熟妇另类久久久 | 一本久久a久久精品vr综合 | 国色天香社区在线视频 | 久久久婷婷五月亚洲97号色 | 亚洲小说图区综合在线 | 精品久久久久香蕉网 | 亚无码乱人伦一区二区 | 久久99精品国产麻豆 | 又粗又大又硬又长又爽 | 最近的中文字幕在线看视频 | 国产激情无码一区二区 | 激情内射亚州一区二区三区爱妻 | 国产午夜福利100集发布 | 丰满妇女强制高潮18xxxx | 亚洲熟妇色xxxxx亚洲 | 欧美精品无码一区二区三区 | 欧美精品一区二区精品久久 | 国产精品内射视频免费 | 麻豆果冻传媒2021精品传媒一区下载 | 久久伊人色av天堂九九小黄鸭 | 大乳丰满人妻中文字幕日本 | 日本饥渴人妻欲求不满 | 欧美老熟妇乱xxxxx | 亚洲日韩乱码中文无码蜜桃臀网站 | 日韩 欧美 动漫 国产 制服 | 成人性做爰aaa片免费看不忠 | 在线视频网站www色 | 荫蒂被男人添的好舒服爽免费视频 | 玩弄人妻少妇500系列视频 | 国产精品久久久久9999小说 | 久久久久久a亚洲欧洲av冫 | 国产成人精品优优av | 成熟妇人a片免费看网站 | 国产成人人人97超碰超爽8 | 人妻少妇精品无码专区动漫 | 欧美人与禽zoz0性伦交 | 亚洲区欧美区综合区自拍区 | 老熟妇仑乱视频一区二区 | 成人影院yy111111在线观看 | 无码帝国www无码专区色综合 | 亚洲色www成人永久网址 | 少妇的肉体aa片免费 | 永久免费观看国产裸体美女 | 亚洲午夜福利在线观看 | 国产午夜亚洲精品不卡下载 | 中文毛片无遮挡高清免费 | 久久综合狠狠综合久久综合88 | 少妇被粗大的猛进出69影院 | 免费人成网站视频在线观看 | a国产一区二区免费入口 | 亚洲国产精品无码久久久久高潮 | 性生交大片免费看女人按摩摩 | 宝宝好涨水快流出来免费视频 | 国产两女互慰高潮视频在线观看 | 亚洲中文字幕无码一久久区 | 成人av无码一区二区三区 | 久久精品99久久香蕉国产色戒 | 国产免费无码一区二区视频 | 丝袜 中出 制服 人妻 美腿 | 好屌草这里只有精品 | 亚洲中文字幕在线观看 | 国产免费久久精品国产传媒 | 日本一区二区三区免费高清 | 色综合久久88色综合天天 | 中文字幕无码人妻少妇免费 | 亚洲第一网站男人都懂 | 西西人体www44rt大胆高清 | 国产香蕉97碰碰久久人人 | 婷婷五月综合激情中文字幕 | 麻豆精产国品 | 国产在线精品一区二区三区直播 | 久久综合激激的五月天 | 国产成人无码专区 | 色偷偷人人澡人人爽人人模 | 亚洲精品综合一区二区三区在线 | 亚洲国产精品美女久久久久 | 牲欲强的熟妇农村老妇女视频 | 亚洲欧美精品aaaaaa片 | 特级做a爰片毛片免费69 | 国产色视频一区二区三区 | 久久久久免费看成人影片 | 国产亚洲精品久久久ai换 | 日日天日日夜日日摸 | 免费国产成人高清在线观看网站 | 日日摸天天摸爽爽狠狠97 | 久久99精品久久久久久动态图 | 激情内射亚州一区二区三区爱妻 | 精品亚洲成av人在线观看 | 精品一区二区三区波多野结衣 | 国产办公室秘书无码精品99 | 精品人妻人人做人人爽 | 久久综合激激的五月天 | 老熟妇仑乱视频一区二区 | 玩弄少妇高潮ⅹxxxyw | 日日摸日日碰夜夜爽av | 国产一区二区三区四区五区加勒比 | 亚洲国产欧美日韩精品一区二区三区 | 国产精品99爱免费视频 | 亚洲人成无码网www | 久久精品国产99久久6动漫 | 亚洲中文字幕在线无码一区二区 | 亚洲七七久久桃花影院 | 国产综合色产在线精品 | 77777熟女视频在线观看 а天堂中文在线官网 | 欧美午夜特黄aaaaaa片 | 丁香花在线影院观看在线播放 | 亚洲成a人片在线观看无码3d | 亚洲乱码中文字幕在线 | 精品国产一区二区三区av 性色 | 亚洲精品一区二区三区四区五区 | 99精品无人区乱码1区2区3区 | ass日本丰满熟妇pics | 成 人 免费观看网站 | 男女性色大片免费网站 | 98国产精品综合一区二区三区 | 精品久久久中文字幕人妻 | 丰满人妻精品国产99aⅴ | 亚洲精品国产精品乱码不卡 | 国产精品va在线观看无码 | 欧美放荡的少妇 | 亚洲s色大片在线观看 | 人妻少妇精品无码专区二区 | 67194成是人免费无码 | 日本精品人妻无码免费大全 | 精品一区二区不卡无码av | 国产精品国产自线拍免费软件 | 久久久中文字幕日本无吗 | 玩弄少妇高潮ⅹxxxyw | 成人欧美一区二区三区黑人免费 | 国产亚洲欧美日韩亚洲中文色 | 国产成人久久精品流白浆 | 国产性生大片免费观看性 | 人妻无码久久精品人妻 | 久久人人爽人人爽人人片av高清 | 鲁鲁鲁爽爽爽在线视频观看 | 少妇人妻偷人精品无码视频 | 欧美野外疯狂做受xxxx高潮 | 无码人妻出轨黑人中文字幕 | 日日天干夜夜狠狠爱 | 国内丰满熟女出轨videos | 成人精品天堂一区二区三区 | 亚洲综合无码久久精品综合 | 免费无码午夜福利片69 | 日本xxxx色视频在线观看免费 | 丰满人妻翻云覆雨呻吟视频 | 人妻熟女一区 | 午夜福利电影 | 日本一区二区三区免费播放 | 欧美日韩视频无码一区二区三 | 亚洲国产成人a精品不卡在线 | 国产精品人人爽人人做我的可爱 | 99精品国产综合久久久久五月天 | 欧美刺激性大交 | 国产精品亚洲а∨无码播放麻豆 | 久久婷婷五月综合色国产香蕉 | 欧美国产日产一区二区 | 亚洲精品久久久久久久久久久 | 国产美女极度色诱视频www | 色欲久久久天天天综合网精品 | 欧美丰满熟妇xxxx | 久久亚洲日韩精品一区二区三区 | 人妻aⅴ无码一区二区三区 | 亚洲精品中文字幕久久久久 | 欧美午夜特黄aaaaaa片 | 亚洲中文字幕va福利 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 国产精品自产拍在线观看 | 天天拍夜夜添久久精品大 | 久久精品99久久香蕉国产色戒 | 免费无码的av片在线观看 | 精品国产福利一区二区 | 无码午夜成人1000部免费视频 | 夜夜夜高潮夜夜爽夜夜爰爰 | 六月丁香婷婷色狠狠久久 | 日韩人妻少妇一区二区三区 | 国产人妻精品一区二区三区 | 久9re热视频这里只有精品 | 免费国产成人高清在线观看网站 | 人妻少妇精品无码专区动漫 | 精品亚洲韩国一区二区三区 | 18无码粉嫩小泬无套在线观看 | 无码任你躁久久久久久久 | 国精产品一品二品国精品69xx | 无套内谢的新婚少妇国语播放 | 色综合久久久无码中文字幕 | 午夜福利不卡在线视频 | 日日碰狠狠丁香久燥 | 亚洲精品成人av在线 | 国产综合久久久久鬼色 | 大肉大捧一进一出好爽视频 | 樱花草在线播放免费中文 | 中文久久乱码一区二区 | 亚洲成a人片在线观看无码 | 亚洲熟妇自偷自拍另类 | 亚洲春色在线视频 | 久久久久亚洲精品男人的天堂 | 欧美35页视频在线观看 | 无码精品人妻一区二区三区av | 成年美女黄网站色大免费视频 | 高潮毛片无遮挡高清免费 | 国产欧美精品一区二区三区 | 久久久久久a亚洲欧洲av冫 | 国产成人精品必看 | 亚洲国产精品成人久久蜜臀 | 国产高清不卡无码视频 | 亚洲热妇无码av在线播放 | 在线精品亚洲一区二区 | 亚洲自偷自偷在线制服 | 国产人妻精品一区二区三区不卡 | 国产精品香蕉在线观看 | 亚洲精品综合一区二区三区在线 | 国产精品高潮呻吟av久久4虎 | 国产成人精品久久亚洲高清不卡 | 久久精品人人做人人综合试看 | 奇米影视7777久久精品 | 亚洲aⅴ无码成人网站国产app | 熟妇人妻无乱码中文字幕 | 国产特级毛片aaaaaa高潮流水 | 特大黑人娇小亚洲女 | 国产真人无遮挡作爱免费视频 | 亚洲a无码综合a国产av中文 | 中文无码成人免费视频在线观看 | 国产欧美亚洲精品a | 中国女人内谢69xxxx | 嫩b人妻精品一区二区三区 | 国产绳艺sm调教室论坛 | 对白脏话肉麻粗话av | 宝宝好涨水快流出来免费视频 | 色婷婷综合中文久久一本 | 免费人成在线视频无码 | 福利一区二区三区视频在线观看 | 国产无遮挡又黄又爽免费视频 | 熟妇激情内射com | 国产综合久久久久鬼色 | 欧美国产日韩久久mv | 成人影院yy111111在线观看 | 久久久久久av无码免费看大片 | www国产亚洲精品久久网站 | 亚洲精品成a人在线观看 | 国产精品久久久久久亚洲毛片 | 人妻天天爽夜夜爽一区二区 | 国产极品视觉盛宴 | 少妇的肉体aa片免费 | 亚洲日韩乱码中文无码蜜桃臀网站 | www国产亚洲精品久久久日本 | 少妇被黑人到高潮喷出白浆 | 婷婷五月综合缴情在线视频 | 97久久国产亚洲精品超碰热 | 一本色道久久综合亚洲精品不卡 | 色妞www精品免费视频 | 夜夜夜高潮夜夜爽夜夜爰爰 | 4hu四虎永久在线观看 | 亚洲自偷自拍另类第1页 | 国产黑色丝袜在线播放 | 欧美人与禽zoz0性伦交 | 国产情侣作爱视频免费观看 | 婷婷色婷婷开心五月四房播播 | 成熟女人特级毛片www免费 | 国产成人综合在线女婷五月99播放 | 2019nv天堂香蕉在线观看 | 无码福利日韩神码福利片 | 日韩精品无码一本二本三本色 | 国产又爽又黄又刺激的视频 | 亚洲人成影院在线无码按摩店 | 亚洲成av人影院在线观看 | 伊人久久大香线蕉午夜 | 国精产品一区二区三区 | 亚洲国产精品成人久久蜜臀 | 天天做天天爱天天爽综合网 | 国产成人精品优优av | 亚洲va中文字幕无码久久不卡 | 国产精品怡红院永久免费 | 国产精品对白交换视频 | 丰满少妇弄高潮了www | 亚洲乱码日产精品bd | 国产在线aaa片一区二区99 | 精品一区二区三区无码免费视频 | a在线观看免费网站大全 | 男女作爱免费网站 | 特黄特色大片免费播放器图片 | 亚洲男人av天堂午夜在 | √8天堂资源地址中文在线 | 六月丁香婷婷色狠狠久久 | 少妇高潮喷潮久久久影院 | 亚洲日韩乱码中文无码蜜桃臀网站 | 麻豆国产人妻欲求不满 | 97人妻精品一区二区三区 | 国产无遮挡吃胸膜奶免费看 | 亚洲国产欧美日韩精品一区二区三区 | 日本熟妇大屁股人妻 | 久久久久免费精品国产 | 亚洲人亚洲人成电影网站色 | 人人妻人人藻人人爽欧美一区 | 女人高潮内射99精品 | 日本丰满熟妇videos | 日本爽爽爽爽爽爽在线观看免 | 人人妻人人澡人人爽欧美一区 | aⅴ亚洲 日韩 色 图网站 播放 | 高清不卡一区二区三区 | 国产熟妇另类久久久久 | 午夜福利试看120秒体验区 | 国产99久久精品一区二区 | 精品乱子伦一区二区三区 | 中文字幕人妻丝袜二区 | 亚洲色大成网站www | 中文字幕av伊人av无码av | 大肉大捧一进一出视频出来呀 | 亚洲色www成人永久网址 | 欧美野外疯狂做受xxxx高潮 | 最近中文2019字幕第二页 | 亚洲熟妇色xxxxx欧美老妇y | 精品无码一区二区三区爱欲 | 精品熟女少妇av免费观看 | 国产香蕉尹人视频在线 | 国产精品资源一区二区 | 男女下面进入的视频免费午夜 | 亚洲综合伊人久久大杳蕉 | 精品国产一区二区三区av 性色 | 漂亮人妻洗澡被公强 日日躁 | 给我免费的视频在线观看 | 久久精品视频在线看15 | 亚洲精品一区二区三区在线观看 | 天天摸天天透天天添 | 精品久久久中文字幕人妻 | 牲欲强的熟妇农村老妇女 | 色五月五月丁香亚洲综合网 | 久久综合九色综合97网 | 无码人妻黑人中文字幕 | 99在线 | 亚洲 | 狠狠色欧美亚洲狠狠色www | av无码久久久久不卡免费网站 | 人人澡人摸人人添 | 激情国产av做激情国产爱 | 久久久久久久人妻无码中文字幕爆 | 爽爽影院免费观看 | 日日躁夜夜躁狠狠躁 | 国产99久久精品一区二区 | 欧美乱妇无乱码大黄a片 | 国色天香社区在线视频 | 又色又爽又黄的美女裸体网站 | 国产熟妇另类久久久久 | 国产精品va在线观看无码 | 中文字幕av日韩精品一区二区 | 亚洲国产精华液网站w | 国产精品亚洲а∨无码播放麻豆 | 久久久久久久久888 | 国产成人无码av一区二区 | 中文字幕av伊人av无码av | 日韩人妻无码一区二区三区久久99 | 国产精品香蕉在线观看 | 亚洲伊人久久精品影院 | 国产亚洲美女精品久久久2020 | 久久99精品国产麻豆 | 西西人体www44rt大胆高清 | 特黄特色大片免费播放器图片 | 中文字幕无码av激情不卡 | 中文字幕人妻丝袜二区 | 欧美丰满熟妇xxxx性ppx人交 | 国产亲子乱弄免费视频 | 丝袜 中出 制服 人妻 美腿 | 丰满肥臀大屁股熟妇激情视频 | 国产精品嫩草久久久久 | 国产亚洲视频中文字幕97精品 | 国产电影无码午夜在线播放 | 天天av天天av天天透 | 丁香花在线影院观看在线播放 | 中文字幕日韩精品一区二区三区 | 亚洲爆乳精品无码一区二区三区 | 大屁股大乳丰满人妻 | 特级做a爰片毛片免费69 | 国产卡一卡二卡三 | 天天av天天av天天透 | 亚洲综合久久一区二区 | 亚洲国产精品无码久久久久高潮 | 国内精品久久久久久中文字幕 | 日欧一片内射va在线影院 | 无码一区二区三区在线观看 | 久久久久亚洲精品男人的天堂 | 纯爱无遮挡h肉动漫在线播放 | 日本免费一区二区三区最新 | 一本色道久久综合亚洲精品不卡 | 在线成人www免费观看视频 | 久久精品国产精品国产精品污 | 成人三级无码视频在线观看 | 真人与拘做受免费视频 | 在线а√天堂中文官网 | 国产色xx群视频射精 | 毛片内射-百度 | 精品偷自拍另类在线观看 | 牲欲强的熟妇农村老妇女 | 国产精品毛片一区二区 | 网友自拍区视频精品 | 中文字幕乱码人妻无码久久 | 久久人人爽人人爽人人片ⅴ | 少妇人妻大乳在线视频 | 久久99精品国产麻豆蜜芽 | 两性色午夜视频免费播放 | 久久亚洲国产成人精品性色 | 欧美精品国产综合久久 | 久久午夜无码鲁丝片 | 国产两女互慰高潮视频在线观看 | 久久精品人人做人人综合试看 | 精品国产一区二区三区av 性色 | 亚洲爆乳精品无码一区二区三区 | 亚洲 欧美 激情 小说 另类 | 日本乱人伦片中文三区 | 国产人成高清在线视频99最全资源 | 亚洲国产日韩a在线播放 | 99精品国产综合久久久久五月天 | 久久99久久99精品中文字幕 | 亚洲一区二区三区含羞草 | 小鲜肉自慰网站xnxx | 波多野42部无码喷潮在线 | 特级做a爰片毛片免费69 | 色诱久久久久综合网ywww | 国产乱人偷精品人妻a片 | 一本无码人妻在中文字幕免费 | 午夜福利不卡在线视频 | 九九综合va免费看 | 国产精品福利视频导航 | 国产真实夫妇视频 | 久久午夜无码鲁丝片午夜精品 | 人妻与老人中文字幕 | 国产精品毛片一区二区 | 亚洲精品国偷拍自产在线麻豆 | 波多野结衣av在线观看 | 国产两女互慰高潮视频在线观看 | 国产国产精品人在线视 | 色欲久久久天天天综合网精品 | 国产精品成人av在线观看 | 宝宝好涨水快流出来免费视频 | 性欧美疯狂xxxxbbbb | 国产在线aaa片一区二区99 | 伦伦影院午夜理论片 | 性生交片免费无码看人 | 久久午夜夜伦鲁鲁片无码免费 | 久久99精品国产麻豆 | 激情五月综合色婷婷一区二区 | 成人无码影片精品久久久 | 午夜无码区在线观看 | √天堂中文官网8在线 | 久久久久久九九精品久 | 在线欧美精品一区二区三区 | 国产成人久久精品流白浆 | 亚洲 日韩 欧美 成人 在线观看 | 免费无码午夜福利片69 | 日本肉体xxxx裸交 | 永久黄网站色视频免费直播 | 亚洲国产欧美日韩精品一区二区三区 | 人妻中文无码久热丝袜 | 色综合久久久无码网中文 | 日本精品少妇一区二区三区 | 欧美精品在线观看 | 无码人妻精品一区二区三区下载 | 国产两女互慰高潮视频在线观看 | 国产香蕉97碰碰久久人人 | 白嫩日本少妇做爰 | 亚洲中文字幕无码中文字在线 | 亚洲欧美色中文字幕在线 | 波多野结衣aⅴ在线 | 免费观看激色视频网站 | 51国偷自产一区二区三区 | 国产免费观看黄av片 | 亚洲aⅴ无码成人网站国产app | 丰满肥臀大屁股熟妇激情视频 | 丝袜美腿亚洲一区二区 | 四虎国产精品一区二区 | 婷婷五月综合激情中文字幕 | 欧美人与物videos另类 | 成在人线av无码免观看麻豆 | 亚洲精品成a人在线观看 | 欧美怡红院免费全部视频 | 色 综合 欧美 亚洲 国产 | 东京热无码av男人的天堂 | 图片小说视频一区二区 | 日本精品人妻无码77777 天堂一区人妻无码 | 亚洲综合在线一区二区三区 | 亚洲の无码国产の无码步美 | 又黄又爽又色的视频 | 精品国产av色一区二区深夜久久 | 一本大道伊人av久久综合 | 欧美喷潮久久久xxxxx | 亚洲熟悉妇女xxx妇女av | ass日本丰满熟妇pics | 国产熟女一区二区三区四区五区 | av香港经典三级级 在线 | 亚洲中文字幕久久无码 | 日本精品高清一区二区 | 亚洲精品久久久久avwww潮水 | aⅴ在线视频男人的天堂 | 久久综合激激的五月天 | 精品日本一区二区三区在线观看 | 国产精品久久福利网站 | 国产在线精品一区二区高清不卡 | 伊人久久大香线蕉亚洲 | 窝窝午夜理论片影院 | 精品久久久久香蕉网 | 日韩 欧美 动漫 国产 制服 | 国产乱人伦av在线无码 | 欧美性黑人极品hd | 亚洲第一网站男人都懂 | 偷窥日本少妇撒尿chinese | 麻豆果冻传媒2021精品传媒一区下载 | 精品人人妻人人澡人人爽人人 | 欧美国产日韩亚洲中文 | 亚洲国产精华液网站w | 性欧美熟妇videofreesex | 性欧美牲交xxxxx视频 | 久久久精品456亚洲影院 | 久久精品中文字幕一区 | 亚洲一区二区三区在线观看网站 | 久久这里只有精品视频9 | 亚洲娇小与黑人巨大交 | 亚洲国产精品一区二区美利坚 | 日本精品高清一区二区 | 国产精品毛多多水多 | 一个人看的视频www在线 | 乌克兰少妇xxxx做受 | 亚洲欧美精品aaaaaa片 | 国产午夜无码视频在线观看 | 日韩欧美中文字幕在线三区 | 内射后入在线观看一区 | 55夜色66夜色国产精品视频 | 欧美精品无码一区二区三区 | 国产又爽又猛又粗的视频a片 | 亚洲精品成人福利网站 | 亚洲国产成人a精品不卡在线 | 扒开双腿疯狂进出爽爽爽视频 | 99riav国产精品视频 | 在线播放亚洲第一字幕 | a国产一区二区免费入口 | 午夜成人1000部免费视频 | 国产亚洲人成a在线v网站 | 131美女爱做视频 | 国产精品高潮呻吟av久久 | 欧洲熟妇精品视频 | 女人被男人躁得好爽免费视频 | 99在线 | 亚洲 | 日韩欧美群交p片內射中文 | 无码任你躁久久久久久久 | 亚洲狠狠婷婷综合久久 | 日韩av无码中文无码电影 | 欧美一区二区三区视频在线观看 | 久久久久久亚洲精品a片成人 | 青青草原综合久久大伊人精品 | 疯狂三人交性欧美 | 精品一二三区久久aaa片 | 无码人中文字幕 | 亚洲欧美综合区丁香五月小说 | 日韩无码专区 | 欧洲欧美人成视频在线 | 天天拍夜夜添久久精品 | 2020久久超碰国产精品最新 | 成人无码精品1区2区3区免费看 | 久久 国产 尿 小便 嘘嘘 | 无码成人精品区在线观看 | 东京热无码av男人的天堂 | 欧美黑人乱大交 | 熟妇人妻中文av无码 | 色噜噜亚洲男人的天堂 | 狠狠亚洲超碰狼人久久 | 奇米影视888欧美在线观看 | 久久99精品久久久久久 | 亚洲熟女一区二区三区 | 人妻aⅴ无码一区二区三区 | 最近的中文字幕在线看视频 | 无遮无挡爽爽免费视频 | 日本欧美一区二区三区乱码 | 无码国产色欲xxxxx视频 | 亚洲国产午夜精品理论片 | 国产莉萝无码av在线播放 | 麻豆国产97在线 | 欧洲 | 国精品人妻无码一区二区三区蜜柚 | 亚洲国产欧美日韩精品一区二区三区 | 男女性色大片免费网站 | 国产性生大片免费观看性 | 欧美激情内射喷水高潮 | 欧美老熟妇乱xxxxx | 亚洲综合无码久久精品综合 | 2020久久香蕉国产线看观看 | 久久国产36精品色熟妇 | 欧美成人午夜精品久久久 | 欧美肥老太牲交大战 | 白嫩日本少妇做爰 | 综合人妻久久一区二区精品 | 亚洲国产欧美日韩精品一区二区三区 | 青春草在线视频免费观看 | 亚洲精品美女久久久久久久 | 欧美色就是色 | 午夜福利电影 | 国产欧美熟妇另类久久久 | 久久久久国色av免费观看性色 | 亚洲熟女一区二区三区 | 露脸叫床粗话东北少妇 | 精品国产aⅴ无码一区二区 | 熟女少妇在线视频播放 | 久在线观看福利视频 | 无码人妻出轨黑人中文字幕 | 伊人久久大香线焦av综合影院 | 久久无码中文字幕免费影院蜜桃 | 久久天天躁狠狠躁夜夜免费观看 | 欧美人与牲动交xxxx | 成人性做爰aaa片免费看不忠 | 亚洲a无码综合a国产av中文 | 欧美老人巨大xxxx做受 | 亚洲男女内射在线播放 | 国产后入清纯学生妹 | 一本无码人妻在中文字幕免费 | 亚洲а∨天堂久久精品2021 | 亚洲一区二区三区偷拍女厕 | 久久99精品久久久久婷婷 | 男人和女人高潮免费网站 | 欧美国产日产一区二区 | 国产热a欧美热a在线视频 | 天海翼激烈高潮到腰振不止 | 国产日产欧产精品精品app | 人妻少妇精品久久 | 夫妻免费无码v看片 | 国色天香社区在线视频 | 欧美精品在线观看 | 成人无码视频在线观看网站 | 精品人妻人人做人人爽夜夜爽 | 国产va免费精品观看 | 国产口爆吞精在线视频 | 国产成人无码区免费内射一片色欲 | 天堂亚洲2017在线观看 | 婷婷五月综合激情中文字幕 | 国产精品亚洲а∨无码播放麻豆 | 中文亚洲成a人片在线观看 | 欧美日本精品一区二区三区 | 亚洲精品中文字幕久久久久 | 亚洲中文字幕在线无码一区二区 | 曰韩无码二三区中文字幕 | 任你躁国产自任一区二区三区 | 日韩在线不卡免费视频一区 | 精品久久久久久人妻无码中文字幕 | 少妇激情av一区二区 | 国产深夜福利视频在线 | 真人与拘做受免费视频一 | 人人妻人人澡人人爽欧美精品 | 精品无人国产偷自产在线 | 久久无码人妻影院 | 中文字幕中文有码在线 | 精品国精品国产自在久国产87 | 国产精品丝袜黑色高跟鞋 | 日本一区二区三区免费播放 | 人妻少妇精品久久 | 一本久久a久久精品vr综合 | 欧洲美熟女乱又伦 | 67194成是人免费无码 | 亚洲中文无码av永久不收费 | 成人影院yy111111在线观看 | 亚洲国产精品美女久久久久 | 久久99精品国产.久久久久 | 久久亚洲国产成人精品性色 | 黑人巨大精品欧美黑寡妇 | 国産精品久久久久久久 | 国产成人无码专区 | 少妇激情av一区二区 | 免费视频欧美无人区码 | 精品一区二区三区波多野结衣 | 图片小说视频一区二区 | 国产人妻人伦精品 | 思思久久99热只有频精品66 | 国产在线精品一区二区高清不卡 | 国产午夜亚洲精品不卡下载 | 精品国精品国产自在久国产87 | 久久久精品国产sm最大网站 | 国产成人亚洲综合无码 | 又粗又大又硬毛片免费看 | 亚洲欧美日韩国产精品一区二区 | 97精品人妻一区二区三区香蕉 | 亚洲精品一区二区三区四区五区 | 99久久精品国产一区二区蜜芽 | 亚洲一区二区三区国产精华液 | 51国偷自产一区二区三区 | 久久综合色之久久综合 | 激情内射亚州一区二区三区爱妻 | 国产特级毛片aaaaaa高潮流水 | 在线欧美精品一区二区三区 | 免费无码午夜福利片69 | 天堂无码人妻精品一区二区三区 | 97夜夜澡人人爽人人喊中国片 | 国产亚洲精品精品国产亚洲综合 | 亚洲精品一区二区三区在线 | 成人综合网亚洲伊人 | 国产人妻久久精品二区三区老狼 | 久久久无码中文字幕久... | 国产精品美女久久久 | 狠狠综合久久久久综合网 | 97夜夜澡人人双人人人喊 | 国产精品人人爽人人做我的可爱 | 精品夜夜澡人妻无码av蜜桃 | 亚洲精品久久久久久一区二区 | 成熟女人特级毛片www免费 | 97资源共享在线视频 | 麻豆精品国产精华精华液好用吗 | 激情内射亚州一区二区三区爱妻 | 国产偷国产偷精品高清尤物 | 国产绳艺sm调教室论坛 | 性生交大片免费看女人按摩摩 | 久久天天躁夜夜躁狠狠 | 久久久无码中文字幕久... | 全黄性性激高免费视频 | 国产sm调教视频在线观看 | 国产亲子乱弄免费视频 | 国产成人精品视频ⅴa片软件竹菊 | 中文无码成人免费视频在线观看 | 国产精品鲁鲁鲁 | 国产精品久久久久久亚洲毛片 | 久久综合激激的五月天 | 成熟妇人a片免费看网站 | 国产精品美女久久久久av爽李琼 | 黑人巨大精品欧美一区二区 | 欧美精品一区二区精品久久 | 精品国产麻豆免费人成网站 | 天天燥日日燥 | 无码精品国产va在线观看dvd | 国内少妇偷人精品视频 | 精品欧美一区二区三区久久久 | 大肉大捧一进一出好爽视频 | 在线观看国产午夜福利片 | 久久国产精品偷任你爽任你 | 九月婷婷人人澡人人添人人爽 | 国内揄拍国内精品人妻 | 内射巨臀欧美在线视频 | 免费观看又污又黄的网站 | 特级做a爰片毛片免费69 | 女人被男人爽到呻吟的视频 | 成人片黄网站色大片免费观看 | 日本精品高清一区二区 | 激情五月综合色婷婷一区二区 | 国产福利视频一区二区 | 精品成人av一区二区三区 | 国产免费观看黄av片 | 国产激情一区二区三区 | 少妇性荡欲午夜性开放视频剧场 | 亚洲欧美日韩成人高清在线一区 | 亚洲国产午夜精品理论片 | 国产精品久久精品三级 | 日本xxxx色视频在线观看免费 | 久久 国产 尿 小便 嘘嘘 | 免费男性肉肉影院 | 久久午夜无码鲁丝片秋霞 | 亚洲精品午夜国产va久久成人 | 精品人妻人人做人人爽 | 欧美性猛交xxxx富婆 | 午夜免费福利小电影 | 无码人妻黑人中文字幕 | 国产乱码精品一品二品 | 国产热a欧美热a在线视频 | 在线а√天堂中文官网 | 亚洲经典千人经典日产 | 偷窥村妇洗澡毛毛多 | 蜜桃无码一区二区三区 | 日本护士毛茸茸高潮 | 性色欲情网站iwww九文堂 | 日韩人妻系列无码专区 | 婷婷丁香五月天综合东京热 | 精品厕所偷拍各类美女tp嘘嘘 | 熟女少妇在线视频播放 | 精品无人国产偷自产在线 | 俺去俺来也www色官网 | 日本一区二区三区免费高清 | 奇米影视7777久久精品人人爽 | 国产精品美女久久久 | 精品无码国产自产拍在线观看蜜 | 欧美熟妇另类久久久久久多毛 | 高清国产亚洲精品自在久久 | 亚洲精品国产第一综合99久久 | 久激情内射婷内射蜜桃人妖 | 亚洲一区二区观看播放 | 无码毛片视频一区二区本码 | 国産精品久久久久久久 | 国产超级va在线观看视频 | 曰韩无码二三区中文字幕 | 久久亚洲国产成人精品性色 | 免费无码av一区二区 | 老熟女乱子伦 | 亚洲精品国偷拍自产在线观看蜜桃 | 初尝人妻少妇中文字幕 | 精品午夜福利在线观看 | 国产av无码专区亚洲awww | 丰满肥臀大屁股熟妇激情视频 | 天海翼激烈高潮到腰振不止 | 日韩欧美中文字幕公布 | 国产国语老龄妇女a片 | 蜜桃无码一区二区三区 | 日韩av无码一区二区三区不卡 | 国产精品99爱免费视频 | 国产深夜福利视频在线 | 老子影院午夜精品无码 | 欧美兽交xxxx×视频 | 国产av一区二区三区最新精品 | 激情内射日本一区二区三区 | 一本大道伊人av久久综合 | 国产9 9在线 | 中文 | 亚洲精品成人av在线 | 学生妹亚洲一区二区 | 美女极度色诱视频国产 | 夜先锋av资源网站 | 丰满少妇人妻久久久久久 | 国内精品人妻无码久久久影院 | 无码国产色欲xxxxx视频 | 国产av无码专区亚洲awww | 亚洲男人av天堂午夜在 | 亚洲男人av香蕉爽爽爽爽 | 性欧美熟妇videofreesex | 网友自拍区视频精品 | 国产成人av免费观看 | 日日碰狠狠躁久久躁蜜桃 | 波多野结衣乳巨码无在线观看 | 午夜不卡av免费 一本久久a久久精品vr综合 | 久久无码人妻影院 | 99久久婷婷国产综合精品青草免费 | 一本色道久久综合亚洲精品不卡 | 中文字幕av无码一区二区三区电影 | 国产成人无码av片在线观看不卡 | 国产一区二区三区四区五区加勒比 | 亚洲男女内射在线播放 | 久久久av男人的天堂 | 亚洲精品国产第一综合99久久 | 综合人妻久久一区二区精品 | 久久精品99久久香蕉国产色戒 | 精品欧美一区二区三区久久久 | 在线欧美精品一区二区三区 | 国产无遮挡又黄又爽又色 | 中文字幕乱码亚洲无线三区 | 欧美精品在线观看 | 99久久久无码国产精品免费 | 99久久精品日本一区二区免费 | 国产性生交xxxxx无码 | 国产卡一卡二卡三 | 中文无码精品a∨在线观看不卡 | 中文久久乱码一区二区 | 影音先锋中文字幕无码 | 中文字幕乱码亚洲无线三区 | 国产熟女一区二区三区四区五区 | 国产综合色产在线精品 | 精品一区二区三区波多野结衣 | 欧美肥老太牲交大战 | 野狼第一精品社区 | 国产激情艳情在线看视频 | 国产综合色产在线精品 | 一区二区三区乱码在线 | 欧洲 | 女人被男人爽到呻吟的视频 | 2020最新国产自产精品 | 人人妻人人澡人人爽欧美一区九九 | 成人精品视频一区二区 | 日韩精品无码一区二区中文字幕 | 亚洲成a人片在线观看日本 | 国产人妻精品午夜福利免费 | 国产激情无码一区二区app | 玩弄人妻少妇500系列视频 | 永久免费精品精品永久-夜色 | 免费无码肉片在线观看 | 亚洲精品成a人在线观看 | 欧美熟妇另类久久久久久不卡 | 亚洲一区二区三区含羞草 | 国产精品igao视频网 | 亚洲伊人久久精品影院 | 婷婷五月综合缴情在线视频 | 国产三级精品三级男人的天堂 | 九九综合va免费看 | 国产欧美精品一区二区三区 | 午夜精品一区二区三区的区别 | 伊人色综合久久天天小片 | 在线a亚洲视频播放在线观看 | 内射老妇bbwx0c0ck | 蜜臀av在线观看 在线欧美精品一区二区三区 | 天堂久久天堂av色综合 | 人人澡人摸人人添 | 狠狠色欧美亚洲狠狠色www | 九九在线中文字幕无码 | 久久久久久久女国产乱让韩 | 成人试看120秒体验区 | 中文字幕av无码一区二区三区电影 | 一个人看的www免费视频在线观看 | 一二三四社区在线中文视频 | 国产精品亚洲一区二区三区喷水 | 2020久久超碰国产精品最新 | 人妻有码中文字幕在线 | 亚洲国产一区二区三区在线观看 | 人妻少妇精品久久 | 国产极品美女高潮无套在线观看 | 欧美放荡的少妇 | 成在人线av无码免费 | 99久久亚洲精品无码毛片 | 中文字幕 亚洲精品 第1页 | 久久久久成人精品免费播放动漫 | 狠狠噜狠狠狠狠丁香五月 | 自拍偷自拍亚洲精品被多人伦好爽 | 日日躁夜夜躁狠狠躁 | 狠狠色丁香久久婷婷综合五月 | 东北女人啪啪对白 | 成人亚洲精品久久久久软件 | 国产精品福利视频导航 | 色综合天天综合狠狠爱 | 中文字幕乱妇无码av在线 | 国产香蕉尹人综合在线观看 | 99er热精品视频 | 国产精品a成v人在线播放 | 男人扒开女人内裤强吻桶进去 | 国产精品久久久久9999小说 | 老司机亚洲精品影院 |