語言整合:
使用nvcc編譯主機代碼的CUDA Runtime API使用者可以通過<<< ... >>>運算符通路其他語言內建功能,例如共享符号名稱和内聯核心啟動。 Unified Memory為CUDA的語言內建增加了一個額外元素:用__managed__關鍵字注釋的變量可直接從主機和裝置代碼中引用。
以下簡化GPU程式設計的例子說明了__managed__全局聲明的一個簡單使用:
具有<code>__managed__</code>變量的可用功能是符号在裝置代碼和主機代碼中均可用,無需取消引用指針,資料由所有人共享。 這使得在主機和裝置程式之間交換資料變得特别容易,而不需要明确的配置設定或複制。
在語義上,<code>__managed__</code>變量的行為與通過cudaMallocManaged()配置設定的存儲的行為相同。 資料托管在實體GPU存儲中,并且系統中的所有GPU以及CPU都可以看到資料。 流可見性預設為cudaMemAttachGlobal,但可能會受到cudaStreamAttachMemAsync()的限制。
有效的CUDA上下文對于<code>__managed__</code>變量的正确操作是必需的。 如果尚未建立目前裝置的上下文,則通路<code>__managed__</code>變量可以觸發CUDA上下文建立。 在上面的示例中,在核心啟動之前通路x會觸發裝置0上的上下文建立。如果沒有該通路,核心啟動将觸發上下文建立。
聲明為<code>__managed__</code>的C ++對象受到某些特定的限制,特别是在涉及靜态初始化器的情況下。 請參閱CUDA C程式設計指南中的C / C ++語言支援以擷取這些限制的清單。
<code>__managed__</code>變量發生主機程式錯誤:
<code>__managed__</code>變量的使用取決于底層的統一記憶體系統是否正常運作。 例如,如果CUDA安裝失敗或CUDA上下文建立失敗,則可能會發生錯誤的功能。
當特定于CUDA的操作失敗時,通常會傳回一個錯誤,訓示失敗的來源。 如果統一記憶體系統運作不正常,則使用<code>__managed__</code>變量會引入一種新的失敗模式,即非CUDA操作(例如,CPU通路應該成為有效主機記憶體位址的内容)可能會失敗。 這種無效的記憶體通路不能輕易歸因于底層的CUDA子系統,盡管像cuda-gdb這樣的調試器會指出托管記憶體位址是失敗的根源。
查詢統一記憶體支援:
裝置屬性:
統一記憶體僅在計算能力為3.0或更高的裝置上受支援。 程式可以通過使用cudaGetDeviceProperties()查詢GPU裝置是否支援托管記憶體并檢查新的managedMemory屬性。 該功能還可以使用具有屬性cudaDevAttrManagedMemory的單個屬性查詢函數cudaDeviceGetAttribute()來确定。
如果在GPU上和目前作業系統下允許托管記憶體配置設定,則任一屬性都将設定為1。 請注意,即使GPU具有足夠的功能,32位應用程式也不支援統一記憶體(除非在Android上)。
支援平台上的計算能力6.x的裝置可以通路可分頁的記憶體,而無需在其上調用cudaHostRegister。 應用程式可以通過檢查新的pageableMemoryAccess屬性來查詢裝置是否支援連貫地通路可分頁記憶體。
使用新的頁面錯誤機制,全局資料一緻性通過統一記憶體得以保證。 這意味着CPU和GPU可以同時通路統一記憶體配置設定。 這在計算能力低于6.x的裝置上是非法的,因為如果CPU在GPU核心處于活動狀态時通路統一記憶體配置設定,則無法保證一緻性。 程式可以通過檢查concurrentManagedAccess屬性來查詢并發通路支援。
指針屬性:
要确定給定的指針是否引用托管記憶體,程式可以調用cudaPointerGetAttributes()并檢查isManaged屬性的值。 如果指針指向托管記憶體,則該屬性設定為1,否則設定為0。
緻敬冰蛙