2013-03-04 37 views
1

輸出錯誤時告訴我的電腦用C(INT)-1的CUDA內核的printf給人以%d符

printf("%d",(int)-1); 

我也想到,通常可以得到,同樣,一個 '-1' 的迴應。然而,在我的Tesla M2090 NVIDIA顯卡從我的基於Ubuntu的Cuda的5.0這個無辜的演示程序

/** cheese.cu */ 
#include <iostream> 
#include <cuda.h> 
#include <cstdio> 

using namespace std; 

template<typename T> struct SpacePtr 
    { size_t size; T* ptr; }; 

__global__ void f(SpacePtr<int>* sp) 
{ 
    printf("This _is_ a 'minus one' or ain't it: %d\n",(int)-1); 
    // Note: All appears to work fine with %lu instead of %zd 
    // Still: How does the size value affect the -1? 
    printf("On DEV: Size: %zd, Minus One: %d\n",sp->size,(int)-1); 
} 

int main() 
{ 
    SpacePtr<int> data; data.ptr = 0; data.size = 168; 
    SpacePtr<int>* devPtr = 0; 
    cudaMalloc(&devPtr,1); 
    cudaMemcpy(devPtr,&data,sizeof(SpacePtr<int>),cudaMemcpyHostToDevice); 
    f<<<1,1,0,0>>>(devPtr); 
    cudaError_t err = cudaGetLastError(); 
    cout << "The last error code was " << err << " (" << 
    cudaGetErrorString(err) << ")" << endl; 
    cudaDeviceSynchronize(); 
} 

編譯並通過

nvcc -arch=sm_20 cheese.cu && ./a.out 

稱爲談過產生的輸出:

The last error code was 0 (no error) 
This _is_ a 'minus one' or ain't it: -1 
On DEV: Size: 168, Minus One: 10005640 

最後一個數字實際上是某種隨機數(兩個子查詢返回不同的結果),就好像內存分配有什麼不對。 -1之前的(int)已經是試錯了。原來的程序沒有它。

這裏是問題:有沒有人看,爲什麼-1不寫,如果是這樣,請你告訴我,爲什麼?非常感謝,Markus。

+0

唯一可能的不確定的行爲可能是內存分配。如果不。不要忘記重新編譯代碼然後執行。我猜:)對於'printf(「%d」,(int)-1)defiantly沒有問題;' – 2013-03-04 09:51:08

+0

這是我自己的問題的更新:如果我使用「%lu」作爲size_t和「 %d「爲臭名昭着的」-1「。所以可能與設備出於某種原因需要C90風格%lu有關。仍然:在內核代碼%zd和%d之外工作正常。我保持開放的問題,我仍然沒有看到一個大小值錯誤的格式化程序如何破壞-1的格式。 – 2013-03-04 10:02:11

回答

4

如果您查看CUDA C編程指南的appendix B.16.1 "Format Specifiers",您會發現不支持%zd中的z修飾符。你將不得不轉換爲unsigned long並使用%lu作爲格式說明:因爲`SP-> size`的

printf("On DEV: Size: %lu, Minus One: %d\n",(unsigned long)(sp->size), (int)-1); 
+0

我想這就是打印文檔所得到的結果,因此在你的文檔中有一個過時的變化...你的回答恢復了我的信念,沒有在CUDA中發現錯誤,從而保留了我對整個事物的信心!非常感謝! :-) – 2013-03-04 10:17:20

2

基本的問題似乎是設備printf不支持%zd格式說明符(我不確定,不管我的頭頂是否支持)。

編輯:

在CUDA 5 printf的文檔說這樣的:

至於標準printf()的,格式說明採取的形式: %[標誌] [寬度] [精度] [大小]類型

以下字段支持(見廣泛使用的文檔 對於所有行爲的完整描述):

Flags: ‘#’ ‘ ‘ ‘0’ ‘+’ ‘-‘ 
Width: ‘*’ ‘0-9’ 
Precision: ‘0-9’ 
Size: ‘h’ ‘l’ ‘ll’ 
Type: ‘%cdiouxXpeEfgGaAs’ 

請注意,CUDA的printf()將接受標誌,寬度,精度,尺寸和類型的任意組合,不管它們是否總體上形成有效的 格式說明符。換言之,「%hd」將被接受,並且printf 將在參數列表中的相應位置 期望雙精度變量。

因此不支持%zd格式說明符size_t。像這樣修改你的內核:

__global__ void f(SpacePtr<int>* sp) 
{ 
    const int minus_one = -1; 
    printf("This _is_ a 'minus one' or ain't it: %d\n", minus_one); 
    printf("On DEV: Size: %d, Minus One: %d\n",int(sp->size), minus_one); 
} 

工作正常。

還要注意你在你的主機代碼有一個非常重大的失誤,雖然這不會對你的榜樣清單的行爲沒有任何影響。你只是分配和複製一個字節爲dev_ptr這顯然是不正確的。它應該是這個樣子:

cudaMalloc((void **)&devPtr, sizeof(data)); 
cudaMemcpy(devPtr, &data, sizeof(data), cudaMemcpyHostToDevice); 

從主機數據的全部內容傳送到設備。

+0

回答:也謝謝你。顯然我應該更新我的文檔。我使用Cuda 4.0手冊。內存分配:Eeek。是。在我的主程序中,我從這個黑客入侵這個演示是正確的! ;-) – 2013-03-04 10:18:51