簡體   English   中英

CUDA,使用2D和3D陣列

[英]CUDA, Using 2D and 3D Arrays

在線上有很多關於在CUDA上分配,復制,索引等2d和3d數組的問題。 我得到了很多矛盾的答案,所以我試圖匯編過去的問題,看看是否可以提出正確的問題。

第一個鏈接: https : //devtalk.nvidia.com/default/topic/392370/how-to-cudamalloc-two-Dimension-array-/

問題:分配二維指針數組

用戶解決方案:使用mallocPitch

“正確”的低效率解決方案:在for循環中為每行使用malloc和memcpy(荒謬的開銷)

“更正確”的解決方案:將其壓縮為1d數組的“專業意見”,有評論說沒有人關注性能,但在gpu上使用2d指針結構

第二個鏈接: https : //devtalk.nvidia.com/default/topic/413905/passing-a-multiDimension-array-to-kernel-how-to-allocate-space-in-host-and-pass-to-device -/

問題:在主機上分配空間並將其傳遞給設備

子鏈接: https : //devtalk.nvidia.com/default/topic/398305/cuda-programming-and-performance/dynamically-allocate-array-of-structs/

子鏈接解決方案:在GPU上編碼基於指針的結構是一種糟糕的體驗,並且效率極低,因此將其壓縮為一維數組。

第三個鏈接: 在CUDA中的設備內存上分配2D陣列

問題:分配和傳輸二維數組

用戶解決方案:使用mallocPitch

其他解決方案:將其展平

第四個鏈接: 如何在CUDA中使用2D陣列?

問題:分配和遍歷二維數組

提交的解決方案:不顯示分配

其他解決方案:壓扁

還有許多其他消息來源大多在說同樣的話,但是在多個實例中,我看到有關GPU上指針結構的警告。

許多人認為分配指針數組的正確方法是為每行調用malloc和memcpy,但函數mallocPitch和memcpy2D存在。 這些功能的效率有所降低嗎? 為什么這不是默認答案?

二維數組的另一個“正確”答案是將它們壓縮成一個數組。 我是否應該習慣生活中的事實? 我對我的代碼非常拘謹,對我來說感覺很不雅。

我正在考慮的另一種解決方案是使使用1d指針數組的矩陣類最大化,但是我找不到實現雙括號運算符的方法。

還要根據此鏈接: 將對象復制到設備?

和子鏈接答案: cudaMemcpy分段錯誤

這有點浮躁。

我想全部使用CUDA的類都具有2 / 3d數組,將這些轉換為CUDA的1d數組會不會有很多開銷?

我知道我已經問了很多問題,但總的來說,我應該習慣於將數組壓縮為現實,還是可以使用2d分配和復制函數而不會產生不好的開銷,例如在for中調用alloc和cpy的解決方案中環?

由於您的問題會匯編其他問題的列表,因此我將通過匯編其他答案的列表進行回答。

cudaMallocPitch / cudaMemcpy2D:

首先,諸如cudaMallocPitchcudaMemcpy2D類的cuda運行時API函數實際上並不涉及雙指針分配或2D(雙下標)數組。 只需查看文檔 ,並注意函數原型中的參數類型,即可輕松確認。 srcdst參數是單指針參數。 它們不能加倍下標或加倍取消引用。 對於其他示例用法, 是與此有關的許多問題之一。 是一個完整的示例用法。 覆蓋與相關聯的各種構思的另一示例cudaMallocPitch / cudaMemcpy2d用法是這里 相反,想想這些正確的做法是,他們與分配工作。 另外,在循環中使用一組malloc (或new或類似的操作)創建了基礎分配時,也不能使用cudaMemcpy2D傳輸數據。 這種主機數據分配結構特別不適用於處理設備上的數據。

一般情況下,動態分配的2D情況:

如果您想學習如何在CUDA內核中使用動態分配的2D數組(這意味着您可以使用雙下標訪問方式,例如data[x][y] ),則cuda標簽信息頁面包含針對“ canonical”的問題這個,就在這里 那里的爪子給出的答案包括適當的機制以及適當的警告:

  • 還有其他的,非平凡的復雜性
  • 由於數據訪問需要解引用2個指針而不是1個指針,因此訪問通常不如1D訪問有效。

(請注意,分配對象數組(其中的對象具有指向動態分配的嵌入式指針)在本質上與2D數組概念相同,並且您在問題中鏈接的示例對此進行了合理的演示)

展平:

如果您認為必須使用常規的2D方法,那么就可以做到這一點(盡管有時人們會為該過程而苦惱!)但是,由於增加了復雜性並降低了效率,此處的典型“建議”是“扁平化”您的存儲方法,並使用“模擬” 2D訪問。 是討論“展平”的問題/答案的眾多示例之一。

動態分配的一般3D情況:

當我們將其擴展到3個(或更高!)尺寸時,IMO的一般情況變得過於復雜。 額外的復雜性應強烈激勵我們尋求替代方案。 三次下標的一般情況涉及在實際檢索數據之前進行3次指針訪問,因此效率更低。 是一個完整的示例(第二個代碼示例)。

特殊情況:編譯時已知的數組寬度:

請注意,當在編譯時知道數組尺寸( 寬度 ,對於2D數組,或3D數組的3個尺寸中的2個)時,應將其視為特殊情況 在這種情況下,使用適當的輔助類型定義,我們可以“指示”編譯器應如何計算索引,並且在這種情況下,我們可以使用雙標訪問方式,而復雜度要比一般情況低得多, 並且不會造成任何損失指針追逐帶來的效率提升。 僅需要取消引用一個指針即可檢索數據(與數組維數無關,如果在編譯時已知n維數組的n-1維,則不考慮數組維數)。 這里已經提到的答案中的第一個代碼示例(第一個代碼示例)給出了3D情況下的完整示例,而這里的答案給出了這種特殊情況的2D示例。

雙下標主機代碼,單下標設備代碼:

最后,另一種方法選擇允許我們輕松地在主機代碼中混合使用2D(雙下標)訪問,而在設備代碼中僅使用1D(單下標,可能帶有“模擬2D”訪問)。 一個可行的例子在這里 通過將基礎分配組織為連續分配,然后構建指針“樹”,我們可以在主機上啟用雙下標訪問,並且仍然可以輕松地將平面分配傳遞給設備。 盡管該示例未顯示,但是可以擴展此方法以基於平面分配和手動創建的指針“樹”在設備上創建雙下標訪問系統,但是這將具有大致相同的問題如上面給出的2D一般動態分配方法:它將涉及雙指針(雙引用)訪問,因此效率較低,並且與在設備代碼中使用的構建指針“樹”相關聯,存在一些復雜性(例如,可能需要額外的cudaMemcpy操作)。

從以上方法中,您需要選擇一種適合您的胃口和需求的方法。 沒有一個適合所有可能情況的建議。

暫無
暫無

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

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