我在我的cuda程序中添加了一些printf语句
__device__ __global__ void Kernel(float *, float * ,int );
void DeviceFunc(float *temp_h , int numvar , float *temp1_h)
{ .....
//Kernel call
printf("calling kernel\n");
Kernel<<<dimGrid , dimBlock>>>(a_d , b_d , numvar);
printf("kernel called\n");
....
}
int main(int argc , char **argv)
{ ....
printf("beforeDeviceFunc\n\n");
DeviceFunc(a_h , numvar , b_h); //Showing the data
printf("after DeviceFunc\n\n");
....
}
同样在Kernel.cu中,我写道:
#include<cuda.h>
#include <stdio.h>
__device__ __global__ void Kernel(float *a_d , float *b_d ,int size)
{
int idx = threadIdx.x ;
int idy = threadIdx.y ;
//Allocating memory in the share memory of the device
__shared__ float temp[16][16];
//Copying the data to the shared memory
temp[idy][idx] = a_d[(idy * (size+1)) + idx] ;
printf("idx=%d, idy=%d, size=%d", idx, idy, size);
....
}
然后我使用-arch=sm_20
进行编译,如下所示:
nvcc -c -arch sm_20 main.cu
nvcc -c -arch sm_20 Kernel.cu
nvcc -arch sm_20 main.o Kernel.o -o main
现在,当我运行该程序时,我看到了:
beforeDeviceFunc
calling kernel
kernel called
after DeviceFunc
因此不打印内核中的printf。我该如何解决这个问题?
答案 0 :(得分:8)
printf()
输出,因此请检查所有CUDA函数调用的返回代码,并确保没有报告错误。
此外printf()
输出仅显示在程序的某些位置。 Appendix B.20.2 of the Programming Guide将这些列为
<<<>>>
或cuLaunchKernel()
启动内核(在启动时,如果CUDA_LAUNCH_BLOCKING环境变量设置为1,则在启动结束时),cudaDeviceSynchronize()
,cuCtxSynchronize()
,cudaStreamSynchronize()
,cuStreamSynchronize()
,cudaEventSynchronize()
或cuEventSynchronize()
进行同步,cudaMemcpy*()
或cuMemcpy*()
,cuModuleLoad()
或cuModuleUnload()
,cudaDeviceReset()
或cuCtxDestroy()
进行上下文销毁。cudaStreamAddCallback()
或cuStreamAddCallback()
添加的流回调之前。要轻松检查这是您的问题,请在内核调用后输入以下代码:
{
cudaError_t cudaerr = cudaDeviceSynchronize();
if (cudaerr != cudaSuccess)
printf("kernel launch failed with error \"%s\".\n",
cudaGetErrorString(cudaerr));
}
然后,您应该看到内核的输出或错误消息。
答案 1 :(得分:0)
我刚才遇到了同样的错误,将块大小减少到 512 有所帮助。根据文档,最大块大小可以是 512 或 1024。
我编写了一个简单的测试,显示我的 GTX 1070 的最大块大小为 1024。 UPD:您可以使用 cudaError_t cudaPeekAtLastError() 检查您的内核是否曾经执行过,如果内核已成功启动,则返回 cudaSuccess,并且只有在调用 cudaError_t cudaDeviceSynchronize() 之后才会更糟。
测试块大小为 1023
测试块大小为 1024
测试块大小为 1025
CUDA 错误:无效的配置参数
块最大大小为 1024
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
__global__
void set1(int* t)
{
t[threadIdx.x] = 1;
}
inline bool failed(cudaError_t error)
{
if (cudaSuccess == error)
return false;
fprintf(stderr, "CUDA error: %s\n", cudaGetErrorString(error));
return true;
}
int main()
{
int blockSize;
for (blockSize = 1; blockSize < 1 << 12; blockSize++)
{
printf("Testing block size of %d\n", blockSize);
int* t;
if(failed(cudaMallocManaged(&t, blockSize * sizeof(int))))
{
failed(cudaFree(t));
break;
}
for (int i = 0; i < blockSize; i++)
t[0] = 0;
set1 <<<1, blockSize>>> (t);
if (failed(cudaPeekAtLastError()))
{
failed(cudaFree(t));
break;
}
if (failed(cudaDeviceSynchronize()))
{
failed(cudaFree(t));
break;
}
bool hasError = false;
for (int i = 0; i < blockSize; i++)
if (1 != t[i])
{
printf("CUDA error: t[%d] = %d but not 1\n", i, t[i]);
hasError = true;
break;
}
if (hasError)
{
failed(cudaFree(t));
break;
}
failed(cudaFree(t));
}
blockSize--;
if(blockSize <= 0)
{
printf("CUDA error: block size cannot be 0\n");
return 1;
}
printf("Block maximum size is %d", blockSize);
return 0;
}
附言请注意,块大小中唯一的东西是扭曲粒度,现在是 32,所以如果 0 == yourBlockSize % 32 则扭曲被非常有效地使用。使块大于 32 的唯一原因是当代码需要同步时,因为同步仅在单个块中的线程之间可用,这使得开发人员使用单个大块而不是许多小块。因此,运行更多的小块比运行更少的大块更有效。