2013-07-14 49 views
1

我有一個包含0,1和2的二維矩陣。我正在編寫一個cuda內核,其中線程的數量等於矩陣大小,每個線程將對矩陣的每個元素進行操作。現在,我需要可以保持0和1的數學運算,但會將2轉換爲1.這是一個數學運算,沒有任何if-else,它會進行以下轉換:0 - > 0; 1 - > 1; 2 - > 1。有沒有可能的方法使用數學運算符來完成上述轉換。任何幫助將不勝感激。謝謝。CUDA中的一些數學運算

回答

3

這不是一個cuda問題。

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運算符(&&)的適合你「數學運算」的定義。

+0

是的我知道,這是一個普遍的問題。我只是想標記,因爲我在cuda應用程序中使用它。我剛剛測試了表達式,並且在輸入2時它給出了0。我想要1代替0. – duttasankha

+0

我更正了你的表達式。在右移之後它會代替1 – duttasankha

+0

我無法編輯您的帖子。請編輯它,我會接受它作爲答案。非常感謝。你剛剛救了我。 – duttasankha

1

由於問題是關於「數學」的功能,我建議以下的2階多項式:

int f(int x) { return ((3-x)*x)/2; } 

但是如果你想避免以最大限度速度分支:有,因爲PTX ISA 1.0分鐘的指令。 (在PTX ISA 3.1手動見表36)。所以下面的CUDA代碼

__global__ void test(int *x, int *y) 
{ 
    *y = *x <= 1 ? *x : 1; 
} 

編譯以下PTX彙編程序在我的測試(只是叫NVCC從CUDA 5沒有任何拱選項)

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指令而沒有任何分支。通過使用兩個不

用C得到這個結果的另一種形式是:所以我建議這對任何現實世界的應用:

int f(int x) { return x <= 1 ? x : 1; } 

但這回只用非分支工作的問題運營商:

int f(int x) { return !!x; } 

或者乾脆比較爲零:

int f(int x) { return x != 0; } 

(的結果! nd!=保證是0或1,比較秒。 6.5.3.3參數5和Sec。 6.5.9 Par。 C99標準3,ISO/IEC 9899:1999。 Afair此保證也適用於CUDA。)