[英]some mathematical operations in CUDA
我有一個包含0,1和2的2D矩陣。我正在編寫一個cuda內核,其中線程數等於矩陣大小,每個線程將對矩陣的每個元素進行操作。 現在,我需要可以保持0和1的數學運算,但是將2轉換為1.這是一個數學運算,沒有任何if-else,它將執行以下轉換:0 - > 0; 1 - > 1; 2 - > 1。 是否有任何可能的方法使用數學運算符進行上述轉換。 任何幫助將非常感激。 謝謝。
這不是一個問題。
int A;
// set A to 0, 1, or 2
int a = (A + (A>>1)) & 1;
// a is now 0 if A is 0, or 1 if A is 1 or 2
或作為宏:
#define fix01(x) ((x+(x>>1))&1)
int a = fix01(A);
這似乎也有效:
#define fix01(x) ((x&&1)&1)
我不知道布爾AND運算符( &&
)的使用是否符合您對“數學運算”的定義。
由於問題是關於“數學”函數,我建議使用以下二階多項式:
int f(int x) { return ((3-x)*x)/2; }
但是如果你想避免分支以最大化速度:自PTX ISA 1.0以來有一條min指令。 (參見PTX ISA 3.1手冊中的表36)。所以下面的CUDA代碼
__global__ void test(int *x, int *y)
{
*y = *x <= 1 ? *x : 1;
}
在我的測試中編譯到下面的PTX匯編程序(剛從CUDA 5調用nvcc而沒有任何arch選項)
code for sm_10
Function : _Z4testPiS_
/*0000*/ /*0x1000c8010423c780*/ MOV R0, g [0x4];
/*0008*/ /*0xd00e000580c00780*/ GLD.U32 R1, global14 [R0];
/*0010*/ /*0x1000cc010423c780*/ MOV R0, g [0x6];
/*0018*/ /*0x30800205ac400780*/ IMIN.S32 R1, R1, c [0x1] [0x0];
/*0020*/ /*0xd00e0005a0c00781*/ GST.U32 global14 [R0], R1;
所以使用條件?的min()實現:實際上編譯為單個IMIN.S32 PTX指令而沒有任何分支。 因此,我建議將其用於任何實際應用:
int f(int x) { return x <= 1 ? x : 1; }
但回到僅使用非分支操作的問題:
在C中獲得此結果的另一種形式是使用兩個非運算符:
int f(int x) { return !!x; }
或者簡單地與零比較:
int f(int x) { return x != 0; }
(!和!=的結果保證為0或1,比較C.5標准的第6.5.3.3節第5節和第6.5.9節第3節,ISO / IEC 9899:1999。此保證也是在CUDA舉行。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.