天天看點

CUDA學習(七十八)

5.擴充的lambda不能在函數本地的類中定義。 例:

6.擴充lambda的封閉函數不能推導出傳回類型。 例:

7.<code>__host__</code> <code>__device__</code>擴充lambdas不能是通用lambdas。例:

8.如果封閉函數是函數模闆或成員函數模闆的執行個體,并且/或者函數是類模闆的成員,則模闆必須滿足以下限制條件:

該模闆必須至多有一個可變參數,并且必須在模闆參數清單中最後列出。

模闆參數必須命名。

模闆執行個體化參數類型不能涉及函數本地的類型(擴充lambdas的閉包類型除外),或者是私有或受保護的類成員。

例子:

9.使用Visual Studio 2013及更高版本的Visual Studio主機編譯器時,封閉函數必須具有外部連結。 限制是存在的,因為該主機編譯器不支援将非外部連結函數的位址用作模闆參數,這是CUDA編譯器轉換所需的,以支援擴充lambda表達式。

10.擴充lambda對捕獲的變量有以下限制:

變量隻能通過值來捕獲。

數組類型的變量不能被捕獲。

無法捕獲作為可變參數包的元素的函數參數。

捕獲的變量的類型不能涉及函數本地的類型(除了擴充lambdas的閉包類型),或者是私有類或受保護的類成員。

對于<code>__host__</code> <code>__device__</code>擴充lambda,在lambda表達式的operator()的return或參數類型中使用的類型不能涉及函數本地的類型(除了擴充lambdas的閉包類型),或者是私有或受保護的類成員。

<code>__host__</code> <code>__device__</code>擴充lambdas不支援初始捕獲。 initcapture支援<code>__device__</code>擴充lambda表達式,除非initcapture類型為std :: initializer_list。

11.解析函數時,CUDA編譯器為該函數中的每個擴充lambda配置設定一個計數器值。 該計數器值用于傳遞給主機編譯器的替換命名類型。 是以,函數中是否定義了擴充lambda是不應該依賴于<code>__CUDA_ARCH__</code>的特定值,或者是<code>__CUDA_ARCH__</code>未定義。

12.如上所述,CUDA編譯器用命名空間範圍中定義的占位符類型替換主機函數中定義的<code>__device__</code>擴充lambda。 此占位符類型未定義與原始lambda聲明等效的operator()函數。 由于主機編譯器處理的代碼與CUDA編譯器處理的輸入代碼在語義上不同,是以嘗試确定operator()函數的傳回類型或參數類型可能會在主機代碼中錯誤地工作。 但是,可以在裝置代碼中檢討operator()函數的傳回類型或參數類型。 請注意,此限制不适用于<code>__host__</code> <code>__device__</code>擴充lambdas。

13.如果由擴充lambda表示的函子對象從主機傳遞到裝置代碼(例如,作為<code>__global__</code>函數的參數),則表達式捕獲變量的lambda表達式的任何表達式都必須保持不變,而不管<code>__CUDA_ARCH__</code> 宏定義,宏是否有特定的值。 這種限制的出現是因為lambda的閉包類布局取決于編譯器在處理lambda表達式時遇到的捕獲變量的順序; 如果封裝類布局在裝置和主機編譯中不同,程式可能會錯誤地執行。

如前所述,CUDA編譯器用發送到主機編譯器的代碼中的占位符類型執行個體替換擴充的__device__ lambda表達式。 此占位符類型未在主機代碼中定義指針函數轉換運算符,但轉換運算符在裝置代碼中提供。 請注意,此限制不适用于__host__ __device__擴充lambdas。

CUDA編譯器将為1-10中描述的一些情況生成編譯器診斷; 對于情況11-14,将不會生成診斷資訊,但主機編譯器可能無法編譯生成的代碼。

CUDA學習(七十八)

繼續閱讀