關於__host__
__device__
lambdas的說明:
與__device__ lambdas
不同,可以從主機**呼叫__host__
__device__
lambdas。 如前所述,cuda編譯器用乙個已命名的佔位符型別的例項替換主機**中定義的擴充套件lambda表示式。 擴充套件__host__
__device__
lambda的佔位符型別通過間接函式呼叫呼叫orignal lambda的operator()。
間接函式呼叫的存在可能會導致擴充套件的__host__
__device__
lambda被主機編譯器優化得比只隱式或明確__host__
的lambda更優化。 在後一種情況下,主機編譯器可以輕鬆地將lambda的主體內聯到呼叫上下文中。 但是如果擴充套件了__host__
__device__
lambda,主機編譯器會遇到間接函式呼叫,並且可能無法輕鬆內聯原始__host__
__device__
lambda主體。
*this capture by value:
當在非靜態類成員函式中定義lambda時,並且lambda的主體引用類成員變數時,c ++ 11 / c ++ 14規則要求該類的該指標由值捕獲, 而不是被引用的成員變數。 如果lambda是在主機函式中定義的擴充套件的__device__
或__host__
__device__
lambda,並且在gpu上執行lambda,則如果此指標指向主機記憶體,則在gpu上訪問引用的成員變數將導致執行時錯誤.
例子:
#include template __global__ void foo(t in)
struct s1_t ;
void doit(void) ;
// kernel launch fails at run time because 'this->***'
// is not accessible from the gpu
foo << <1, 1 >> >(lam1);
cudadevicesynchronize();
}};int main(void)
c ++ 17通過新增新的「this」捕獲模式解決了這個問題。 在這種模式下,編譯器複製由「 this」表示的物件,而不是按值捕獲指標。 下面詳細描述「* this」捕捉模式:
當使用--expt-extended-lambda nvcc標誌時,cuda編譯器支援在__device__
和__global__
函式中定義的lambda以及在主機**中定義的擴充套件__device__
lambda的「* this」捕獲模式。
上面的示例修改為使用「* this」捕獲模式:
#include template __global__ void foo(t in)
struct s1_t ;
void doit(void) ;
// kernel launch succeeds
foo << <1, 1 >> >(lam1);
cudadevicesynchronize();
}};int main(void)
「*this」捕獲模式不允許用於在主機**中定義的未注釋的lambdas或擴充套件的__host__devicelambdas。 支援和不支援的用法示例:
struct s1_t ;
void host_func(void) ;
// error: use in an extended __host__ __device__ lambda
auto lam2 = [=, *this] __host__ __device__;
// error: use in an unannotated lambda in host function
auto lam3 = [=, *this];
}__device__ void device_func(void) ;
// ok: use in a lambda defined in a __device__ function
auto lam2 = [=, *this] __host__ __device__;
// ok: use in a lambda defined in a __device__ function
auto lam3 = [=, *this];
}__host__ __device__ void host_device_func(void) ;
// error: use in an extended __host__ __device__ lambda
auto lam2 = [=, *this] __host__ __device__;
// error: use in an unannotated lambda in a __host__ __device__ function
auto lam3 = [=, *this];}};
補充筆記:
adl lookup:如前所述,在呼叫主機編譯器之前,cuda編譯器將用佔位符型別的例項替換擴充套件的lambda表示式。 佔位符型別的乙個模板引數使用包含原始lambda表示式的函式的位址。 對於引數型別涉及擴充套件lambda表示式的閉包型別的任何主機函式呼叫,這可能會導致其他命名空間參與引數相關查詢(adl)。 這可能會導致主機編譯器選擇錯誤的功能。
例子:
namespace n1 ;
template void foo(t);
};namespace n2
}void bar(n1::s1_t in)
; n2::doit(lam1);
}
在上面的例子中,cuda編譯器用包含n1命名空間的佔位符型別替換了擴充套件lambda。 因此,命名空間n1參與了n2 :: doit主體中的foo(in)的adl查詢,並且主機編譯失敗,因為找到了多個過載候選n1 :: foo和n2 :: foo。
六十九到七十九題
第六十九題 鍵盤輸入乙個字串 長度不超過20,其中不含空格 將其複製乙份,複製時將小寫字母都轉換成為大寫字母。include void main 第七十題 從乙個三行四列的整型二維陣列中查詢第乙個出現的負數。include int main if flag printf 該陣列中沒有負數!n 第七十...
Spark七十九 Spark RDD API一
package spark.examples.rddapi import org.apache.spark.測試rdd的aggregate方法 object aggregatetest package spark.examples.rddapi import org.apache.spark.rdd...
第七十九題合集 微軟面試100題 第七十九題
題目要求 問題 編寫實現鍊錶排序的一種演算法。問題 編寫實現陣列排序的一種演算法。問題 編寫能直接實現strstr 功能的 問題分析 問題1分析 方法1 首先想到的是氣泡排序,因為簡單 方法2 如果記憶體空間允許,可以通過乙個陣列來輔助排序,時間複雜度o nlogn 但是需要耗費空間複雜度.具體如下...