2013-05-13 67 views
0

我不明白我在CUDA内核中使用printf观察到的行为。 有人可以对此有所了解吗?如果这是正常的,为什么呢? 有没有办法确保我的printf数据之前它们在内核(调试)内被修改?CUDA:意想不到的printf行为

下面是代码:

~>more * 
:::::::::::::: 
Makefile 
:::::::::::::: 
all: 
    nvcc -o WTF.cu.o -arch=sm_21 -c WTF.cu 
    g++ -o WTF.exe -I/usr/local/cuda/include WTF.cpp WTF.cu.o -L/usr/local/cuda/lib64 -lcuda -lcudart 
:::::::::::::: 
WTF.cpp 
:::::::::::::: 
#include <iostream> // cout 
#include <cstdlib> // rand, srand 

#include <cuda_runtime_api.h> // cudaXXX 
void PrintOnGPU (unsigned int const iDataSize, int * const iopData); 

using namespace std; 

int main() 
{ 
    // Allocate and initialize CPU data 
    unsigned int dataSize = 4; 
    srand (time (NULL)); // Random seed 
    int * pCPUData = (int *) malloc (sizeof (int) * dataSize); 
    for (unsigned int i = 0; i < dataSize; i++) { pCPUData[i] = rand() % 100; cout << "CPU : " << pCPUData[i] << endl; } 

    // Print from GPU 
    int * pGPUData = NULL; 
    cudaMalloc ((void **) &pGPUData, dataSize * sizeof (int)); 
    cudaMemcpy (pGPUData, pCPUData, dataSize * sizeof (int), cudaMemcpyHostToDevice); 
    PrintOnGPU (dataSize, pGPUData); 

    // Get out 
    cudaFree (pGPUData); 
    if (pCPUData) { free (pCPUData); pCPUData = NULL; } 
    return 0; 
} 
:::::::::::::: 
WTF.cu 
:::::::::::::: 
#include "stdio.h" 

__global__ void WTF (unsigned int const iDataSize, int * const iopData) 
{ 
    if (iDataSize == 0 || !iopData) return; 

    // Don't modify : just print 
    unsigned long long int tIdx = blockIdx.x * blockDim.x + threadIdx.x; // 1D grid 
    if (tIdx == 0) 
    { 
    for (unsigned int i = 0; i < iDataSize; i++) 
     printf ("GPU : %i \n", iopData[i]); 
    } 
    __syncthreads(); 

    // Modify 
    // iopData[tIdx] = 666; // WTF ?... 
} 

void PrintOnGPU (unsigned int const iDataSize, int * const iopData) 
{ 
    WTF<<<2,2>>> (iDataSize, iopData); 
} 

而且,正如预期的,我没有得到任何值在100以上(在CPP文件中第15行:兰特()%100):

~>make; ./WTF.exe 
nvcc -o WTF.cu.o -arch=sm_21 -c WTF.cu 
g++ -o WTF.exe -I/usr/local/cuda/include WTF.cpp WTF.cu.o -L/usr/local/cuda/lib64 -lcuda -lcudart 
CPU : 38 
CPU : 73 
CPU : 28 
CPU : 82 
GPU : 38 
GPU : 73 
GPU : 28 
GPU : 82 

现在我在cu文件中取消注释第17行(iopData [tIdx] = 666):我将所有值修改为666(即100以上)。由于我在CUDA内核中有4个数据(dataSize = 4,在cpp文件中),一个2×2网格和一个__syncthreads(),所以我不应该打印任何修改过的数据,对不对?不过,我得到这个(打印修改的数据与值666):

~>make; ./WTF.exe 
nvcc -o WTF.cu.o -arch=sm_21 -c WTF.cu 
g++ -o WTF.exe -I/usr/local/cuda/include WTF.cpp WTF.cu.o -L/usr/local/cuda/lib64 -lcuda -lcudart 
CPU : 29 
CPU : 72 
CPU : 66 
CPU : 90 
GPU : 29 
GPU : 72 
GPU : 666 
GPU : 666 

我不明白为什么这些666显示:对我来说,他们不应该出现?!如果这种行为是正常的,那为什么呢?

FH

回答

2

这是因为你正在推出2个threadblocks,而那些threadblocks可以以任何顺序执行,同时或顺序

假设您有麻烦的行未注释。现在假设线程块1先运行并在线程块0之前完成。然后线程块0运行。但threadblock 0正在进行打印,并且它正在打印所有4个值。所以之前由线程块1设置为666的值是通过线程块0打印出来的。

如果线程块0先运行,则不会发生这种情况,相应地,我的猜测是,您从未看到列为666的前2个GPU值, 2(从线程块1发出)。不管线程的数量如何(至少在发布的内核代码中),如果您只启动1个块,您也永远不会看到它。

您也可能会觉得__syncthreads()是一个设备范围的同步时感到困惑。不是这样。它仅作为线程块中的线程的屏障。单独的线程块之间没有同步。

+0

谢谢,这对我有意义!我很高兴终于找到了一个逻辑!你是对的,只有最后2个值(与线程块1关联)被修改 – 2013-05-14 06:13:58