顯存滿了可以使用內存,而內存滿了只能使用硬碟了。如有方案效果如何?


首先要說一個虛擬內存的概念。很多人以為「用磁碟空間來擴展物理內存」就是虛擬內存。實際上你的所有物理內存都是虛擬內存的一部分。CPU 執行的指令中的主存地址對應的都是虛擬地址,會通過 MMU(內存管理單元)來進行轉換,而如果訪問的地址並不在物理內存上,就會產生所謂的缺頁中斷,然後藉助 IO 系統調用去外存拿頁面文件。如果 CPU 沒有 MMU,那麼就是所謂的 MCU,比如很多 stm32(基於 A7 的除外),8051 單片機。虛擬內存對於操作系統和應用程序有很多好處,一個典型的好處就是fork這個系統調用,將運行著的程序分成2個(幾乎)完全一樣的進程,這樣就可以實現 CoW(寫時複製),減少不必要的內存複製。應用的多線程相當依賴 fork。

而顯卡通常都是掛在 PCIe 上的外部設備,其顯存並不屬於虛擬內存空間,雖然顯卡因為有 DMA 能力,所以會佔用一段虛擬內存空間,但是目前來看沒有顯卡實現讓自己的顯存進入操作系統的主存空間。

其中這裡還有一個原因,操作系統的字長通常都是 32bit/64bit。而顯卡為了實現更大的吞吐量,通常都是 128bit 起步,HBM 能夠到 1024bit 的位寬,並且也沒有延遲上的優化,這對於 CPU 這樣的結構去訪問是不利的。所以使用 GDDR 的遊戲機都會配置 eDRAM/eSRAM 增加命中率,降低平均訪存延遲。但是這種情況還是 CPU/GPU/內存控制器都在同一個 Die 上的情況。如果是普通的 PC 架構,PCIe 延遲還是非常可觀的,而且吞吐也有限制。所以並不是完全不能用,而是用了收益也不大。

如果內存真的不夠用,也就只能依賴內存壓縮(比如 ZRAM)或者SWAP這樣的頁面文件機制。現在很多 SSD 基於 NVMe,特別是 Intel 的 3D xpoint 有著低延遲特性,甚至被做成 DIMM 插槽,對於提升內存空間還是有幫助的。

不過答主的這種想法不是沒人干過

Is Video RAM a Good Swap Device? - Slashdot?

hardware.slashdot.org

這位大哥把 Video RAM 變成了標準塊設備(差不多就是存儲設備),然後格式化為 SWAP 文件系統,結果發現比普通存儲設備慢了三倍(也沒說 SSD/HDD)。

Overv/vramfs?

github.com圖標

這個項目基本就是你想要的,利用 OpenCL API 將一塊顯存變成塊設備,然後這哥們做了個簡單 benchmark,開了 2GB 顯存做實驗。

  • OS: Ubuntu 14.04.01 LTS (64 bit)
  • CPU: Intel Core i5-2500K @ 4.0 Ghz
  • RAM: 8GB DDR3-1600
  • GPU: AMD R9 290 4GB (Sapphire Tri-X)

結果長這樣。2GB/s 的速度比 NVMe SSD 都要慢一點,當然沒有延遲數據。i5-2500K 目測只有 PCIe 2.0 x16,8.0 GB/s,挺一般的。


早期遊戲機這麼乾的太多了,我好像曾經回答過,你在超任裡面可以 JMP 到顯存里然後再 JMP 到手柄寄存器上,然後現場把遊戲改成任意的樣子

https://www.bilibili.com/video/av4229135/?spm_id_from=333.788.videocard.3?

www.bilibili.com

https://www.bilibili.com/video/av1050125/?

www.bilibili.com


真想用也不是不可以,甚至都不用改現在的硬體,改改os kernel和顯卡驅動就行。

顯卡是一個掛在pcie匯流排上的設備,也會佔用一段虛擬地址空間來做dma,當你設定好映射之後事實上就把一塊顯存映射到cpu能訪問的區域里了,只要os kernel和驅動不給你下絆子,這塊區域就可以當作內存用,放數據放代碼都隨你。

那麼為什麼現在大家都不這麼做呢?主要原因就是慢,顯存一般是帶寬大延遲高的內存比如GDDR5,主要適用於批量向顯卡傳遞數據,但內存的延遲一般都要很低,否則CPU的運行效率會大打折扣,而且顯卡使用PCI匯流排傳遞數據,速度相比於內存和CPU之間的專用通道慢很多。

另外還有一個小問題就是DMA映射的地址空間一般都不大且基本固定,也就是說你沒辦法直接映射全部的顯存,只能用類似古老的DOS下overlay的方式,用哪塊映射哪塊,很不方便。


內存延遲幾十ns,光顯存延遲都比這個高,更別說走pcie匯流排的延遲了。

事實上用硬碟做頁面文件時,也只是把頁面文件當作後備存儲,即把不頻繁使用的頁面放到硬碟上,畢竟硬碟訪問的延遲也很高。

從這一角度說,拿顯存做頁面文件也沒什麼不可的。

甚至於你可以繞開OS,自己寫程序時利用CUDA、OpenCL等runtime去分配顯存空間作為一部分內存使用。只不過驅動沒有針對這種情況設計,因此頻繁讀取小數據的效率很低(需要頻繁同步,還可能會佔用內存來緩存你要寫入/讀取的數據),更適合批量讀取。

至於為什麼沒有發展這項技術……顯存也是dram,和內存一樣貴,有買顯卡的錢不如去買內存啊……相比之下機械硬碟和SSD、乃至傲騰都更便宜,才有了作為後備存儲的意義。

另外還有很多機器是沒有獨顯的,畢竟intel才是最大份額的顯卡廠商。


@Luv Letter 的答案基本上已經回答你的問題了:

內存可以給顯卡用,為什麼不能把顯存給cpu用?

這個問題可以轉化擴展一下:PCIe 卡上的存儲是否可以另做它用?答案是可以的,你的問題只是其中一個沒有太多 value-add 的方案,太局限了。

簡單發散:是否可以把 NVMe 當成內存用呢?答案是毫無疑問,HW 和 FW 都不需要做改動,現在所有的OS都支持這種玩法,也就是所謂的虛擬內存。

繼續發散:是否可以把內存放在PCIe卡上?答案也是可以的,PCIe 卡要支持這個功能並需要 FW 進行改動;這種設計會更有價值,而且有對應的產品已經上市:西數的 Ultrastar DC ME200 Memory Extension Drive。

產品介紹:

Ultrastar DC ME200 Memory Extension Drive

https://documents.westerndigital.com/content/dam/doc-library/en_us/assets/public/western-digital/product/data-center-drives/ultrastar-dc-me200/data-sheet-ultrastar-dc-me200.pdf

上述方案為什麼可以實現?

CPU core 需要從一個地址中抓取數據,core 並不需要知道這個地址屬於誰,只需要把訪問請求發出去就可以,CPU 內部會有專門的路由邏輯去解析地址,並把這個請求送往地址對應的設備,然後設備響應請求帶回數據給請求的core。

由於 CPU 不需要知道這個地址屬於誰,所以這個地址可以是一個落在 DIMM 中的地址,也可以是落在一個 PCIe 設備的地址,對core 來說他們的區別僅僅只有拿到數據的快慢之分(DIMM 比 PCIe快),而路由邏輯僅僅是起到把請求發給指定的設備;從上面兩點看,CPU HW 不需要做變動就可以實現我們的目的,但我們需要對 PCIe 卡 和系統的 UEFI/BIOS 做一些定製:

a. PCIe 卡需要申請足夠的 MMIO 空間(MMIO空間是一段內存地址,這個地址落在了PCIe 卡上,而不是DIMM上),並且PCIe卡能夠支持到這麼大的MMIO 空間 (空間的大小直接影響了PCIe 卡內部要實現的地址線的數量;和 CPU一樣,卡內部的地址線並不是64,卡的地址匯流排一般來說都是40多,更多的地址匯流排可以支持更高的定址,但會帶來成本的增加),而且這段空間要用來做 MMIO 不做其他用途。

b. 一般來說 MMIO 空間在被 UEFI/BIOS 彙報給OS 的時候,屬性標註的是 MMIO,OS 並不會把 MMIO空間做memory使用,應用申請內存的時候OS會從屬性為 memory 的地址空間分配,所以針對這張卡的 MMIO 屬性要在report給 OS之前,被UEFI/BIOS 改成 memory 屬性。

經過上述兩步之後OS下看到的內存大小就是 PCIe 卡 + 所有 DIMM 容量的大小了。但這會有其它的問題:同樣的內存空間,訪問DIMM要遠快於PCIe 卡,OS如果不知道他們的區別,那麼系統的性能就會忽高忽低;所以最後還是需要 OS 做改動,讓OS 可以知道有段內存空間落在 PCIe 卡上,有比較大的訪問延遲,同時可以針對性這個 PCIe 卡的內存地址做一些特殊的cache 設計,優化其性能。


推薦閱讀:
相关文章