1

私のコンピューターにCで話すとき

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

私は期待しており、通常は「-1」の応答も受け取ります。しかし、私のUbuntuベースのCuda5.0から話された私のTeslaM2090 Nvidiaカードでは、この無実のデモプログラム

/** 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

最後の数値は、実際にはある種の乱数であり(2つの後続の呼び出しは異なる結果を返します)、メモリ割り当てで何かが間違っているかのようになります。-1の前の(int)は、すでに試行錯誤です。元のプログラムにはありませんでした。

そして、ここに質問があります:誰かが、なぜ-1が書かれていないのかわかりますか?もしそうなら、その理由を教えてください。どうもありがとう、マーカス。

4

2 に答える 2

6

CUDA Cプログラミングガイドの付録B.32.1「フォーマット指定子」をチェックすると、のz修飾子%zdがサポートされていないことがわかります。フォーマット指定子にキャストしunsigned longて使用する必要があります。%lu

printf("On DEV: Size: %lu, Minus One: %d\n",(unsigned long)(sp->size), (int)-1);
于 2013-03-04T10:04:31.240 に答える
2

基本的な問題は、%zdフォーマット指定子がデバイスprintfによって尊重されていないことのようです(サポートされているかどうかはわかりません)。

編集:

CUDA 5のprintfのドキュメントには、次のように書かれています。

標準のprintf()の場合、フォーマット指定子は次の形式を取ります:%[flags][width][。precision][size]type

次のフィールドがサポートされています(すべての動作の完全な説明については、広く利用可能なドキュメントを参照してください)。

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明らかに正しくない1バイトを割り当ててコピーしているだけです。次のようになります。

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

データの全内容をホストからデバイスに転送します。

于 2013-03-04T10:04:20.623 に答える