簡體   English   中英

什么是Vulkan的Queue家族?

[英]What is actually a Queue family in Vulkan?

我目前正在學習vulkan,現在我正在拆開每個命令並檢查結構以試圖理解它們的含義。

現在我正在分析QueueFamilies,我有以下代碼:

vector<vk::QueueFamilyProperties> queue_families = device.getQueueFamilyProperties();
for(auto &q_family : queue_families)
{
    cout << "Queue number: "  + to_string(q_family.queueCount) << endl;
    cout << "Queue flags: " + to_string(q_family.queueFlags) << endl;
}

這會產生以下輸出:

Queue number: 16
Queue flags: {Graphics | Compute | Transfer | SparseBinding}
Queue number: 1
Queue flags: {Transfer}
Queue number: 8
Queue flags: {Compute}

所以,天真地我這樣理解:

有3個Queue系列,一個隊列系列有16個隊列,都可以進行圖形,計算,傳輸和稀疏綁定操作(不知道后兩個是什么)

另一個有1個隊列,只能傳輸(無論是什么)

最后一個有8個隊列,可以進行計算操作。

每個隊列系列是什么? 我理解這是我們發送執行命令的地方,比如繪制和交換緩沖區,但這是一個有點廣泛的解釋,我想要更詳細的知識答案。

2個額外標志是什么? 轉移和SparseBidning?

最后,為什么我們需要/需要多個命令隊列?

要了解隊列系列,首先必須了解隊列。

隊列是您向命令緩沖區提交的,並且提交到隊列的命令緩沖區按順序[* 1]相對於彼此執行。 提交到不同隊列的命令緩沖區相對於彼此是無序的,除非您明確地將它們與VkSemaphore同步。 您只能一次從一個線程向隊列提交工作,但不同的線程可以同時向不同的隊列提交工作。

每個隊列只能執行某些類型的操作。 圖形隊列可以運行由vkCmdDraw*命令啟動的圖形管道。 計算隊列可以運行由vkCmdDispatch*啟動的計算管道。 傳輸隊列可以從vkCmdCopy*執行傳輸(復制)操作。 稀疏綁定隊列可以使用vkQueueBindSparse更改稀疏資源與內存的vkQueueBindSparse (請注意,這是直接提交給隊列的操作,而不是命令緩沖區中的命令)。 某些隊列可以執行多種操作。 在規范中,每個可以提交到隊列的命令都有一個“命令屬性”表,列出了可以執行命令的隊列類型。

隊列系列只描述了一組具有相同屬性的隊列。 因此,在您的示例中,設備支持三種隊列:

  • 一種可以執行圖形,計算,傳輸和稀疏綁定操作,並且您最多可以創建該類型的16個隊列。

  • 另一種只能進行傳輸操作,你只能創建一個這種隊列。 通常這是用於在離散GPU上的主機和設備存儲器之間異步DMA數據,因此可以與獨立的圖形/計算操作同時進行傳輸。

  • 最后,您最多可以創建8個只能進行計算操作的隊列。

某些隊列可能只對應於主機端調度程序中的單獨隊列,其他隊列可能對應於硬件中的實際獨立隊列。 例如,許多GPU只有一個硬件圖形隊列,因此即使您從具有圖形功能的隊列系列創建兩個VkQueue,提交給這些隊列的命令緩沖區也將獨立地通過內核驅動程序的命令緩沖區調度程序,但將以某些序列執行在GPU上訂購。 但是一些GPU具有多個僅計算硬件隊列,因此僅用於計算的隊列系列的兩個VkQueue實際上可以在GPU中一直獨立並同時進行。 Vulkan不公開這個。

最重要的是,根據您擁有的並發數量,確定可以有效使用的隊列數。 對於許多應用程序,只需要一個“通用”隊列。 更高級的可能有一個圖形+計算隊列,一個用於異步計算工作的單獨的僅計算隊列,以及用於異步DMA的傳輸隊列。 然后將你想要的東西映射到可用的東西上; 您可能需要進行自己的多路復用,例如,在沒有僅計算隊列系列的設備上,您可以創建多個圖形+計算隊列,或者自己將異步計算作業序列化到單個圖形+計算隊列中。

[* 1]過度簡化了一下。 它們按順序啟動 ,但允許在此之后獨立進行並完成故障。 但是不保證不同隊列的獨立進度。 對於這個問題我會留下它。

隊列是接受包含給定類型的操作的命令緩沖區(由系列標志給出)的東西。 提交給隊列的命令具有提交順序,因此它們受管道障礙,子通道依賴關系和事件的同步(跨隊列時必須使用信號量或beter)。

有一個技巧: COMPUTEGRAPHICS總是可以隱式接受TRANSFER工作負載(即使QueueFamilyProperties沒有列出它。請參閱下面的注釋VkQueueFlagBits規范 )。

傳輸用於復制和Blit命令。 稀疏就像分頁; 它允許將多個Memory句柄綁定到單個Image,並且它允許稍后重新綁定不同的內存。

在規范中,下面給出了vkCmd*命令,它總是說哪些是“支持的隊列類型”。

隊列族是一組與自己有特殊關系的隊列。 有些東西僅限於單個隊列系列,例如圖像(它們必須在隊列系列之間轉移)或命令池(僅為給定的隊列系列而不是其他隊列系列創建命令緩沖區)。 理論上,在一些奇特的設備上,可能會有更多具有相同標志的隊列系列。

這幾乎是Vulkan規范保證的一切。 請參閱KhronosGroup / Vulkan-Docs#569上的問題


提供了一些供應商特定的材料,例如:

GPU具有異步圖形引擎,計算引擎和復制\\ DMA引擎。 圖形和計算當然會與GPU的相同計算單元競爭。

它們通常只有一個圖形前端。 這是圖形操作的瓶頸,因此這意味着使用多個圖形隊列毫無意義。

Compute有兩種操作模式:Synchronous Compute(公開為GRAPHICS|COMPUTE系列)和Async Compute(公開為COMPUTE -only系列)。 首先是一個安全的選擇。 第二個可以給你大約10%的性能,但更棘手,需要更多的努力。 AMD文章建議始終將第一個作為基線。

理論上可以有與GPU上的計算單元一樣多的計算隊列。 但AMD認為,對兩個以上的異步計算隊列沒有任何好處,並且暴露了許多。 NVIDIA似乎全力以赴。

Copy \\ DMA Engines(作為TRANSFER -only系列公開)主要用於CPU⇄GPU傳輸。 它們通常無法實現內部GPU副本的完全吞吐量。 因此,除非有一些驅動程序魔法,否則異步傳輸系列應該用於CPU⇄GPU傳輸(以獲取Async屬性,能夠無阻礙地在其旁邊執行圖形)。 對於內部GPU副本,大多數情況下使用GRAPHICS|TRANSFER系列應該更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM