英偉達GeForce RTX 2080 Ti圖靈架構淺析

6 人贊了文章

作者:陳寅初

曾幾何時,人們為了在屏幕上能實時顯示幾個有深度感的方塊而歡呼雀躍,1993 年經典遊戲 DOOM 問世的時候,遊戲業界媒體發表了大量圍繞該遊戲的報道,除了通關攻略外,對遊戲開發人員、遊戲技術都進行了全方位的報道,原因無他——這是當時第一個能在個人電腦上以實時三維方式渲染的第一人稱網路遊戲,在遊戲圖形史上的地位舉足輕重。

自此以後,圍繞電腦實時三維渲染圖形的技術和應用開始鋪天蓋地的湧現,CPU 方面首先發力,擁有更強浮點性能以及 SIMD 的 Pentium II 問世,不過 CPU 畢竟主要負責邏輯代碼的處理,遊戲只是眾多任務之一。

因此為了實現更快的實時渲染性能,人們又推出了專門針對遊戲圖形加速晶元,3Dfx、NVIDIA、ATi、S3 等等眾多(還有許多現在已經消失的)顯卡廠商都在此時興風作浪。最終,經過激烈的市場競爭,到了 2002 年的時候,隨著 NVIDIA 收購 3dfx,顯卡競爭廠商也就剩下兩家:NVIDIA 以及 2005 年被 AMD 收購的 ATi。

受制於晶元面積的緣故,人們往圖形晶元堆放的功能並非一步到位,對速度追求的優先度總是優先於功能。

例如早期的遊戲圖形晶元也就是實現了三角形設置、貼圖、顏色混合這三個功能,在這之後纔是逐漸加上頂點變換(例如 NVIDIA Celsius攝氏,Celsius是架構代號,代表晶元是全球第一枚 GPU NV10,例如採用 NV10 的 GeForce 256)、多採樣抗鋸齒(例如 NVIDIA Kelvin開爾文)、可編程著色器(例如 NVIDIA Kelvin開爾文)、高級語言通用計算(NVIDIA Tesla特斯拉)、統一架構(NVIDIA Tesla特斯拉)、曲面計算(NVIDIA Fermi費米)等特性。

不過在 GPU 功能、性能不斷提升的日子裡,業界一直伴隨著一種聲音:什麼時候可以實現光線追蹤渲染呢?

現在的遊戲絕大多數都是採用名為光柵渲染的技術,而光線追蹤則和光柵渲染有不少區別,在過去它都是離線渲染才會使用的渲染技術,不過到了今年,NVIDIA 公司卻公佈了首款具備專門光線追蹤硬體加速的微架構——圖靈Turing,這標誌著沿用了 20 多年的遊戲渲染技術終於迎來了首次真正意義上的革命,人們得以嘗試基於物理的實時渲染加速。

看到這裡,相信有些人已經有點看不下去了,因為上面引出一堆諸如光柵化渲染、光線追蹤的學術名詞。好在這些東西解釋起來其實並不是很複雜,接下來我會嘗試用最短的篇幅來介紹,務求大家看完後能知道基於圖靈架構的顯卡是否就是自己要買的那塊顯卡。

光的起源:光柵化與光線追蹤

PC 上比較著名的早期三維遊戲《德軍總部 3D(Wolfenstein 3D)》使用的是名為光線投射(Ray Casting)技術實現的,它的原理是在某種幾何尺度限制的前提下進行光線投射和追蹤。例如,顯示器的解析度是 320×200 個像素的話,光線投射器只追蹤 320 條光線(因為水平像素解析度只有 320 個)。

在大多數情況下,這種渲染方式的方程並不準確(例如不進行場景光線遞歸),渲染品質不是很真實(稍微湊近看到的都是斑塊),但是速度比較快。除了德軍總部 3D 外,Raven 公司的 Shadow Caster、Bethesda 公司的 Arena、前面提到的 id Software 的 Doom 以及盧卡斯公司的 Dark Forces 都採用了 Ray Casting 技術。

光柵化渲染

現在的遊戲都採用了名為光柵化(rasterization)的方式進行渲染,在光柵化渲染流水線上,同一時間內都是在畫一個三角形。

這個三角形需要先經過計算確定其大小和位置,然後到了光柵器上,由光柵器計算出有哪些像素被其覆蓋以及在被覆蓋像素上的投影面積。

光柵化渲染的好處是快速,例如渲染大場景的時候,因為理論上每次渲染的時候內存裏只要存放一個三角形的信息即可,三角形的屬性維護可以在寄存器或者高速緩存裏進行,這樣能減少內存傳輸;只需要渲染被當前三角形覆蓋的像素即可,如果配合一些隱面消除技術,還可以減少需要渲染的三角形數量。

問題是,光柵化每次都只渲染一個三角形,很多效果其實至少需要兩個三角形才能實現,例如把三角形的陰影投射到另一個三角形上、三角形和另一個三角形的倒影、場景中所有三角形的光照反射等等。

光柵化渲染要實現複雜特效來模擬真實世界需要用上許多技巧,而這些技巧有時候會彼此之間存在衝突,需要另外的技巧來避免,這使得光柵化渲染在實現高級特效的時候會相當複雜,使得渲染器的編寫、維護成本日益高昂。

光線追蹤渲染

光線追蹤(Ray-Tracing)就是一種用射線來確定不同元素可見性的渲染方法,它的實現原理相當簡單,用 C++ 語言寫成代碼的話,完全可以放到一張名片上(最初的實現來自這裡):

這張卡片上的代碼可以以光線追蹤的渲染方式畫出下面的效果:

這裡插播一個視頻,也許能讓你對實時光線追蹤能達到的效果有更直觀的瞭解。

實時光線追蹤能達到的效果

光線追蹤的方式可以分為正向光線追蹤(從場景裏的光源發射光線)和逆向光線追蹤(從觀察者或者說眼部、攝像機燈發射光線)。

現在人們一般所指的光線追蹤演算法,都是採用逆向光線追蹤方式,讓光線從「眼部(或者說』相機』)」發射,穿過屏幕上像素柵格進入場景中,直至找到最近的物體,確定與物體的交匯點,這個動作被稱作求交。

「眼部」發出的第一條射線被稱作主射線(primary ray)

光線追蹤的第一次求交和德軍總部 3D 採用的光線投射渲染方式是一樣的,但是光線投射不會做接下來的反射、折射等光線遞歸處理。

此時,這條光線可能會被物體吸收、折射、反射,也可能會落入到陰影(交匯點和光源之間存在遮擋物)中,根據物料和光照等條件,交匯點會被著色器畫上相應的顏色。對於存在折射、反射、陰影的情況,需要再從交匯點發射光線,直到遇到吸收表面、或者抵達場景極深處,完成遞歸。

光線追蹤求交後,出現需要遍歷場景其餘三角形而發射的射線被稱作次生射線(Secondary Ray),包括反射射線、折射射線、陰影射線。

此時,該像素的顏色最終確定下來了。

比較有趣的是,雖然我們現在覺得正向光線追蹤是最自然的光照原理,但是從誕生時間上來說,逆向光線追蹤理論誕生得最早,它可以追溯到公元前五世紀古希臘哲學家恩培多克勒提出的古怪理論。

和當時的許多希臘人一樣,恩培多克勒認為萬物都是由火、空氣、泥土、水構成的,但是他相信希臘愛神阿芙洛狄蒂將人類的眼球獨立於四種元素之外,並在其中點燃了火光,這些火光從眼部射出,使得人們有了視覺。

而正向光線追蹤是到了公元 11 世紀左右才由阿拉伯科學家海什木提出,他認為我們之所以能看到物體,是因為來自太陽的光線:以直線方式行進的微小顆粒流從物體反射到我們眼中。

由於場景中的光源發出的絕大部分光線不會在觀察者看到的光線中佔很大比例,因此逆向光線追蹤在效率上要比正向光線追蹤高很多倍。

光線追蹤的目的是要構建出整個場景的可視信息以及光照條件,藉此計算出光線和場景中物體相交時光線的反射、折射、吸收、遮擋信息,但是一般來說,它並不怎麼考慮漫反射的情況,而且物體表面的屬性相對單一。

對於漫反射,人們也會使用輻射度演算法實現,當然,這和光線追蹤並不矛盾,輻射度可以在光柵化和光線追蹤渲染流水線中應用,例如 EA 的遊戲戰地三就用了輻射度來模擬全局光照。

相對於光柵化渲染速度快但是複雜的特點而言,光線追蹤則剛好相反,它的渲染演算法比較簡單,但是要實現逼真的效果,是需要大量的計算才能實現,與光線追蹤的技巧主要是如何實現節省計算資源和減少內存存取上。

上面兩張圖分別是在 DirectX 12 中的光柵化渲染流水線(簡化)和光線追蹤流水線,你可以看出兩者在輸入、前端處理、中段渲染上是很不一樣的。

我們在這裡說了一大堆看上去比較理論的東西,目的是為了下面的圖靈架構介紹可以更簡單明瞭,因為像光柵化這樣的渲染框架其實對於許多人來說也是不清楚的,更不要說又冒出了個光線追蹤出來,而光線追蹤中能加速的部分正是圖靈架構的重大革命。

尋光之旅:NVIDIA 圖靈體系架構概況

自從 2006 年 11 月發布 G80 至今,NVIDIA 已經推出了多代支持 CUDA 的 GPU 微架構,它們分別是 Tesla 特斯拉、Fermi 費米、Kepler 開普勒、Maxwell 麥克斯韋爾、Pascal 帕斯卡、Volta 伏特,以及在半個月前才剛剛發布的 Turing 圖靈。

如果大家有關心前兩年 NVIDIA 發布的架構路線圖的話,應該都知道,當時的架構路線圖最後一個代號是 Volta,在這之後 NVIDIA 的路線圖一直未更新。

按照 NVIDIA 以往的做法,在 Fermi 之後的每代微架構,都會衍生超算、高端、中端、低端/入門四個產品線,例如 Pascal 微架構下,有 GP100、GP102、GP104、GP106、GP107、GP108 等六個晶元。

其中 GP100 是面向超算為主,只存在於 NVIDIA 的 Tesla 產品線裏,餘下的其餘 GP 系列 GPU 都能在 GeForce 遊戲產品相中找到對應的型號,例如 GeForce Titan Xp 是足本的 GP102;GeForce GTX 1080 採用的是 GP104,面向高端玩家;基於 GP106 的 GeForce GTX 1060 系列面向中端玩家;基於 GP107 的 GeForce GTX 1050 系列面向主流玩家以及遊戲筆電。

不過到了 Volta 這一代,NVIDIA 目前為止只做了一枚晶元:GV100。GV100 提供了高性能雙精度、多達六條 NVLINK 2.0 通道等遊戲卡市場用不上的特性,完全針對超算市場,具體產品目前只有 Tesla V100、Quadro GV100、Titan V、Titan V CEO 四款卡,此外還有以整機伺服器提供的 DGX-2。如果說衍生內核的話,倒是有一個針對嵌入式市場的 Tegra Xavier 小晶元集成了 Volta 架構的縮水版。

在 8 月 14 日的 Siggraph 計算機圖形學頂級年會上,NVIDIA 正式公佈了 Turing 微架構,一併發布的是基於該架構的 Quadro 8000/6000/5000 三款專業顯卡,它們都是針對圖形工作站或者渲染農場為主的應用。

在不到一週後的德國,NVIDIA 公佈了基於 Turing 微架構的遊戲卡產品線 GeForce RTX 2080Ti、GeForce RTX 2080 以及 GeForce RTX 2070:

我們都知道,GeForce 這個名稱最早是在 NV10 開始啟用的,Ge 的含義就是 Geometry 幾何的含義,GPU 的說法也是從那時候被 NVIDIA 給出明確定義的:每秒至少能處理 1000 萬三角形的圖形晶元。

RTX 這個產品名稱後續是 Turing 架構首次出現,其中的 R 就是指英文裏 ray 即光線或者射線的意思。

上面三張圖是目前圖靈架構 TU102、Volta 架構 GV100以及 Pascal 架構 GP102 的架構簡圖,更多具體的細節我會在稍後給出,這節裏我們先從晶元的宏觀角度看看。

首先,TU102 一共有 6 個 GPC(圖形處理簇),每個 GPC 裏包含有七個 TPC(紋理處理簇),每個 TPC 裏有兩個 StreamingMultiprocesor(流式多處理器,SM,對應 OpenCL 中的概念就是 CU,Computing Unit),每個 SM 裏包括若干個 CUDA Core。

現在的 GPU 都是類似的多層階式多核設計,而 GPC 的劃分基礎是它有一個光柵處理引擎。

對於編寫 CUDA 通用計算或者說深度學習之類應用的人來說,GPC 甚至 TPC 都是不需要去了解的概念,絕大部分情況下,編程人員需要關注的是 CUDA Core,如果需要進一步優化代碼的話,可能還會考慮 SM 層面的東西。

但是對於遊戲來說,在傳統光柵化渲染的時候,每個 GPC 可以跑一個三角形,因此六個 GPC,意味著在三角形不相依的情況下,TU102 最高可以同時跑六個不同的三角形。這相當於著 TU102 內有 6 個小 GPU。所以從硬體光柵加速渲染的最高層級角度看,TU102 就是一個 6 核處理器,這 6 個內核都需要透過 L2 Cache 完成所有的訪存操作。

GPC 使用光柵處理引擎作為劃分基礎,而 TPC 或者說紋理處理簇「現在」是以 Tesslation 引擎(NVIDIA 稱之為 PolyMorph 引擎)為基礎劃分的,每個 TPC 裏都有一個 PolyMorphy 引擎。

每個 TPC 根據架構和 GPU 實現的不同,其中包含的 SM 數也不一樣。在 Fermi 之前的 GPU,例如 G80,每個 TPC 裏包含有兩個 SM,GT200 包含有三個 SM。這些 Fermi 之前的 GPU 只是以幾何控制器和 SM 控制器為基礎劃分 TPC 的。

而在 Fermi 出來後的一段時間裡,TPC 以 PolyMorph 引擎劃分,幾何控制器則部分下沉到 SM 裏。由於NVIDIA 在 Fermi 到 Maxwell 這段期間的微架構,TPC 只包含一個 SM,TPC 和 SM 在概念上是重疊的。

因此 NVIDIA 基本不再提及 TPC,因為對編程人員來說,TPC 相當於是透明的概念,而 SM 在多階層線程編寫中是一個非常重要的映射單元,所以 SM 的概念必須存在。

在這時候開始, SM 的名字出現了各種變化:SM->SMX(Kepler)->SMM(Maxwell),名字的變化並非沒事亂改,而是這些不同的 SM 在控制單元上發生了重大變化。

到了 Pascal 後,TPC 又在架構圖中出現,命名的混亂消除了。

去年 GTC 2017 上發布的 Volta 架構和新發布的 Turing 架構裏,TPC 中包含的 SM 數量增加到了兩個。

通常來說,在同一個層階裏容納更多的下級單元規模,一般是為了提升該層級的吞吐量。

對於 Volta 來說,節省的晶體管用在了雙精度和張量內核,而對於圖靈來說,節省的晶體管就用在了光線追蹤和張量內核。

其中,兩個新架構都集成了張量內核,說明 NVIDIA 認為不管是超算、遊戲或者工作站領域,人工智慧加速已經是不可或缺的東西。

TU102 晶元物理上一共有 72 個 SM,但是目前的 GeForce RTX 2080 Ti 只有 68 個 SM,這意味著 2080 Ti 裏有 4 個 SM 或者說兩個 TPC 被屏蔽了。

單論單精度浮點性能的話,GeForce RTX 2080 Ti 和 GeForce GTX 1080 Ti 差別不是很大,前者也就是比後者快大約 10%,但是如果你看看紋理性能、內存帶寬等指標,都可以發現,前者具備比後者快得多的局部性能,而它們在目前的遊戲性能影響還是著舉足輕重的。

在製造工藝方面,Volta 和 Turing 都採用臺積電 12 納米線寬製程(12FFN,N 表示專為 NVIDIA 定製)生產,這個製程屬於 16 納米工藝節點。

上面分別是 TU102 和 GP102 的管芯圖,圖片已經按照尺寸比例進行了縮放。大家可以看到,TU102 的管芯面積達到了 754mm^2,長寬分別大概是 30.7mm 和 24.6mm,比全畫幅相機的感測器只是略小一點,不過 NVIDIA 目前最大的晶元依然是數月前發布的 GV100,GV100 的管芯面積是 815mm^2(晶體管數量 21B)。

如果按照晶體管密度來看的話,TU102 密度其實要比 GP102 低,這可能是因為 TU102 的邏輯電路比例更多導致的。

雖然晶體管密度降低了,但是可能因為 12nm 製程以及 GDDDR6 內存更省電的緣故,官方給出的 GeForce RTX 2080 Ti 全卡耗電和 GeForce GTX 1080i 保持在一個水平上,都是 250 瓦特,需要配合怎樣的電源以及進行散熱管理纔是用戶真正關心的。

生於遊戲:圖靈微架構——Streaming Multiprocessor

前面說過,Turing 基本承繼自 Volta,主要是強調了遊戲性能,下面就讓我們來看在具體的架構細節上 Turing 是長成什麼樣子吧。

首先,我們來看看 SM 部分。

完整的 TU102 有 72 個 SM,GeForce RTX 2080 Ti 是 68 個,目前只有 Quadro RTX 8000/6000 是具備完整 72 個 SM 配置的。

如果說從光柵圖形渲染的角度看,一個 GPC 是一個小 GPU,那麼在通用編程中一個 SM 就相當於一個硬體內核,可以同時跑一個或者多個寬度為 32 的 SIMT 指令(NVIDIA 稱之為 Warp)。

在最初的 NVIDIA 微架構 Tesla 中,每個 SM 有 8 個 CUDA core(CUDA Core 在 OpenCL 稱作 PE),一個 Warp 指令或者說 Warp 線程中包含有 32 個 CUDA thread(Open CL 稱作 work-item),因此 Tesla 的 SM 需要花 4 個週期才能完成一個 Warp。

從 Tesla 的下一代架構 Fermi 開始,SM 中出現了兩個調度器和兩個指令分發器,每個調度器/指令分發器下對應有 16 個 CUDA Core,因此 Fermi 的 SM 可以一個週期跑完一個 Warp。

到了 Maxwell 後,NVIDIA 為 SM 引入了 Sub-Core(子核,又被稱作 Processing Block 處理塊)的概念,每個 SM 依然具備共享的 L1 Cache 和 SharedMemory(或者說 SMEM),但是內部的資源被劃分為 4 個各含 32 個 CUDA Core 的子核,這些子核每個都有自己的調度器和指令緩存,NVIDIA 對 Maxwell 的 SM 命名為 SMM。

Turing 和 Volta 的 SM 基本沿用了 SMM 的基本框架,其中也是有 4 個子核,每個子核可以每個週期執行一個 Warp 或者說 32 個單精度 FMA 操作:

和 GP102 不同的是,如上圖所示,TU102 的 SM 中每個 Sub-Core 都引入了兩個 Tensor Core(張量內核),這些 Tensor Core(張量內核)可以每個週期跑 64 個混合精度張量操作,因此 TU104 的每個 SM 集成了 8 個 Tensor Core(張量內核),可以每個週期跑 1024 個混合精度張量操作。

Tensor Core(張量內核) 是 Volta 或者說 GV100 才首次引入到 GPU 的,它的作用是加速人工智慧運算。

人工智慧是當下最熱門的科技前沿學科,像自動駕駛、動態捕捉合成、改頭換面等等,都是現在大家耳熟能詳的應用。

在遊戲領域,NVIDIA 已經有了若干項能結合人工智慧加速的應用,例如光線追蹤去噪、深度學習超取樣抗失真混淆等等,隨著人們進一步的研究,必定會有遊戲與人工智慧結合的應用場景產生。

在整數運算方面,Turing 也和 Volta 一樣,將整數運算單元擁有自己專門的指令發射埠,浮點運算和整數運算可以並行執行。

按照 NVIDIA 提供的資料,現在的遊戲著色器程序,每 100 條浮點指令,就會伴隨有平均 36 條整數流水線指令。很顯然,兩者並行執行的話,指令吞吐率將得以提升,遊戲速度自然也提升了。

Turing 的每個 SM 還集成了兩個 FP64 單元(上圖中並未畫出),和 FP32 單元的比例 1/32,集成 FP64 單元的目的主要是為了確保兼容性。

Turing 的 SM 集成了 96 KiB 大小的 SRAM,這個 SRAM 可以由驅動程序或者開發人員確定分配為 L1 數據緩存和 SharedMemory。SharedMemory 的存在是為了讓一個 Thread Block 內的 CUDA Thread 可以共享數據,驅動程序一般可以為其確定最佳的大小,例如 Thread Blcok 內的 CUDA Thread 不需要進行數據交換的話,那麼 SharedMemory 可能會被設置為 0KiB,這塊 SRAM 就會被配置為 L1 D-Cache,改善隨機數據存取性能。

理論上,L1 D-Cache 和 SharedMemory 最好獨立分開,但是受制於晶體管和耗電成本,當我們需要儘可能多的實現隨機存取加速的時候,在 Maxwell 上曾經採用的獨立分開設計可能未必是最佳化的設計。

像 Turing 引入了硬體光線追蹤,而光線追蹤在遍歷場景的時候,很容易發生大量的隨機存儲,一個可以配置的 L1 D-Cache 也許是一個不錯的性能改善方案。

遊戲卡新絕技:RT Core 光線追蹤內核

微軟公司在今年的 GDC (遊戲開發者峯會)上公佈了 DX12 DXR(DirectX Raytracing)技術,讓開發人員可以透過該介面比較方便的實現遊戲實時光線追蹤渲染開發,至此,光線追蹤終於從過去基本只在離線渲染中看到轉為實時渲染的可選項了。

和微軟的其他 DirectX API 一樣,DXR 並沒有明確硬體應該如何運作,只是指明瞭硬體應該具備哪些特性,允許讓廠商將函數功能以黑盒子硬體的方式實現,這樣的做法讓 GPU 廠商有了可以用自己的方式來實現這個功能的可能。當然,具體的一些要求細節可能還是有的,例如輸入、輸出的要求、限制等,應該都是有保密協議,一般來說都是軟體開發人員自己嘗試了後才知道:哦,原來有這些限制。

其實早在 2004 年(GeForce 6800 時代)的時候,當時的 NVIDIA 首席科學家還是 David Kirk,他與德國薩爾大學(也有稱作薩爾布呂肯大學)的 Philipp Slusallek 教授有過一場關於光線追蹤和光柵化渲染的激烈辯論(Philipp 在此之前也曾經在 NVIDIA 公司工作過,所以兩人的觀點比較能擦出火花)。

當時 ,Slusallek 教授正在做光線追蹤的相關研究,甚至做了一個光線追蹤加速晶元,提出了實時渲染未來應該選擇專用的光線追蹤晶元。而 Kirk 除了強調光柵化非常快外,也沒有否認光線追蹤的好處,但是他特別指出定製硬體無法維持維持龐大的處理器研發費用,每 6-9 個月性能倍增的 GPU 纔是實現 Ray Tracing 的正確途徑。

Philipp Slusallek

在三年後也即是 2007 年,NVIDIA 還真的伴隨 G80 發布了採用 Ray Tracing 技術的 D3D 演示程序——Luna,Luna 演示場景中有一個超大的眼球物體使用了 Ray Tracing 技術。

所以,很早之前的 GPU 已經具備了足夠的通用性來實現光線追蹤了,當然,性能是另一回事。

這次 DXR 也提供了兩種執行方式,分別是 Compute-base Path 和 DXR API Path。前者就是在 DXR 框架內的使用 GPU 已有的通用計算單元來跑光線追蹤,而後者,就是在具備遵循 DXR 框架的硬體加速電路的 GPU 上執行光線追蹤,DXR 中負責判斷交給誰來跑的部分被稱作 Feedback 層。

例如,對於 Pascal 架構的 GPU,DXR 是完全軟體方式執行的,Volta 的情況有些特別,它可以使用 Tensor Core(張量內核) 來實現光線追蹤的去噪處理,真正第一款遵循 DXR 硬體加速要求的,也就是新的 Turing,只有它具備 RT Core。

在 Turing 之前,也有一些光線追蹤的硬體,例如前面 Philipp Slusallek 教授在 2002 年的時候就搞出了名為 SaarCOR(Saarbrucken』s Coherence Optimized Ray Tracer)的硬體架構,最初是在 FPGA 上實現的,後來也拿到了 IBM Cell 上跑了一下。在SaarCOR 後,薩爾大學在 2005 年還弄出了 RPU,同樣是基於 FGPA 實現的。

在 RPU 之後,另一個重要的光線追蹤硬體是來自 Caustic Graphics 在 2010 年推出的的 CausticOne,可以在和 CPU、GPU 結合的情況下,用作光線追蹤全局光照以及光線相關的加速計算。在同年的 12 月,開發 PowerVR 的 Imagination 公司收購了 Caustic Graphics,推出了集成可以每秒跑 50M 條光線的 RT2 的 RT2500 和 RT2100 光線追蹤加速卡。2014 年。

Imagination 發布了名為 PowerVR GR6500 的 GPU,這是全球首枚集成了專用光線追蹤硬體加速單元(RTU,Ray Tracing Unit)的 GPU,在 600MHz 的頻率下能做到每秒跑 300M 條光線(MRPS,million rays per second),採用 GLSL 為編程語言。

PowerVR GR6500 是一枚 GPU,其中集成了 1 個光線追蹤加速單元,而 NVIDIA Turing 架構則是每個 SM 內都集成了一個 RT Core,一個完整的 TU102 一共有 72 個 SM,也就是有 72 個 RT Core。GeForce RTX 2080 Ti 的光線追蹤性能號稱可以達到 10 GRPS(我們並不清楚 NVIDIA 這個指標是如何衡量的,只知道是在場景中只有一個三角形的情況下的理論值),相當於 PowerVR GR 6500 的 33.3 倍。

那麼,既然像 Pascal 用通用計算單元的方式也能跑光線追蹤,為什麼 Turing 不直接增加通用計算單元來實現更快的光線追蹤性能呢?

答案很簡單,光線追蹤涉及的某些操作非常耗時而且動作重複。

機器最適合做重複的事情,目前發明的機器,主要都是用來幹又臟又累又重複的活,對圖形渲染來說,就是典型的重複、耗時操作,光線追蹤更是如此。

Imagination 介紹 PowerVR GR6500 的時候提到,在 AABB(軸對稱包圍盒)測試的時候,涉及到 26 條指令,如果將這個操作做成專門的固化電路,面積可以縮小到由通用計算單元來實現的 1/44。

光線追蹤可以拆分為三個動作,分別是:

射線的生成

找出射線與場景物體交匯點的求交測試

對交匯點進行著色計算

其中,求交測試或者說第二步是最耗時的操作。

身為電子工程師和計算機科學家的 John Turner Whitted 在 1979 年發表了一篇名為 《An improved illumination model for shaded display》的論文,這是首次在計算機圖形引入遞歸式光線追蹤,如今 John Turner Whitted 是 NVIDIA 研究事業部的一員,8 月份的時候還在 NVIDIA 官網發表了一篇使用光線追蹤實現全局光照的文章。

Ray Traycing之父:John Turner Whitted

按照 Whitted 的說法,對於簡單場景來說,75% 的耗時都花費在了光線和場景物體的求交計算上,在更複雜的場景中,這類操作的耗時會高達 95%,

求交計算的耗時與場景中涉及的物體數量直接相關。

怎麼理解這句話?

假設你手頭一張拼圖,拼圖有大約 1000000 個毫無規則的圖塊組成,現在你需要將這些圖塊復原,那你就是逐個嘗試了。

我們人腦雖然具有豐富的想像力,但是其實記憶力一般,1000000 個圖塊,說不定需要數年時間才能拼完整。

光線追蹤也是類似的情況。

場景的三角形存放在內存中,射線從眼球發射到像平面穿過像素後,需要從內存中存放的場景中包含的數以百萬計的三角形中查找到可能剛巧被擊中的三角形。實際的情況其實更複雜,因為光線追蹤碰到的三角形很可能存在折射、反射、陰影等情況,這也就有了次生或者衍生射線(Secondary Ray),次生射線還得繼續做求交測試。

所以這樣的處理過程相當耗時。

那麼,如果拼圖出廠的時候,已經預先按照原圖中的對象關係將圖塊打包為若干份(例如拼圖裡有自行車、汽車、人物,就按照這樣的對象,一個大致的對象打包為一份),那拼圖的速度也自然能提升。

如果能儘可能地減少求交測試的物體,求交測試的時間自然可以減少,從而提升性能,例如對於複雜的場景減少 50% 的物體,那麼性能差不多能提升一倍。

為此,人們又提出了所謂的加速結構(acceleration structure)或者說加速結構體,希望透過某種數據結構實現儘可能快地找出場景中哪些物體可能會被某些射線擊中,以及扔掉那些包含有永遠不會被射線擊中的物體的包圍盒。

對於剛剛接觸編程的人而言來說,數據結構和演算法簡直是夢魘般的存在,所以在我們這裡不打算對光線追蹤的加速架構作深入的分析,只是簡單介紹一下,因為這對理解 RT Core 還是有幫助的。

Kay 和 Kajiya 在 1986 提出了使用 BVH(Bounding Volume Hierarchy包圍盒層級)的數據結構作為光線追蹤加速結構的技術,現在幾乎所有的實時光線追蹤技術都是採用了 BVH 作為加速結構。

BVH(包圍盒層級) 的概念很簡單,例如場景中有一輛自行車、一部空的汽車,其中自行車上還有一個騎車人,我們可以把這個自行車、騎車人、汽車都用一個包圍框(A)框柱,然後自行車和騎車人也放在一個包圍框中(B),汽車也給一個包圍框(C)。

此時,我們看到場景中有三個包圍框,分別是 A、B、C。其中,B 和 C 是 A 的子集,。

包圍框 B 裏有兩個物體,分別是自行車和騎車人,我們可以繼續給兩者各一個包圍框,分別是 D 和 E 吧。

如此類推,直到我們把這些對象拆成原子~~~噗。

如果這些對象都是用三角形構成並且我們用樹狀結構來存放這個 BVH 的話,那麼這個 BVH 的根就是包圍框 A 或者集合 A,而最底層根莖就是三角形了。

微軟 DXR 的加速結構和 BVH 類似,採用了兩級的加速結構。

具體的幾何體被納入到 Buttom Level AS(低層加速結構,簡稱 BLAS)中,在這個基礎上,微軟引入了名為 Top Level AS(上層加速結構)的數據結構,在這個 TLAS 裏,存放有經過一些轉換處理的 BLAS 幾何體的引用。

如下圖所示,藍色的框框就是 TLAS,紅色的就是 BLAS(圖片取自 Remedy 今年 GDC 上的幻燈片)。

有了 BVH 後,進入場景後的射線首先會嘗試看看是否有包圍盒被撞上,有的話,那就繼續找被撞中包圍盒的子包圍盒,如此類推,直到撞上最後的三角形。

至此,我們已經瞭解了,光線追蹤最耗時的操作就是射線與場景物體的求交,使用加速結構可以有效減少求交的物體從而提升性能,常見光線追蹤加速結構就是 BVH,微軟 DXR 的加速結構屬於 BVH,而 NVIDIA 的 Turing 微架構正是將三角形和 BVH 的求交測試遍歷演算法集成到了 RT Core 中。

具備 RT Core 的 Turing 運行光線追蹤能實現射線求交測試和著色程序並行運行

不具備 RT Core 的舊式 GPU 運行光線追蹤的時候需要消耗上千條指令槽來跑單條射線求交測試,佔用了著色程序資源

在沒有 RT Core 的 GPU 上,BVH 的遍歷需要使用著色器單元來執行,每次使用光線投射對 BVH 中包圍盒執行求交測試直到最後撞上三角形確定交匯點(確定交匯點纔可以知道應該給射線穿越的像素「畫」什麼顏色上去),需要跑上千條指令。

EA 下屬的研究機構 SEED 使用原型版圖靈和 Volta(Titan V)進行的光線追蹤性能對比分析,測試的項目名為 PICA PICA,項目是開源的。

PICA PICA 最初是在 Volta 上實現的,測試用的版本未經過代碼修改,Volta 跑的代碼和 Turing 跑的是一樣的,未針對 Turing 作專門的優化。

測試結果可以看到,Turing 比 Volta 在 1 個 Primary Ray(主射線,也就是光線追蹤從眼球發射到每個像素上的射線)的情況下,陰影和環境遮蔽的性能為 Volta 的 3 倍以上,隨著 Primary Ray 的增加,性能的提升效果也越來越明顯,在 16 條 Primary Ray 的情況下,Tunring 在陰影、環境遮蔽特效上可以達到 Volta 的 5 倍以上性能。而在大家比較關心的全局光照方面,Turing 達到了 Volta 的 4.8 倍性能。

按照 NVIDIA 的說法,TU102 的 GeForce RTX 2080 Ti 和 GP102 的 GeForce GTX 1080 Ti 純光線追蹤(射線求交)性能分別是 10 GRPS 和 1.1 GRPS,而 GeForce GTX 1080 Ti 的理論單精度性能是 10.6 TFLOPS,換算出來就是 10 TFLOPS/GigaRay,因此可以認為 GrFoece RTX 2080 Ti 的 68 個 RT Core 性能為 110 TFLOPS 左右。

按照之前 NVIDIA 給出的每條射線需要上千條指令才能完成一次完整的求交來看,GeForce RTX 2080 Ti 的 RT Core 部分等效 110 TFLOPS 也是可以對得上的。

如果按照 10 GRPS 來算的話,GeForce RTX 2080 Ti 的每個 RT Core 每個週期大約可以跑 0.1 條射線求交測試,或者說每個週期完成等效 100 條指令的左右浮點計算。

給細節打雞血:Tensor Core 張量內核與遊戲加速

前面我們介紹過,2017 年 5 月發布 的 Volta 開始引入了名為 Tensor Core(張量內核)的新單元,這個東西的引入主要是因為當前深度學習如火如荼,大量相關應用被開發出來了,而深度學習有大量計算涉及的數據並不需要很高的精度,因此,許多深度學習加速處理器都採用了混合精度,以追求儘可能高的運算吞吐量,Tensor Core(張量內核)的設計也是基於同樣的理念。

Turing 的 Tensor Core 和 Volta 的 Tensor Core 是不一樣的。Volta 的每個 Tensor Core(張量內核) 可以一個週期完成 16 位輸入的 4*4*4 個操作,每個 SM 一個週期可以跑 1024 個張量操作,GeForce RTX 2080 Ti 可以每秒跑 107.6T TensorOp。

而 Turing 在這個基礎上,還引入了 INT8 和 INT4,INT8 的吞吐是 FP16 的兩倍:215.2T TensorOp,INT4 是 430.4T TensorOp。

正如前面介紹 RT Core 提到的那樣,凡是機器做的事情,必定是重複、耗時的,Turing 是主要針對遊戲市場的架構,引入 Tensor Core(張量內核) 顯然不是因為 Turing 晶體管用量嫌太少了隨便塞一些充數。

首先,在 Volta 發布一年多後,Tensor Core(張量內核) 目前已經獲得了業界的廣泛支持,包括 NVCaffe、Caffe2、MXNet、微軟 Cognitive Toolkit(CNTK)、PyTorch、TensorFlow 以及 Theano 等目前重要的深度學習框架,只要設定了以 16 位精度存儲的話,Tensor Core(張量內核) 就會自動開啟(…Torch 這傢伙怎麼還沒支持 Tensor Core 呢)。

然後,NVIDIA 推出了名為 NGX(神經圖形加速)的 API,它提供了多個深度學習功能供遊戲和應用程序使用,這些功能都是經過 NVIDIA 預訓練的。

比較特別的是這個框架要求 GPU 必須是 Turing 起步,連 Volta 都不支持,這是 NGX 因為用到了 Turing Tensor Core 新引入的 INT8、INT4 加速做深度推理加速。

NGX 是透過 GFE(GeForce Experence)和 QXP(Qaudro Experence) 來管理的,當 GFE 或者 QXP 偵測到當前系統有基於 Turing 的 GPU 後,就會下載安裝 NXP Core 功能包。

NXP Core 會偵測系統中的遊戲和應用程序 ID,將它們關聯到 NGX。不同的遊戲和應用會使用不同的深度神經網路(DNN)。

NGX DNN 可以和 CUDA 10、DirectX、Vulkan 驅動連接,利用 NVIDIA TensorRT 在深度推理上的低時延、高吞吐優勢,提供包括遊戲渲染、視頻、圖片等應用的合成加速。

NGX 中一個和遊戲直接相關的功能叫 DLSS,它的名字是深度學習超取樣的英文首字母縮寫。

NVIDIA 使用自己的超級計算機以極高(64 倍於標準解析度)的解析度運行遊戲,得出數千張以黃金分方法渲染的畫面作為完美渲染品質的參考標準,然後使用 DLSS 神經網路將這些圖片和標準解析度畫面對比,讓 DLSS 生成一張畫面,再次與 64X 超取樣畫面對比,測量出其和 64x 超取樣畫面的區別,根據這些差別,透過反向傳播演算法調整其在神經網路中的權重。

經過多次重複迭代後,DLSS 就知道如何生成儘可能近似於 64X 超取樣的畫面。一旦人工智慧弄清楚後,修改畫面的規則就會透過驅動或者配置文件提供,Turing 的 Tensor Core(張量內核) 會運行這些代碼,嘗試修改畫面使其儘可能地近似於 64 倍超取樣的效果,而且還能避免使用著色器跑 TAA(時間域抗鋸齒)時會產生的模糊、斷裂、透明等問題。

DLSS 在玩家端都是先渲染一個「基本」畫面,然後由圖靈的 Tensor Core(張量內核) 做一個最佳的猜測,嘗試為這個畫面生成更高品質的畫面。

在標準模式或者說高性能 DLSS 下,」4K」 DLSS 畫面效果可以達到兩倍取樣 TAA 抗鋸齒的水平,而且性能高一倍。標準模式 DLSS 的「基本」畫面有可能是用低於最終輸出畫面解析度渲染的。

NVIDIA 還提供了 DLSS 的高畫質版:DLSS 2X。

在 DLSS 2X 模式下,DLSS 的輸入畫面是以最終輸出解析度渲染的,然後結合一個比標準 DLSS 更大的神經網路生成達到 64 倍超取樣級別的輸出畫面,這種效果對傳統渲染來說是根本不可能實時達成的。

另一個 NGX 提供的功能是 InPainting(畫面修復)。

InPainting 可以讓程序對現有的圖片進行內容清除,然後結合 NGX AI 演算法對清除的地方用基於計算機生成的畫面進行替換。

例如,InPainting 可以去掉風景照片中的電線,然後使用天空背景實現無縫的替換。

這有點類似於 PhotoShop 中的修補工具,但是修補工具是需要畫面中有能用於填補的內容纔行,如果沒優化好可能產生視覺上明顯的平鋪模式。

相比之下,NGX InPainting 是依賴於從一大堆真實世界的圖像進行訓練來填補畫面空隙,生成更具視覺意義的圖片(見上圖)。

此外,NGX 還提供了 AI Slow-Mo 以及 AI Super Rez 兩種功能,前者是基於人工智慧的慢鏡,對現有視頻插幀生成平滑無失真的慢鏡,後者是基於人工智慧生成兩倍、四倍、八倍的超解析度畫面,能以實時(大約 30fps)的速度實現 1080p 到 4K 的放大處理,其生成畫面的質量(PSNR)要比採用傳統雙三次濾波高一到兩個分貝。

效率制勝:圖靈內存子系統

圖靈 SM 的內存子系統有 16 個 load/store 單元(LSU),每個 LSU 可以每個週期實現 32 位數據的存取,合共每週期 64 位元組的帶寬,從這個理論值來看,圖靈 SM 的存取帶寬要比 Pascal 和 Volta 低 50%。

在圖靈架構中,每個 TPC 包含有兩個 SM;

而在 GP102 中,每個 TPC 只有一個 SM,因此圖靈每個 TPC 的 LSU 數量和 GP102 一樣都是 16 個。

圖靈 SM 的 L1 紋理、數據 Cache 和 Sharedmemory 採用一體式可配置結構,L1 和 SMEM 可以共享每個週期 64 位元組帶寬的 LSU 通道,在 TPC 維度看來,就是每個 TPC 128 位元組每週期。

相比之下,GP102 SM(TPC) L1 和 SMEM 是獨立的各 64 位元組每週期。

因此,從 TPC 的維度看,圖靈 TPC 的 L1 Cache 帶寬是 GP102 的兩倍。

TU104 的 L2 Cache 是 6 MiB,是 GP102 3 MiB 的兩倍,帶寬也顯著增加,更大的 L2 Cache 有助於提高隨機存取的命中率,更快的 L2 Cache 能提升運算單元的效率。

完整的 TU102 有 6 個 64 位 DDR6 內存通道,合共 384 位內存匯流排,速率為 14GT/s,這個速率是 GDDR5X 的 1.27 倍左右。

每個內存通道都和 16 個 ROP(光柵操作處理器)單元綁定在一起,因此完整的 TU102 有 96 個 ROP。

基於 TU102 的 GeForce RTX 2080 Ti 的內存匯流排是 354 位,縮減了一個內存通道,但是內存帶寬依然高達 616 GiB/s,比 GeForce GTX 1080 Ti 高 27.2%。

除了內存帶寬提升外,新的 GDDR6 內存也比 GDDR5X 省電 20%。

現在的 NVIDIA GPU 集成了一個內存壓縮引擎,根據畫面特徵偵測結果使用不同的無損壓縮演算法,降低幀緩存寫入壓力、減少內存、L2 Cache 以及紋理等用戶單元的數據傳輸量。

Turing 的內存壓縮引擎在 Pascal 的基礎上作了進一步改善,能在遊戲中達到比 Pascal 高 50% 的有效帶寬提升。

看到這裡的讀者,我們要向你說一聲抱歉,由於字數的原因,知乎無法刊發所有原文。但文章還有一部分沒有刊登上面,小夥伴們可以點擊這個鏈接繼續閱讀。

此處鏈接是繼續連著文章的頁數,感謝大家的支持!

追光者 NVIDIA GeForce RTX 2080 Ti圖靈架構淺析


推薦閱讀:
查看原文 >>
相關文章